From 08f913e81b56ffa474783cf279cabe5fc0756a4b Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:17:32 +0100 Subject: [PATCH] feat: use new Configuration Injection mechanism everywhere (#4633) * feat: use new Config injection mechanism everywhere * checkstyle * fix tests * pr remarks --- .../edc/boot/BootServicesExtension.java | 6 +- .../ConfigurationInjectionPoint.java | 5 +- .../InjectionPointDefaultServiceSupplier.java | 2 +- .../system/injection/ValueInjectionPoint.java | 8 +- .../core/CoreDefaultServicesExtension.java | 68 ++---------- .../core/base/OkHttpClientConfiguration.java | 31 +++++- .../core/base/RetryPolicyConfiguration.java | 37 +++++- .../core/base/OkHttpClientFactoryTest.java | 13 ++- ...eferenceStoreDefaultServicesExtension.java | 18 +-- ...enceStoreDefaultServicesExtensionTest.java | 31 +++--- .../DependencyInjectionExtension.java | 11 +- .../ControlPlaneServicesExtension.java | 2 +- .../contract/ContractCoreExtension.java | 51 ++++----- .../transfer/TransferCoreExtension.java | 29 +++-- .../selector/DataPlaneSelectorExtension.java | 21 ++-- .../DataPlaneFrameworkExtension.java | 42 ++++--- .../monitor/PolicyMonitorExtension.java | 12 +- .../DspApiConfigurationExtension.java | 11 +- .../DspApiConfigurationExtensionTest.java | 9 +- .../ControlApiConfigurationExtension.java | 8 +- .../ControlApiConfigurationExtensionTest.java | 19 ++-- .../ManagementApiConfigurationExtension.java | 16 +-- ...nagementApiConfigurationExtensionTest.java | 7 +- .../DelegatedAuthenticationExtension.java | 29 ++--- .../DelegatedAuthenticationExtensionTest.java | 14 ++- .../core/DcpDefaultServicesExtension.java | 24 ++-- .../core/IdentityAndTrustExtension.java | 40 +++---- .../core/DcpDefaultServicesExtensionTest.java | 14 ++- .../core/IdentityAndTrustExtensionTest.java | 30 ++--- .../sts/accounts/StsAccountsApiExtension.java | 9 +- .../accounts/StsAccountsApiExtensionTest.java | 17 ++- .../defaults/StsDefaultServicesExtension.java | 7 +- .../oauth2/Oauth2ServiceConfiguration.java | 38 ++++++- .../iam/oauth2/Oauth2ServiceExtension.java | 105 ++++++------------ .../oauth2/identity/Oauth2ServiceImpl.java | 11 +- .../oauth2/Oauth2ServiceExtensionTest.java | 15 +-- .../identity/Oauth2ServiceImplTest.java | 12 +- .../edc/iam/oauth2/daps/DapsExtension.java | 7 +- .../eclipse/edc/jsonld/JsonLdExtension.java | 28 ++--- .../edc/jsonld/JsonLdExtensionTest.java | 11 +- .../org/eclipse/edc/sql/SqlCoreExtension.java | 7 +- ...CommonsConnectionPoolServiceExtension.java | 22 ++-- ...pointDataReferenceEntryIndexExtension.java | 10 +- ...tDataReferenceEntryIndexExtensionTest.java | 4 - .../sql/SqlJtiValidationStoreExtension.java | 8 +- .../SqlJtiValidationStoreExtensionTest.java | 4 - .../sts/store/SqlStsClientStoreExtension.java | 5 +- .../SqlStsAccountStoreExtensionTest.java | 4 - .../hashicorp/HashicorpVaultExtension.java | 81 ++------------ .../client/HashicorpVaultClient.java | 15 ++- .../client/HashicorpVaultSettings.java | 30 ++++- .../health/HashicorpVaultHealthExtension.java | 10 +- .../HashicorpVaultExtensionTest.java | 32 ++++-- .../HashicorpVaultIntegrationTest.java | 32 +++--- .../client/HashicorpVaultSettingsTest.java | 19 +--- ...ntDataReferenceStoreReceiverExtension.java | 6 +- ...taReferenceStoreReceiverExtensionTest.java | 12 +- .../SqlAssetIndexServiceExtension.java | 7 +- .../SqlAssetIndexServiceExtensionTest.java | 4 - .../SqlContractDefinitionStoreExtension.java | 9 +- ...lContractDefinitionStoreExtensionTest.java | 4 - .../SqlContractNegotiationStoreExtension.java | 14 +-- ...ContractNegotiationStoreExtensionTest.java | 7 -- .../SqlPolicyStoreExtension.java | 12 +- ...SqlPolicyDefinitionStoreExtensionTest.java | 4 - .../SqlTransferProcessStoreExtension.java | 9 +- .../SqlTransferProcessStoreExtensionTest.java | 4 - .../TransferDataPlaneSignalingExtension.java | 5 +- ...ndpointDataReferenceReceiverExtension.java | 17 ++- .../DataPlaneSelectorClientExtension.java | 13 +-- .../DataPlaneSelectorClientExtensionTest.java | 13 ++- .../SqlDataPlaneInstanceStoreExtension.java | 10 +- ...qlDataPlaneInstanceStoreExtensionTest.java | 4 - .../http/DataPlaneHttpExtension.java | 7 +- .../DataPlaneIamDefaultServicesExtension.java | 11 +- .../kafka/DataPlaneKafkaExtension.java | 7 +- .../api/DataPlanePublicApiV2Extension.java | 27 ++--- .../DataplaneSelfRegistrationExtension.java | 7 +- ...ataplaneSelfRegistrationExtensionTest.java | 12 +- .../sql/SqlAccessTokenDataStoreExtension.java | 11 +- .../store/sql/SqlDataPlaneStoreExtension.java | 11 +- .../sql/SqlPolicyMonitorStoreExtension.java | 12 +- .../eclipse/edc/test/bom/BomSmokeTests.java | 3 + 83 files changed, 623 insertions(+), 790 deletions(-) diff --git a/core/common/boot/src/main/java/org/eclipse/edc/boot/BootServicesExtension.java b/core/common/boot/src/main/java/org/eclipse/edc/boot/BootServicesExtension.java index 30b7e395881..6962da7bb31 100644 --- a/core/common/boot/src/main/java/org/eclipse/edc/boot/BootServicesExtension.java +++ b/core/common/boot/src/main/java/org/eclipse/edc/boot/BootServicesExtension.java @@ -37,13 +37,13 @@ public class BootServicesExtension implements ServiceExtension { public static final String NAME = "Boot Services"; - @Setting(value = "Configures the participant id this runtime is operating on behalf of") + @Setting(description = "Configures the participant id this runtime is operating on behalf of") public static final String PARTICIPANT_ID = "edc.participant.id"; - @Setting(value = "Configures the runtime id. This should be fully or partly randomized, and need not be stable across restarts. It is recommended to leave this value blank.", defaultValue = "") + @Setting(description = "Configures the runtime id. This should be fully or partly randomized, and need not be stable across restarts. It is recommended to leave this value blank.", defaultValue = "") public static final String RUNTIME_ID = "edc.runtime.id"; - @Setting(value = "Configures this component's ID. This should be a unique, stable and deterministic identifier.", defaultValue = "") + @Setting(description = "Configures this component's ID. This should be a unique, stable and deterministic identifier.", defaultValue = "") public static final String COMPONENT_ID = "edc.component.id"; private HealthCheckServiceImpl healthCheckService; diff --git a/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ConfigurationInjectionPoint.java b/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ConfigurationInjectionPoint.java index f929e07342e..dcb0d6126fe 100644 --- a/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ConfigurationInjectionPoint.java +++ b/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ConfigurationInjectionPoint.java @@ -126,7 +126,7 @@ public Object resolve(ServiceExtensionContext context, DefaultServiceSupplier de } else { // all other classes MUST have a default constructor. try { - var pojoClass = Class.forName(configurationObject.getType().getName()); + var pojoClass = configurationObject.getType(); var defaultCtor = pojoClass.getDeclaredConstructor(); defaultCtor.setAccessible(true); var instance = defaultCtor.newInstance(); @@ -145,8 +145,7 @@ public Object resolve(ServiceExtensionContext context, DefaultServiceSupplier de return instance; } catch (NoSuchMethodException e) { throw new EdcInjectionException("Configuration objects must declare a default constructor, but '%s' does not.".formatted(configurationObject.getType())); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | - InvocationTargetException e) { + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { throw new EdcInjectionException(e); } } diff --git a/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionPointDefaultServiceSupplier.java b/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionPointDefaultServiceSupplier.java index 40d30ea38c9..5645c293038 100644 --- a/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionPointDefaultServiceSupplier.java +++ b/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/InjectionPointDefaultServiceSupplier.java @@ -29,7 +29,7 @@ public class InjectionPointDefaultServiceSupplier implements DefaultServiceSuppl public @Nullable Object provideFor(InjectionPoint injectionPoint, ServiceExtensionContext context) { var defaultService = injectionPoint.getDefaultValueProvider(); if (injectionPoint.isRequired() && defaultService == null) { - throw new EdcInjectionException("No default provider for required service " + injectionPoint.getType()); + throw new EdcInjectionException("No default provider for required injection point " + injectionPoint); } return ofNullable(defaultService).map(vp -> vp.get(context)).orElse(null); } diff --git a/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ValueInjectionPoint.java b/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ValueInjectionPoint.java index df7b151c187..c61e5b379fa 100644 --- a/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ValueInjectionPoint.java +++ b/core/common/boot/src/main/java/org/eclipse/edc/boot/system/injection/ValueInjectionPoint.java @@ -192,19 +192,19 @@ public String toString() { private Object parseEntry(String string, Class valueType) { try { - if (valueType == Long.class) { + if (valueType == Long.class || valueType == long.class) { return Long.parseLong(string); } - if (valueType == Integer.class) { + if (valueType == Integer.class || valueType == int.class) { return Integer.parseInt(string); } - if (valueType == Double.class) { + if (valueType == Double.class || valueType == double.class) { return Double.parseDouble(string); } } catch (NumberFormatException e) { throw new EdcInjectionException("Config field '%s' is of type '%s', but the value resolved from key '%s' is \"%s\" which cannot be interpreted as %s.".formatted(targetField.getName(), valueType, annotationValue.key(), string, valueType)); } - if (valueType == Boolean.class) { + if (valueType == Boolean.class || valueType == boolean.class) { return Boolean.parseBoolean(string); } diff --git a/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/CoreDefaultServicesExtension.java b/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/CoreDefaultServicesExtension.java index 1504f9d2b41..9b8b9df9e7a 100644 --- a/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/CoreDefaultServicesExtension.java +++ b/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/CoreDefaultServicesExtension.java @@ -27,10 +27,10 @@ import org.eclipse.edc.http.client.EdcHttpClientImpl; import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.participant.spi.ParticipantIdMapper; +import org.eclipse.edc.runtime.metamodel.annotation.Configuration; 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.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; @@ -49,52 +49,16 @@ public class CoreDefaultServicesExtension implements ServiceExtension { public static final String NAME = "Core Default Services"; - private static final int DEFAULT_RETRY_POLICY_MAX_RETRIES = 5; - private static final int DEFAULT_RETRY_POLICY_BACKOFF_MIN_MILLIS = 500; - private static final int DEFAULT_RETRY_POLICY_BACKOFF_MAX_MILLIS = 10000; - private static final boolean DEFAULT_RETRY_POLICY_LOG_ON_RETRY = false; - private static final boolean DEFAULT_RETRY_POLICY_LOG_ON_RETRY_SCHEDULED = false; - private static final boolean DEFAULT_RETRY_POLICY_LOG_ON_RETRIES_EXCEEDED = false; - private static final boolean DEFAULT_RETRY_POLICY_LOG_ON_FAILED_ATTEMPT = false; - private static final boolean DEFAULT_RETRY_POLICY_LOG_ON_ABORT = false; - private static final int DEFAULT_OK_HTTP_CLIENT_TIMEOUT_CONNECT = 30; - private static final int DEFAULT_OK_HTTP_CLIENT_TIMEOUT_READ = 30; - private static final boolean DEFAULT_OK_HTTP_CLIENT_HTTPS_ENFORCE = false; - private static final int DEFAULT_OK_HTTP_CLIENT_SEND_BUFFER_SIZE = 0; - private static final int DEFAULT_OK_HTTP_CLIENT_RECEIVE_BUFFER_SIZE = 0; - - @Setting(value = "RetryPolicy: Maximum retries before a failure is propagated", defaultValue = DEFAULT_RETRY_POLICY_MAX_RETRIES + "", type = "int") - private static final String RETRY_POLICY_MAX_RETRIES = "edc.core.retry.retries.max"; - @Setting(value = "RetryPolicy: Minimum number of milliseconds for exponential backoff", defaultValue = DEFAULT_RETRY_POLICY_BACKOFF_MIN_MILLIS + "", type = "int") - private static final String RETRY_POLICY_BACKOFF_MIN_MILLIS = "edc.core.retry.backoff.min"; - @Setting(value = "RetryPolicy: Maximum number of milliseconds for exponential backoff", defaultValue = DEFAULT_RETRY_POLICY_BACKOFF_MAX_MILLIS + "", type = "int") - private static final String RETRY_POLICY_BACKOFF_MAX_MILLIS = "edc.core.retry.backoff.max"; - @Setting(value = "RetryPolicy: Log onRetry events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_RETRY + "", type = "boolean") - private static final String RETRY_POLICY_LOG_ON_RETRY = "edc.core.retry.log.on.retry"; - @Setting(value = "RetryPolicy: Log onRetryScheduled events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_RETRY_SCHEDULED + "", type = "boolean") - private static final String RETRY_POLICY_LOG_ON_RETRY_SCHEDULED = "edc.core.retry.log.on.retry.scheduled"; - @Setting(value = "RetryPolicy: Log onRetriesExceeded events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_RETRIES_EXCEEDED + "", type = "boolean") - private static final String RETRY_POLICY_LOG_ON_RETRIES_EXCEEDED = "edc.core.retry.log.on.retries.exceeded"; - @Setting(value = "RetryPolicy: Log onFailedAttempt events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_FAILED_ATTEMPT + "", type = "boolean") - private static final String RETRY_POLICY_LOG_ON_FAILED_ATTEMPT = "edc.core.retry.log.on.failed.attempt"; - @Setting(value = "RetryPolicy: Log onAbort events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_ABORT + "", type = "boolean") - private static final String RETRY_POLICY_LOG_ON_ABORT = "edc.core.retry.log.on.abort"; - @Setting(value = "OkHttpClient: If true, enable HTTPS call enforcement", defaultValue = DEFAULT_OK_HTTP_CLIENT_HTTPS_ENFORCE + "", type = "boolean") - private static final String OK_HTTP_CLIENT_HTTPS_ENFORCE = "edc.http.client.https.enforce"; - @Setting(value = "OkHttpClient: connect timeout, in seconds", defaultValue = DEFAULT_OK_HTTP_CLIENT_TIMEOUT_CONNECT + "", type = "int") - private static final String OK_HTTP_CLIENT_TIMEOUT_CONNECT = "edc.http.client.timeout.connect"; - @Setting(value = "OkHttpClient: read timeout, in seconds", defaultValue = DEFAULT_OK_HTTP_CLIENT_TIMEOUT_READ + "", type = "int") - private static final String OK_HTTP_CLIENT_TIMEOUT_READ = "edc.http.client.timeout.read"; - @Setting(value = "OkHttpClient: send buffer size, in bytes", defaultValue = DEFAULT_OK_HTTP_CLIENT_SEND_BUFFER_SIZE + "", type = "int", min = 1) - private static final String OK_HTTP_CLIENT_SEND_BUFFER_SIZE = "edc.http.client.send.buffer.size"; - @Setting(value = "OkHttpClient: receive buffer size, in bytes", defaultValue = DEFAULT_OK_HTTP_CLIENT_RECEIVE_BUFFER_SIZE + "", type = "int", min = 1) - private static final String OK_HTTP_CLIENT_RECEIVE_BUFFER_SIZE = "edc.http.client.receive.buffer.size"; /** * An optional OkHttp {@link EventListener} that can be used to instrument OkHttp client for collecting metrics. */ @Inject(required = false) private EventListener okHttpEventListener; + @Configuration + private OkHttpClientConfiguration configuration; + @Configuration + private RetryPolicyConfiguration retryPolicyConfiguration; @Override public String name() { @@ -134,31 +98,13 @@ public ControlClientAuthenticationProvider controlClientAuthenticationProvider() @Provider public OkHttpClient okHttpClient(ServiceExtensionContext context) { - var configuration = OkHttpClientConfiguration.Builder.newInstance() - .enforceHttps(context.getSetting(OK_HTTP_CLIENT_HTTPS_ENFORCE, DEFAULT_OK_HTTP_CLIENT_HTTPS_ENFORCE)) - .connectTimeout(context.getSetting(OK_HTTP_CLIENT_TIMEOUT_CONNECT, DEFAULT_OK_HTTP_CLIENT_TIMEOUT_CONNECT)) - .readTimeout(context.getSetting(OK_HTTP_CLIENT_TIMEOUT_READ, DEFAULT_OK_HTTP_CLIENT_TIMEOUT_READ)) - .sendBufferSize(context.getSetting(OK_HTTP_CLIENT_SEND_BUFFER_SIZE, DEFAULT_OK_HTTP_CLIENT_SEND_BUFFER_SIZE)) - .receiveBufferSize(context.getSetting(OK_HTTP_CLIENT_RECEIVE_BUFFER_SIZE, DEFAULT_OK_HTTP_CLIENT_RECEIVE_BUFFER_SIZE)) - .build(); - return OkHttpClientFactory.create(configuration, okHttpEventListener, context.getMonitor()); } @Provider public RetryPolicy retryPolicy(ServiceExtensionContext context) { - var configuration = RetryPolicyConfiguration.Builder.newInstance() - .maxRetries(context.getSetting(RETRY_POLICY_MAX_RETRIES, DEFAULT_RETRY_POLICY_MAX_RETRIES)) - .minBackoff(context.getSetting(RETRY_POLICY_BACKOFF_MIN_MILLIS, DEFAULT_RETRY_POLICY_BACKOFF_MIN_MILLIS)) - .maxBackoff(context.getSetting(RETRY_POLICY_BACKOFF_MAX_MILLIS, DEFAULT_RETRY_POLICY_BACKOFF_MAX_MILLIS)) - .logOnRetry(context.getSetting(RETRY_POLICY_LOG_ON_RETRY, DEFAULT_RETRY_POLICY_LOG_ON_RETRY)) - .logOnRetryScheduled(context.getSetting(RETRY_POLICY_LOG_ON_RETRY_SCHEDULED, DEFAULT_RETRY_POLICY_LOG_ON_RETRY_SCHEDULED)) - .logOnRetriesExceeded(context.getSetting(RETRY_POLICY_LOG_ON_RETRIES_EXCEEDED, DEFAULT_RETRY_POLICY_LOG_ON_RETRIES_EXCEEDED)) - .logOnFailedAttempt(context.getSetting(RETRY_POLICY_LOG_ON_FAILED_ATTEMPT, DEFAULT_RETRY_POLICY_LOG_ON_FAILED_ATTEMPT)) - .logOnAbort(context.getSetting(RETRY_POLICY_LOG_ON_ABORT, DEFAULT_RETRY_POLICY_LOG_ON_ABORT)) - .build(); - - return RetryPolicyFactory.create(configuration, context.getMonitor()); + + return RetryPolicyFactory.create(retryPolicyConfiguration, context.getMonitor()); } @Provider(isDefault = true) diff --git a/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/base/OkHttpClientConfiguration.java b/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/base/OkHttpClientConfiguration.java index 97025b59c7c..ddbdaf66eab 100644 --- a/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/base/OkHttpClientConfiguration.java +++ b/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/base/OkHttpClientConfiguration.java @@ -14,15 +14,30 @@ package org.eclipse.edc.connector.core.base; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.runtime.metamodel.annotation.Settings; + +@Settings public class OkHttpClientConfiguration { + public static final boolean DEFAULT_OK_HTTP_CLIENT_HTTPS_ENFORCE = false; + public static final int DEFAULT_OK_HTTP_CLIENT_TIMEOUT_CONNECT = 30; + public static final int DEFAULT_OK_HTTP_CLIENT_TIMEOUT_READ = 30; + public static final int DEFAULT_OK_HTTP_CLIENT_SEND_BUFFER_SIZE = 0; + public static final int DEFAULT_OK_HTTP_CLIENT_RECEIVE_BUFFER_SIZE = 0; + @Setting(description = "OkHttpClient: If true, enable HTTPS call enforcement", defaultValue = DEFAULT_OK_HTTP_CLIENT_HTTPS_ENFORCE + "", key = "edc.http.client.https.enforce") private boolean enforceHttps; + + @Setting(description = "OkHttpClient: connect timeout, in seconds", defaultValue = DEFAULT_OK_HTTP_CLIENT_TIMEOUT_CONNECT + "", key = "edc.http.client.timeout.connect") private int connectTimeout; + @Setting(description = "OkHttpClient: read timeout, in seconds", defaultValue = DEFAULT_OK_HTTP_CLIENT_TIMEOUT_READ + "", key = "edc.http.client.timeout.read") private int readTimeout; + @Setting(description = "OkHttpClient: send buffer size, in bytes", defaultValue = DEFAULT_OK_HTTP_CLIENT_SEND_BUFFER_SIZE + "", key = "edc.http.client.send.buffer.size", min = 1) private int sendBufferSize; + @Setting(description = "OkHttpClient: receive buffer size, in bytes", defaultValue = DEFAULT_OK_HTTP_CLIENT_RECEIVE_BUFFER_SIZE + "", key = "edc.http.client.receive.buffer.size", min = 1) private int receiveBufferSize; - private OkHttpClientConfiguration() { + public OkHttpClientConfiguration() { } public boolean isEnforceHttps() { @@ -45,15 +60,20 @@ public int getReceiveBufferSize() { return receiveBufferSize; } + public Builder toBuilder() { + return new Builder(this); + } + public static class Builder { - private final OkHttpClientConfiguration instance = new OkHttpClientConfiguration(); + private final OkHttpClientConfiguration instance; - public static Builder newInstance() { - return new Builder(); + private Builder(OkHttpClientConfiguration okHttpClientConfiguration) { + this.instance = okHttpClientConfiguration; } - private Builder() { + public static Builder newInstance() { + return new Builder(new OkHttpClientConfiguration()); } public Builder enforceHttps(boolean enforceHttps) { @@ -85,4 +105,5 @@ public OkHttpClientConfiguration build() { return instance; } } + } diff --git a/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/base/RetryPolicyConfiguration.java b/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/base/RetryPolicyConfiguration.java index daa255dde46..2e15030fcf9 100644 --- a/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/base/RetryPolicyConfiguration.java +++ b/core/common/connector-core/src/main/java/org/eclipse/edc/connector/core/base/RetryPolicyConfiguration.java @@ -14,18 +14,38 @@ package org.eclipse.edc.connector.core.base; -public class RetryPolicyConfiguration { +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.runtime.metamodel.annotation.Settings; +@Settings +public class RetryPolicyConfiguration { + public static final int DEFAULT_RETRY_POLICY_MAX_RETRIES = 5; + public static final int DEFAULT_RETRY_POLICY_BACKOFF_MIN_MILLIS = 500; + public static final int DEFAULT_RETRY_POLICY_BACKOFF_MAX_MILLIS = 10000; + public static final boolean DEFAULT_RETRY_POLICY_LOG_ON_RETRY = false; + public static final boolean DEFAULT_RETRY_POLICY_LOG_ON_RETRY_SCHEDULED = false; + public static final boolean DEFAULT_RETRY_POLICY_LOG_ON_RETRIES_EXCEEDED = false; + public static final boolean DEFAULT_RETRY_POLICY_LOG_ON_FAILED_ATTEMPT = false; + public static final boolean DEFAULT_RETRY_POLICY_LOG_ON_ABORT = false; + + @Setting(description = "RetryPolicy: Maximum retries before a failure is propagated", defaultValue = DEFAULT_RETRY_POLICY_MAX_RETRIES + "", key = "edc.core.retry.retries.max") private int maxRetries; + @Setting(description = "RetryPolicy: Minimum number of milliseconds for exponential backoff", defaultValue = DEFAULT_RETRY_POLICY_BACKOFF_MIN_MILLIS + "", key = "edc.core.retry.backoff.min") private int minBackoff = 1; + @Setting(description = "RetryPolicy: Maximum number of milliseconds for exponential backoff", defaultValue = DEFAULT_RETRY_POLICY_BACKOFF_MAX_MILLIS + "", key = "edc.core.retry.backoff.max") private int maxBackoff = Integer.MAX_VALUE; + @Setting(description = "RetryPolicy: Log onRetry events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_RETRY + "", key = "edc.core.retry.log.on.retry") private boolean logOnRetry; + @Setting(description = "RetryPolicy: Log onRetryScheduled events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_RETRY_SCHEDULED + "", key = "edc.core.retry.log.on.retry.scheduled") private boolean logOnRetryScheduled; + @Setting(description = "RetryPolicy: Log onRetriesExceeded events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_RETRIES_EXCEEDED + "", key = "edc.core.retry.log.on.retries.exceeded") private boolean logOnRetriesExceeded; + @Setting(description = "RetryPolicy: Log onFailedAttempt events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_FAILED_ATTEMPT + "", key = "edc.core.retry.log.on.failed.attempt") private boolean logOnFailedAttempt; + @Setting(description = "RetryPolicy: Log onAbort events", defaultValue = DEFAULT_RETRY_POLICY_LOG_ON_ABORT + "", key = "edc.core.retry.log.on.abort") private boolean logOnAbort; - private RetryPolicyConfiguration() { + public RetryPolicyConfiguration() { } public int getMaxRetries() { @@ -60,15 +80,20 @@ public boolean isLogOnAbort() { return logOnAbort; } + public Builder toBuilder() { + return new Builder(this); + } + public static class Builder { - private final RetryPolicyConfiguration instance = new RetryPolicyConfiguration(); + private final RetryPolicyConfiguration instance; - public static Builder newInstance() { - return new Builder(); + private Builder(RetryPolicyConfiguration instance) { + this.instance = instance; } - private Builder() { + public static Builder newInstance() { + return new Builder(new RetryPolicyConfiguration()); } public Builder maxRetries(int maxRetries) { diff --git a/core/common/connector-core/src/test/java/org/eclipse/edc/connector/core/base/OkHttpClientFactoryTest.java b/core/common/connector-core/src/test/java/org/eclipse/edc/connector/core/base/OkHttpClientFactoryTest.java index c3330769fa7..12344671faa 100644 --- a/core/common/connector-core/src/test/java/org/eclipse/edc/connector/core/base/OkHttpClientFactoryTest.java +++ b/core/common/connector-core/src/test/java/org/eclipse/edc/connector/core/base/OkHttpClientFactoryTest.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; class OkHttpClientFactoryTest { @@ -47,7 +48,7 @@ class OkHttpClientFactoryTest { @Test void shouldPrintLogIfHttpsNotEnforced() { - var configuration = OkHttpClientConfiguration.Builder.newInstance().build(); + var configuration = mock(OkHttpClientConfiguration.class); var okHttpClient = OkHttpClientFactory.create(configuration, eventListener, monitor) .newBuilder().addInterceptor(dummySuccessfulResponse()) @@ -60,7 +61,8 @@ void shouldPrintLogIfHttpsNotEnforced() { @Test void shouldEnforceHttpsCalls() { - var configuration = OkHttpClientConfiguration.Builder.newInstance().enforceHttps(true).build(); + var configuration = mock(OkHttpClientConfiguration.class); + when(configuration.isEnforceHttps()).thenReturn(true); var okHttpClient = OkHttpClientFactory.create(configuration, eventListener, monitor) .newBuilder().addInterceptor(dummySuccessfulResponse()) @@ -73,10 +75,9 @@ void shouldEnforceHttpsCalls() { @Test void shouldCreateCustomSocketFactory_whenSendSocketBufferIsSet() { - var configuration = OkHttpClientConfiguration.Builder.newInstance() - .sendBufferSize(4096) - .receiveBufferSize(4096) - .build(); + var configuration = mock(OkHttpClientConfiguration.class); + when(configuration.getSendBufferSize()).thenReturn(4096); + when(configuration.getReceiveBufferSize()).thenReturn(4096); var okHttpClient = OkHttpClientFactory.create(configuration, eventListener, monitor) .newBuilder() diff --git a/core/common/edr-store-core/src/main/java/org/eclipse/edc/edr/store/EndpointDataReferenceStoreDefaultServicesExtension.java b/core/common/edr-store-core/src/main/java/org/eclipse/edc/edr/store/EndpointDataReferenceStoreDefaultServicesExtension.java index 48dc5cd660f..5a834b6d3b3 100644 --- a/core/common/edr-store-core/src/main/java/org/eclipse/edc/edr/store/EndpointDataReferenceStoreDefaultServicesExtension.java +++ b/core/common/edr-store-core/src/main/java/org/eclipse/edc/edr/store/EndpointDataReferenceStoreDefaultServicesExtension.java @@ -25,15 +25,13 @@ import org.eclipse.edc.spi.query.CriterionOperatorRegistry; 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.spi.types.TypeManager; -@Extension(EndpointDataReferenceStoreExtension.NAME) +@Extension(EndpointDataReferenceStoreDefaultServicesExtension.NAME) public class EndpointDataReferenceStoreDefaultServicesExtension implements ServiceExtension { - public static final String DEFAULT_EDR_VAULT_PATH = ""; - @Setting(value = "Directory/Path where to store EDRs in the vault for vaults that supports hierarchical structuring.", defaultValue = DEFAULT_EDR_VAULT_PATH) - public static final String EDC_EDR_VAULT_PATH = "edc.edr.vault.path"; + @Setting(description = "Directory/Path where to store EDRs in the vault for vaults that supports hierarchical structuring.", key = "edc.edr.vault.path", required = false) + private String vaultPath = ""; protected static final String NAME = "Endpoint Data Reference Core Default Services Extension"; @Inject @@ -47,9 +45,13 @@ public class EndpointDataReferenceStoreDefaultServicesExtension implements Servi @Provider(isDefault = true) - public EndpointDataReferenceCache endpointDataReferenceCache(ServiceExtensionContext context) { - var vaultDirectory = context.getConfig().getString(EDC_EDR_VAULT_PATH, DEFAULT_EDR_VAULT_PATH); - return new VaultEndpointDataReferenceCache(vault, vaultDirectory, typeManager.getMapper()); + public EndpointDataReferenceCache endpointDataReferenceCache() { + return new VaultEndpointDataReferenceCache(vault, vaultPath, typeManager.getMapper()); + } + + @Override + public String name() { + return NAME; } @Provider(isDefault = true) diff --git a/core/common/edr-store-core/src/test/java/org/eclipse/edc/edr/store/EndpointDataReferenceStoreDefaultServicesExtensionTest.java b/core/common/edr-store-core/src/test/java/org/eclipse/edc/edr/store/EndpointDataReferenceStoreDefaultServicesExtensionTest.java index 42184aa87fe..feb9b06bba4 100644 --- a/core/common/edr-store-core/src/test/java/org/eclipse/edc/edr/store/EndpointDataReferenceStoreDefaultServicesExtensionTest.java +++ b/core/common/edr-store-core/src/test/java/org/eclipse/edc/edr/store/EndpointDataReferenceStoreDefaultServicesExtensionTest.java @@ -29,10 +29,9 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.edr.store.EndpointDataReferenceStoreDefaultServicesExtension.EDC_EDR_VAULT_PATH; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.startsWith; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -48,39 +47,35 @@ public class EndpointDataReferenceStoreDefaultServicesExtensionTest { void setUp(ServiceExtensionContext context) { context.registerService(Vault.class, vault); context.registerService(TypeManager.class, typeManager); + + var config = mock(Config.class); + when(context.getConfig()).thenReturn(config); + when(config.hasKey(eq("edc.edr.vault.path"))).thenReturn(true); + when(config.getString(eq("edc.edr.vault.path"))).thenReturn("path/"); } @Test - void initializeTheCache(ServiceExtensionContext context, EndpointDataReferenceStoreDefaultServicesExtension extension) { - - var cache = extension.endpointDataReferenceCache(context); + void initializeTheCache(EndpointDataReferenceStoreDefaultServicesExtension extension) { + var cache = extension.endpointDataReferenceCache(); assertThat(cache).isInstanceOf(VaultEndpointDataReferenceCache.class); } @Test - void initializeTheCache_withPath(ServiceExtensionContext context, EndpointDataReferenceStoreDefaultServicesExtension extension) { - var config = mock(Config.class); - when(context.getConfig()).thenReturn(config); - when(config.getString(eq(EDC_EDR_VAULT_PATH), any())).thenReturn("path/"); - when(typeManager.getMapper()).thenReturn(new ObjectMapper()); - - var cache = extension.endpointDataReferenceCache(context); + void createExtension_withPath(EndpointDataReferenceStoreDefaultServicesExtension extension) { + when(typeManager.getMapper()).thenReturn(new ObjectMapper()); when(vault.storeSecret(any(), any())).thenReturn(Result.success()); - assertThat(cache).isInstanceOf(VaultEndpointDataReferenceCache.class); + var cache = extension.endpointDataReferenceCache(); cache.put("id", DataAddress.Builder.newInstance().type("type").build()); - - verify(vault).storeSecret(argThat(s -> s.startsWith("path/")), any()); + verify(vault).storeSecret(startsWith("path/"), any()); } @Test - void initializeTheStore(ServiceExtensionContext context, EndpointDataReferenceStoreDefaultServicesExtension extension) { - + void initializeTheStore(EndpointDataReferenceStoreDefaultServicesExtension extension) { var store = extension.endpointDataReferenceEntryStore(); - assertThat(store).isInstanceOf(InMemoryEndpointDataReferenceEntryIndex.class); } diff --git a/core/common/junit/src/main/java/org/eclipse/edc/junit/extensions/DependencyInjectionExtension.java b/core/common/junit/src/main/java/org/eclipse/edc/junit/extensions/DependencyInjectionExtension.java index c1246cf3b35..12e154fda2f 100644 --- a/core/common/junit/src/main/java/org/eclipse/edc/junit/extensions/DependencyInjectionExtension.java +++ b/core/common/junit/src/main/java/org/eclipse/edc/junit/extensions/DependencyInjectionExtension.java @@ -17,6 +17,7 @@ import org.eclipse.edc.boot.system.injection.InjectionPointScanner; import org.eclipse.edc.boot.system.injection.InjectorImpl; import org.eclipse.edc.boot.system.injection.ObjectFactory; +import org.eclipse.edc.boot.system.injection.ServiceInjectionPoint; import org.eclipse.edc.boot.system.runtime.BaseRuntime; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; @@ -52,7 +53,15 @@ public void beforeEach(ExtensionContext extensionContext) { context = spy(super.createServiceExtensionContext(ConfigFactory.empty())); context.initialize(); factory = new ReflectiveObjectFactory( - new InjectorImpl((ip, c) -> ofNullable(ip.getDefaultValueProvider()).map(vp -> vp.get(c)).orElseGet(() -> mock(ip.getType()))), + new InjectorImpl((ip, c) -> ofNullable(ip.getDefaultValueProvider()) + .map(vp -> vp.get(c)) + .orElseGet(() -> { + if (ip instanceof ServiceInjectionPoint) { + return mock(ip.getType()); + } else { + return ip.resolve(context, (t, ctx) -> null); + } + })), new InjectionPointScanner(), context ); diff --git a/core/control-plane/control-plane-aggregate-services/src/main/java/org/eclipse/edc/connector/controlplane/services/ControlPlaneServicesExtension.java b/core/control-plane/control-plane-aggregate-services/src/main/java/org/eclipse/edc/connector/controlplane/services/ControlPlaneServicesExtension.java index a0360d9aef8..77257b298f8 100644 --- a/core/control-plane/control-plane-aggregate-services/src/main/java/org/eclipse/edc/connector/controlplane/services/ControlPlaneServicesExtension.java +++ b/core/control-plane/control-plane-aggregate-services/src/main/java/org/eclipse/edc/connector/controlplane/services/ControlPlaneServicesExtension.java @@ -100,7 +100,7 @@ public class ControlPlaneServicesExtension implements ServiceExtension { public static final String NAME = "Control Plane Services"; - @Setting(key = "edc.policy.validation.enabled", description = "If true enables the policy validation when creating and updating policy definitions", defaultValue = "false") + @Setting(description = "If true enables the policy validation when creating and updating policy definitions", defaultValue = "false", key = "edc.policy.validation.enabled") private Boolean validatePolicy; @Inject diff --git a/core/control-plane/control-plane-contract/src/main/java/org/eclipse/edc/connector/controlplane/contract/ContractCoreExtension.java b/core/control-plane/control-plane-contract/src/main/java/org/eclipse/edc/connector/controlplane/contract/ContractCoreExtension.java index 0bad3efff20..6b92be2a264 100644 --- a/core/control-plane/control-plane-contract/src/main/java/org/eclipse/edc/connector/controlplane/contract/ContractCoreExtension.java +++ b/core/control-plane/control-plane-contract/src/main/java/org/eclipse/edc/connector/controlplane/contract/ContractCoreExtension.java @@ -77,26 +77,26 @@ public class ContractCoreExtension implements ServiceExtension { public static final String NAME = "Contract Core"; - @Setting(value = "the iteration wait time in milliseconds in the negotiation state machine. Default value " + DEFAULT_ITERATION_WAIT, type = "long") - private static final String NEGOTIATION_STATE_MACHINE_ITERATION_WAIT_MILLIS = "edc.negotiation.state-machine.iteration-wait-millis"; + @Setting(description = "the iteration wait time in milliseconds in the negotiation state machine. Default value " + DEFAULT_ITERATION_WAIT, key = "edc.negotiation.state-machine.iteration-wait-millis", defaultValue = DEFAULT_ITERATION_WAIT + "") + private long stateMachineIterationWaitMillis; - @Setting(value = "the batch size in the consumer negotiation state machine. Default value " + DEFAULT_BATCH_SIZE, type = "int") - private static final String NEGOTIATION_CONSUMER_STATE_MACHINE_BATCH_SIZE = "edc.negotiation.consumer.state-machine.batch-size"; + @Setting(description = "the batch size in the consumer negotiation state machine. Default value " + DEFAULT_BATCH_SIZE, key = "edc.negotiation.consumer.state-machine.batch-size", defaultValue = DEFAULT_BATCH_SIZE + "") + private int consumerStateMachineBatchSize; - @Setting(value = "the batch size in the provider negotiation state machine. Default value " + DEFAULT_BATCH_SIZE, type = "int") - private static final String NEGOTIATION_PROVIDER_STATE_MACHINE_BATCH_SIZE = "edc.negotiation.provider.state-machine.batch-size"; + @Setting(description = "the batch size in the provider negotiation state machine. Default value " + DEFAULT_BATCH_SIZE, key = "edc.negotiation.provider.state-machine.batch-size", defaultValue = DEFAULT_BATCH_SIZE + "") + private int providerStateMachineBatchSize; - @Setting(value = "how many times a specific operation must be tried before terminating the consumer negotiation with error", type = "int", defaultValue = DEFAULT_SEND_RETRY_LIMIT + "") - private static final String NEGOTIATION_CONSUMER_SEND_RETRY_LIMIT = "edc.negotiation.consumer.send.retry.limit"; + @Setting(description = "how many times a specific operation must be tried before terminating the consumer negotiation with error", key = "edc.negotiation.consumer.send.retry.limit", defaultValue = DEFAULT_SEND_RETRY_LIMIT + "") + private int consumerSendRetryLimit; - @Setting(value = "how many times a specific operation must be tried before terminating the provider negotiation with error", type = "int", defaultValue = DEFAULT_SEND_RETRY_LIMIT + "") - private static final String NEGOTIATION_PROVIDER_SEND_RETRY_LIMIT = "edc.negotiation.provider.send.retry.limit"; + @Setting(description = "how many times a specific operation must be tried before terminating the provider negotiation with error", key = "edc.negotiation.provider.send.retry.limit", defaultValue = DEFAULT_SEND_RETRY_LIMIT + "") + private int providerSendRetryLimit; - @Setting(value = "The base delay for the consumer negotiation retry mechanism in millisecond", type = "long", defaultValue = DEFAULT_SEND_RETRY_BASE_DELAY + "") - private static final String NEGOTIATION_CONSUMER_SEND_RETRY_BASE_DELAY_MS = "edc.negotiation.consumer.send.retry.base-delay.ms"; + @Setting(description = "The base delay for the consumer negotiation retry mechanism in millisecond", key = "edc.negotiation.consumer.send.retry.base-delay.ms", defaultValue = DEFAULT_SEND_RETRY_BASE_DELAY + "") + private long consumerSendRetryBaseDelayMs; - @Setting(value = "The base delay for the provider negotiation retry mechanism in millisecond", type = "long", defaultValue = DEFAULT_SEND_RETRY_BASE_DELAY + "") - private static final String NEGOTIATION_PROVIDER_SEND_RETRY_BASE_DELAY_MS = "edc.negotiation.provider.send.retry.base-delay.ms"; + @Setting(description = "The base delay for the provider negotiation retry mechanism in millisecond", key = "edc.negotiation.provider.send.retry.base-delay.ms", defaultValue = DEFAULT_SEND_RETRY_BASE_DELAY + "") + private long providerSendRetryBaseDelayMs; private ConsumerContractNegotiationManagerImpl consumerNegotiationManager; @@ -192,8 +192,7 @@ private void registerServices(ServiceExtensionContext context) { policyEngine.registerFunction(TransferProcessPolicyContext.class, Permission.class, CONTRACT_EXPIRY_EVALUATION_KEY, new ContractExpiryCheckFunction<>()); - var iterationWaitMillis = context.getSetting(NEGOTIATION_STATE_MACHINE_ITERATION_WAIT_MILLIS, DEFAULT_ITERATION_WAIT); - var waitStrategy = context.hasService(NegotiationWaitStrategy.class) ? context.getService(NegotiationWaitStrategy.class) : new ExponentialWaitStrategy(iterationWaitMillis); + var waitStrategy = context.hasService(NegotiationWaitStrategy.class) ? context.getService(NegotiationWaitStrategy.class) : new ExponentialWaitStrategy(stateMachineIterationWaitMillis); observable.registerListener(new ContractNegotiationEventListener(eventRouter, clock)); @@ -208,8 +207,8 @@ private void registerServices(ServiceExtensionContext context) { .executorInstrumentation(executorInstrumentation) .store(store) .policyStore(policyStore) - .batchSize(context.getSetting(NEGOTIATION_CONSUMER_STATE_MACHINE_BATCH_SIZE, DEFAULT_BATCH_SIZE)) - .entityRetryProcessConfiguration(consumerEntityRetryProcessConfiguration(context)) + .batchSize(consumerStateMachineBatchSize) + .entityRetryProcessConfiguration(consumerEntityRetryProcessConfiguration()) .protocolWebhook(protocolWebhook) .pendingGuard(pendingGuard) .build(); @@ -225,8 +224,8 @@ private void registerServices(ServiceExtensionContext context) { .executorInstrumentation(executorInstrumentation) .store(store) .policyStore(policyStore) - .batchSize(context.getSetting(NEGOTIATION_PROVIDER_STATE_MACHINE_BATCH_SIZE, DEFAULT_BATCH_SIZE)) - .entityRetryProcessConfiguration(providerEntityRetryProcessConfiguration(context)) + .batchSize(providerStateMachineBatchSize) + .entityRetryProcessConfiguration(providerEntityRetryProcessConfiguration()) .protocolWebhook(protocolWebhook) .pendingGuard(pendingGuard) .build(); @@ -235,17 +234,13 @@ private void registerServices(ServiceExtensionContext context) { context.registerService(ProviderContractNegotiationManager.class, providerNegotiationManager); } - private EntityRetryProcessConfiguration providerEntityRetryProcessConfiguration(ServiceExtensionContext context) { - var retryLimit = context.getSetting(NEGOTIATION_PROVIDER_SEND_RETRY_LIMIT, DEFAULT_SEND_RETRY_LIMIT); - var retryBaseDelay = context.getSetting(NEGOTIATION_PROVIDER_SEND_RETRY_BASE_DELAY_MS, DEFAULT_SEND_RETRY_BASE_DELAY); - return new EntityRetryProcessConfiguration(retryLimit, () -> new ExponentialWaitStrategy(retryBaseDelay)); + private EntityRetryProcessConfiguration providerEntityRetryProcessConfiguration() { + return new EntityRetryProcessConfiguration(providerSendRetryLimit, () -> new ExponentialWaitStrategy(providerSendRetryBaseDelayMs)); } @NotNull - private EntityRetryProcessConfiguration consumerEntityRetryProcessConfiguration(ServiceExtensionContext context) { - var retryLimit = context.getSetting(NEGOTIATION_CONSUMER_SEND_RETRY_LIMIT, DEFAULT_SEND_RETRY_LIMIT); - var retryBaseDelay = context.getSetting(NEGOTIATION_CONSUMER_SEND_RETRY_BASE_DELAY_MS, DEFAULT_SEND_RETRY_BASE_DELAY); - return new EntityRetryProcessConfiguration(retryLimit, () -> new ExponentialWaitStrategy(retryBaseDelay)); + private EntityRetryProcessConfiguration consumerEntityRetryProcessConfiguration() { + return new EntityRetryProcessConfiguration(consumerSendRetryLimit, () -> new ExponentialWaitStrategy(consumerSendRetryBaseDelayMs)); } } diff --git a/core/control-plane/control-plane-transfer/src/main/java/org/eclipse/edc/connector/controlplane/transfer/TransferCoreExtension.java b/core/control-plane/control-plane-transfer/src/main/java/org/eclipse/edc/connector/controlplane/transfer/TransferCoreExtension.java index 49236b23cab..0b1a49c1bb5 100644 --- a/core/control-plane/control-plane-transfer/src/main/java/org/eclipse/edc/connector/controlplane/transfer/TransferCoreExtension.java +++ b/core/control-plane/control-plane-transfer/src/main/java/org/eclipse/edc/connector/controlplane/transfer/TransferCoreExtension.java @@ -72,17 +72,17 @@ public class TransferCoreExtension implements ServiceExtension { public static final String NAME = "Transfer Core"; - @Setting(value = "the iteration wait time in milliseconds in the transfer process state machine. Default value " + DEFAULT_ITERATION_WAIT, type = "long") - private static final String TRANSFER_STATE_MACHINE_ITERATION_WAIT_MILLIS = "edc.transfer.state-machine.iteration-wait-millis"; + @Setting(description = "the iteration wait time in milliseconds in the transfer process state machine. Default value " + DEFAULT_ITERATION_WAIT, key = "edc.transfer.state-machine.iteration-wait-millis", defaultValue = DEFAULT_ITERATION_WAIT + "") + private long stateMachineIterationWaitMillis; - @Setting(value = "the batch size in the transfer process state machine. Default value " + DEFAULT_BATCH_SIZE, type = "int") - private static final String TRANSFER_STATE_MACHINE_BATCH_SIZE = "edc.transfer.state-machine.batch-size"; + @Setting(description = "the batch size in the transfer process state machine. Default value " + DEFAULT_BATCH_SIZE, key = "edc.transfer.state-machine.batch-size", defaultValue = DEFAULT_BATCH_SIZE + "") + private int stateMachineBatchSize; - @Setting(value = "how many times a specific operation must be tried before terminating the transfer with error", type = "int", defaultValue = DEFAULT_SEND_RETRY_LIMIT + "") - private static final String TRANSFER_SEND_RETRY_LIMIT = "edc.transfer.send.retry.limit"; + @Setting(description = "how many times a specific operation must be tried before terminating the transfer with error", key = "edc.transfer.send.retry.limit", defaultValue = DEFAULT_SEND_RETRY_LIMIT + "") + private int sendRetryLimit; - @Setting(value = "The base delay for the transfer retry mechanism in millisecond", type = "long", defaultValue = DEFAULT_SEND_RETRY_BASE_DELAY + "") - private static final String TRANSFER_SEND_RETRY_BASE_DELAY_MS = "edc.transfer.send.retry.base-delay.ms"; + @Setting(description = "The base delay for the transfer retry mechanism in millisecond", key = "edc.transfer.send.retry.base-delay.ms", defaultValue = DEFAULT_SEND_RETRY_BASE_DELAY + "") + private long sendRetryBaseDelay; @Inject private TransferProcessStore transferProcessStore; @@ -151,8 +151,7 @@ public void initialize(ServiceExtensionContext context) { registerTypes(typeManager); - var iterationWaitMillis = context.getSetting(TRANSFER_STATE_MACHINE_ITERATION_WAIT_MILLIS, DEFAULT_ITERATION_WAIT); - var waitStrategy = context.hasService(TransferWaitStrategy.class) ? context.getService(TransferWaitStrategy.class) : new ExponentialWaitStrategy(iterationWaitMillis); + var waitStrategy = context.hasService(TransferWaitStrategy.class) ? context.getService(TransferWaitStrategy.class) : new ExponentialWaitStrategy(stateMachineIterationWaitMillis); typeTransformerRegistry.register(new DataAddressToEndpointDataReferenceTransformer()); @@ -163,7 +162,7 @@ public void initialize(ServiceExtensionContext context) { observable.registerListener(new TransferProcessEventListener(eventRouter, clock)); - var entityRetryProcessConfiguration = getEntityRetryProcessConfiguration(context); + var entityRetryProcessConfiguration = getEntityRetryProcessConfiguration(); var provisionResponsesHandler = new ProvisionResponsesHandler(observable, monitor, vault, typeManager); var deprovisionResponsesHandler = new DeprovisionResponsesHandler(observable, monitor, vault); @@ -181,7 +180,7 @@ public void initialize(ServiceExtensionContext context) { .observable(observable) .store(transferProcessStore) .policyArchive(policyArchive) - .batchSize(context.getSetting(TRANSFER_STATE_MACHINE_BATCH_SIZE, DEFAULT_BATCH_SIZE)) + .batchSize(stateMachineBatchSize) .addressResolver(addressResolver) .entityRetryProcessConfiguration(entityRetryProcessConfiguration) .protocolWebhook(protocolWebhook) @@ -209,10 +208,8 @@ public void shutdown() { } @NotNull - private EntityRetryProcessConfiguration getEntityRetryProcessConfiguration(ServiceExtensionContext context) { - var retryLimit = context.getSetting(TRANSFER_SEND_RETRY_LIMIT, DEFAULT_SEND_RETRY_LIMIT); - var retryBaseDelay = context.getSetting(TRANSFER_SEND_RETRY_BASE_DELAY_MS, DEFAULT_SEND_RETRY_BASE_DELAY); - return new EntityRetryProcessConfiguration(retryLimit, () -> new ExponentialWaitStrategy(retryBaseDelay)); + private EntityRetryProcessConfiguration getEntityRetryProcessConfiguration() { + return new EntityRetryProcessConfiguration(sendRetryLimit, () -> new ExponentialWaitStrategy(sendRetryBaseDelay)); } private void registerTypes(TypeManager typeManager) { diff --git a/core/data-plane-selector/data-plane-selector-core/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorExtension.java b/core/data-plane-selector/data-plane-selector-core/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorExtension.java index 17a0ea9fb1b..ee34c448336 100644 --- a/core/data-plane-selector/data-plane-selector-core/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorExtension.java +++ b/core/data-plane-selector/data-plane-selector-core/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorExtension.java @@ -43,14 +43,14 @@ public class DataPlaneSelectorExtension implements ServiceExtension { private static final int DEFAULT_CHECK_PERIOD = 60; - @Setting(value = "the iteration wait time in milliseconds in the data plane selector state machine.", defaultValue = DEFAULT_ITERATION_WAIT + "", type = "long") - private static final String DATA_PLANE_SELECTOR_STATE_MACHINE_ITERATION_WAIT_MILLIS = "edc.data.plane.selector.state-machine.iteration-wait-millis"; + @Setting(description = "the iteration wait time in milliseconds in the data plane selector state machine.", defaultValue = DEFAULT_ITERATION_WAIT + "", key = "edc.data.plane.selector.state-machine.iteration-wait-millis") + private long stateMachineIterationWait; - @Setting(value = "the batch size in the data plane selector state machine.", defaultValue = DEFAULT_BATCH_SIZE + "", type = "int") - private static final String DATA_PLANE_SELECTOR_STATE_MACHINE_BATCH_SIZE = "edc.data.plane.selector.state-machine.batch-size"; + @Setting(description = "the batch size in the data plane selector state machine.", defaultValue = DEFAULT_BATCH_SIZE + "", key = "edc.data.plane.selector.state-machine.batch-size") + private int stateMachineBatchSize; - @Setting(value = "the check period for data plane availability, in seconds", defaultValue = DEFAULT_CHECK_PERIOD + "", type = "int") - private static final String DATA_PLANE_SELECTOR_CHECK_PERIOD = "edc.data.plane.selector.state-machine.check.period"; + @Setting(description = "the check period for data plane availability, in seconds", defaultValue = DEFAULT_CHECK_PERIOD + "", key = "edc.data.plane.selector.state-machine.check.period") + private int selectorCheckPeriod; @Inject private DataPlaneInstanceStore instanceStore; @@ -70,14 +70,11 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var config = context.getConfig(); - var iterationWait = config.getLong(DATA_PLANE_SELECTOR_STATE_MACHINE_ITERATION_WAIT_MILLIS, DEFAULT_ITERATION_WAIT); - var checkPeriod = config.getInteger(DATA_PLANE_SELECTOR_CHECK_PERIOD, DEFAULT_CHECK_PERIOD); var configuration = new DataPlaneSelectorManagerConfiguration( - new ExponentialWaitStrategy(iterationWait), - config.getInteger(DATA_PLANE_SELECTOR_STATE_MACHINE_BATCH_SIZE, DEFAULT_BATCH_SIZE), - Duration.ofSeconds(checkPeriod) + new ExponentialWaitStrategy(stateMachineIterationWait), + stateMachineBatchSize, + Duration.ofSeconds(selectorCheckPeriod) ); manager = DataPlaneSelectorManagerImpl.Builder.newInstance() diff --git a/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/DataPlaneFrameworkExtension.java b/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/DataPlaneFrameworkExtension.java index fab4d18c73f..59cf9fc31c4 100644 --- a/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/DataPlaneFrameworkExtension.java +++ b/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/DataPlaneFrameworkExtension.java @@ -56,38 +56,38 @@ public class DataPlaneFrameworkExtension implements ServiceExtension { private static final int DEFAULT_TRANSFER_THREADS = 20; @Setting( - value = "the iteration wait time in milliseconds in the data plane state machine.", + description = "the iteration wait time in milliseconds in the data plane state machine.", defaultValue = DEFAULT_ITERATION_WAIT + "", - type = "long") - private static final String DATAPLANE_MACHINE_ITERATION_WAIT_MILLIS = "edc.dataplane.state-machine.iteration-wait-millis"; + key = "edc.dataplane.state-machine.iteration-wait-millis") + private long iterationWaitMillis; @Setting( - value = "the batch size in the data plane state machine.", + description = "the batch size in the data plane state machine.", defaultValue = DEFAULT_BATCH_SIZE + "", - type = "int" + key = "edc.dataplane.state-machine.batch-size" ) - private static final String DATAPLANE_MACHINE_BATCH_SIZE = "edc.dataplane.state-machine.batch-size"; + private int batchSize; @Setting( - value = "how many times a specific operation must be tried before terminating the dataplane with error", + description = "how many times a specific operation must be tried before terminating the dataplane with error", defaultValue = DEFAULT_SEND_RETRY_LIMIT + "", - type = "int" + key = "edc.dataplane.send.retry.limit" ) - private static final String DATAPLANE_SEND_RETRY_LIMIT = "edc.dataplane.send.retry.limit"; + private int sendRetryLimit; @Setting( - value = "The base delay for the dataplane retry mechanism in millisecond", + description = "The base delay for the dataplane retry mechanism in millisecond", defaultValue = DEFAULT_SEND_RETRY_BASE_DELAY + "", - type = "long" + key = "edc.dataplane.send.retry.base-delay.ms" ) - private static final String DATAPLANE_SEND_RETRY_BASE_DELAY_MS = "edc.dataplane.send.retry.base-delay.ms"; + private long sendRetryBaseDelay; @Setting( - value = "Size of the transfer thread pool. It is advisable to set it bigger than the state machine batch size", + description = "Size of the transfer thread pool. It is advisable to set it bigger than the state machine batch size", defaultValue = DEFAULT_TRANSFER_THREADS + "", - type = "int" + key = "edc.dataplane.transfer.threads" ) - private static final String TRANSFER_THREADS = "edc.dataplane.transfer.threads"; + private int numThreads; private DataPlaneManagerImpl dataPlaneManager; @@ -121,14 +121,13 @@ public void initialize(ServiceExtensionContext context) { transferServiceRegistry.registerTransferService(pipelineService); context.registerService(TransferServiceRegistry.class, transferServiceRegistry); - var iterationWaitMillis = context.getSetting(DATAPLANE_MACHINE_ITERATION_WAIT_MILLIS, DEFAULT_ITERATION_WAIT); var waitStrategy = new ExponentialWaitStrategy(iterationWaitMillis); dataPlaneManager = DataPlaneManagerImpl.Builder.newInstance() .waitStrategy(waitStrategy) - .batchSize(context.getSetting(DATAPLANE_MACHINE_BATCH_SIZE, DEFAULT_BATCH_SIZE)) + .batchSize(batchSize) .clock(clock) - .entityRetryProcessConfiguration(getEntityRetryProcessConfiguration(context)) + .entityRetryProcessConfiguration(getEntityRetryProcessConfiguration()) .executorInstrumentation(executorInstrumentation) .authorizationService(authorizationService) .transferServiceRegistry(transferServiceRegistry) @@ -157,16 +156,13 @@ public void shutdown() { @Provider public DataTransferExecutorServiceContainer dataTransferExecutorServiceContainer(ServiceExtensionContext context) { - var numThreads = context.getSetting(TRANSFER_THREADS, DEFAULT_TRANSFER_THREADS); var executorService = Executors.newFixedThreadPool(numThreads); return new DataTransferExecutorServiceContainer( executorInstrumentation.instrument(executorService, "Data plane transfers")); } @NotNull - private EntityRetryProcessConfiguration getEntityRetryProcessConfiguration(ServiceExtensionContext context) { - var retryLimit = context.getSetting(DATAPLANE_SEND_RETRY_LIMIT, DEFAULT_SEND_RETRY_LIMIT); - var retryBaseDelay = context.getSetting(DATAPLANE_SEND_RETRY_BASE_DELAY_MS, DEFAULT_SEND_RETRY_BASE_DELAY); - return new EntityRetryProcessConfiguration(retryLimit, () -> new ExponentialWaitStrategy(retryBaseDelay)); + private EntityRetryProcessConfiguration getEntityRetryProcessConfiguration() { + return new EntityRetryProcessConfiguration(sendRetryLimit, () -> new ExponentialWaitStrategy(sendRetryBaseDelay)); } } diff --git a/core/policy-monitor/policy-monitor-core/src/main/java/org/eclipse/edc/connector/policy/monitor/PolicyMonitorExtension.java b/core/policy-monitor/policy-monitor-core/src/main/java/org/eclipse/edc/connector/policy/monitor/PolicyMonitorExtension.java index 2048b940ac5..c731ad05d09 100644 --- a/core/policy-monitor/policy-monitor-core/src/main/java/org/eclipse/edc/connector/policy/monitor/PolicyMonitorExtension.java +++ b/core/policy-monitor/policy-monitor-core/src/main/java/org/eclipse/edc/connector/policy/monitor/PolicyMonitorExtension.java @@ -52,11 +52,12 @@ public class PolicyMonitorExtension implements ServiceExtension { public static final String NAME = "Policy Monitor"; - @Setting(value = "the iteration wait time in milliseconds in the policy monitor state machine. Default value " + DEFAULT_ITERATION_WAIT, type = "long") - private static final String POLICY_MONITOR_ITERATION_WAIT_MILLIS = "edc.policy.monitor.state-machine.iteration-wait-millis"; + @Setting(description = "the iteration wait time in milliseconds in the policy monitor state machine. Default value " + DEFAULT_ITERATION_WAIT, + key = "edc.policy.monitor.state-machine.iteration-wait-millis", defaultValue = DEFAULT_ITERATION_WAIT + "") + private long iterationWaitMillis; - @Setting(value = "the batch size in the policy monitor state machine. Default value " + DEFAULT_BATCH_SIZE, type = "int") - private static final String POLICY_MONITOR_BATCH_SIZE = "edc.policy.monitor.state-machine.batch-size"; + @Setting(description = "the batch size in the policy monitor state machine. Default value " + DEFAULT_BATCH_SIZE, key = "edc.policy.monitor.state-machine.batch-size", defaultValue = DEFAULT_BATCH_SIZE + "") + private int batchSize; @Inject private ExecutorInstrumentation executorInstrumentation; @@ -89,7 +90,6 @@ public class PolicyMonitorExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var iterationWaitMillis = context.getSetting(POLICY_MONITOR_ITERATION_WAIT_MILLIS, DEFAULT_ITERATION_WAIT); var waitStrategy = new ExponentialWaitStrategy(iterationWaitMillis); policyEngine.registerScope(POLICY_MONITOR_SCOPE, PolicyMonitorContext.class); @@ -99,7 +99,7 @@ public void initialize(ServiceExtensionContext context) { manager = PolicyMonitorManagerImpl.Builder.newInstance() .clock(clock) - .batchSize(context.getSetting(POLICY_MONITOR_BATCH_SIZE, DEFAULT_BATCH_SIZE)) + .batchSize(batchSize) .waitStrategy(waitStrategy) .executorInstrumentation(executorInstrumentation) .monitor(context.getMonitor()) diff --git a/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java b/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java index 2e8d0c63350..ec21c6722f2 100644 --- a/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java +++ b/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java @@ -54,6 +54,7 @@ import java.util.Map; import static java.lang.String.format; +import static java.util.Optional.ofNullable; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; import static org.eclipse.edc.jsonld.spi.Namespaces.DCAT_PREFIX; import static org.eclipse.edc.jsonld.spi.Namespaces.DCAT_SCHEMA; @@ -81,9 +82,9 @@ public class DspApiConfigurationExtension implements ServiceExtension { public static final String NAME = "Dataspace Protocol API Configuration Extension"; - @Setting(value = "Configures endpoint for reaching the Protocol API.", defaultValue = "") - public static final String DSP_CALLBACK_ADDRESS = "edc.dsp.callback.address"; - + @Setting(description = "Configures endpoint for reaching the Protocol API in the form \"\"", key = "edc.dsp.callback.address", required = false) + private String callbackAddress; + @SettingContext("Protocol API context setting key") private static final String PROTOCOL_CONFIG_KEY = "web.http." + ApiContext.PROTOCOL; @@ -121,7 +122,9 @@ public String name() { public void initialize(ServiceExtensionContext context) { var contextConfig = context.getConfig(PROTOCOL_CONFIG_KEY); var apiConfiguration = configurator.configure(contextConfig, webServer, SETTINGS); - var dspWebhookAddress = context.getSetting(DSP_CALLBACK_ADDRESS, format("http://%s:%s%s", hostname.get(), apiConfiguration.getPort(), apiConfiguration.getPath())); + var dspWebhookAddress = ofNullable(callbackAddress).orElseGet(() -> format("http://%s:%s%s", hostname.get(), apiConfiguration.getPort(), apiConfiguration.getPath())); + + context.registerService(ProtocolWebhook.class, () -> dspWebhookAddress); var jsonLdMapper = typeManager.getMapper(JSON_LD); diff --git a/data-protocols/dsp/dsp-http-api-configuration/src/test/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtensionTest.java b/data-protocols/dsp/dsp-http-api-configuration/src/test/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtensionTest.java index 16963829939..6fff0136e54 100644 --- a/data-protocols/dsp/dsp-http-api-configuration/src/test/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtensionTest.java +++ b/data-protocols/dsp/dsp-http-api-configuration/src/test/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtensionTest.java @@ -14,6 +14,7 @@ package org.eclipse.edc.protocol.dsp.http.api.configuration; +import org.eclipse.edc.boot.system.injection.ObjectFactory; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.protocol.ProtocolWebhook; @@ -45,7 +46,6 @@ import static org.eclipse.edc.jsonld.spi.Namespaces.DCT_SCHEMA; import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX; import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; -import static org.eclipse.edc.protocol.dsp.http.api.configuration.DspApiConfigurationExtension.DSP_CALLBACK_ADDRESS; import static org.eclipse.edc.protocol.dsp.http.api.configuration.DspApiConfigurationExtension.SETTINGS; import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_SCOPE_V_08; import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_SCOPE_V_2024_1; @@ -99,13 +99,14 @@ void shouldComposeProtocolWebhook_whenNotConfigured(DspApiConfigurationExtension } @Test - void shouldUseConfiguredProtocolWebhook(DspApiConfigurationExtension extension, ServiceExtensionContext context) { + void shouldUseConfiguredProtocolWebhook(ServiceExtensionContext context, ObjectFactory factory) { var webhookAddress = "http://webhook"; when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of( "web.http.protocol.port", String.valueOf(1234), - "web.http.protocol.path", "/path")) + "web.http.protocol.path", "/path", + "edc.dsp.callback.address", webhookAddress)) ); - when(context.getSetting(eq(DSP_CALLBACK_ADDRESS), any())).thenReturn(webhookAddress); + var extension = factory.constructInstance(DspApiConfigurationExtension.class); extension.initialize(context); diff --git a/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java b/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java index f3aa5c965e3..6f4f1e3949b 100644 --- a/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java +++ b/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java @@ -45,6 +45,7 @@ import java.util.stream.Stream; import static java.lang.String.format; +import static java.util.Optional.ofNullable; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_PREFIX; import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_SCHEMA; @@ -64,8 +65,8 @@ public class ControlApiConfigurationExtension implements ServiceExtension { public static final String NAME = "Control API configuration"; - @Setting(value = "Configures endpoint for reaching the Control API. If it's missing it defaults to the hostname configuration.") - public static final String CONTROL_API_ENDPOINT = "edc.control.endpoint"; + @Setting(description = "Configures endpoint for reaching the Control API. If it's missing it defaults to the hostname configuration.", key = "edc.control.endpoint", required = false) + private String controlEndpoint; public static final String CONTROL_SCOPE = "CONTROL_API"; private static final String WEB_SERVICE_NAME = "Control API"; @SettingContext("Control API context setting key") @@ -138,7 +139,8 @@ private void registerVersionInfo(ClassLoader resourceClassLoader) { } private ControlApiUrl controlApiUrl(ServiceExtensionContext context, WebServiceConfiguration config) { - var callbackAddress = context.getSetting(CONTROL_API_ENDPOINT, format("http://%s:%s%s", hostname.get(), config.getPort(), config.getPath())); + var callbackAddress = ofNullable(controlEndpoint).orElseGet(() -> format("http://%s:%s%s", hostname.get(), config.getPort(), config.getPath())); + try { var url = URI.create(callbackAddress); return () -> url; diff --git a/extensions/common/api/control-api-configuration/src/test/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtensionTest.java b/extensions/common/api/control-api-configuration/src/test/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtensionTest.java index adec7a82ce8..0bcdd233935 100644 --- a/extensions/common/api/control-api-configuration/src/test/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtensionTest.java +++ b/extensions/common/api/control-api-configuration/src/test/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtensionTest.java @@ -15,6 +15,7 @@ package org.eclipse.edc.connector.api.control.configuration; import org.eclipse.edc.api.auth.spi.AuthenticationRequestFilter; +import org.eclipse.edc.boot.system.injection.ObjectFactory; import org.eclipse.edc.json.JacksonTypeManager; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; @@ -31,9 +32,10 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import java.util.Map; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.edc.connector.api.control.configuration.ControlApiConfigurationExtension.CONTROL_API_ENDPOINT; import static org.eclipse.edc.connector.api.control.configuration.ControlApiConfigurationExtension.CONTROL_SCOPE; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; import static org.eclipse.edc.jsonld.spi.Namespaces.DSPACE_PREFIX; @@ -43,7 +45,6 @@ import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -83,22 +84,22 @@ void shouldComposeControlApiUrl(ControlApiConfigurationExtension extension, Serv } @Test - void shouldUseConfiguredControlApiUrl(ControlApiConfigurationExtension extension, ServiceExtensionContext context) { + void shouldUseConfiguredControlApiUrl(ServiceExtensionContext context, ObjectFactory objectFactory) { var configuredEndpoint = "http://localhost:8080/test"; - when(context.getConfig()).thenReturn(ConfigFactory.empty()); - when(context.getSetting(eq(CONTROL_API_ENDPOINT), any())).thenReturn(configuredEndpoint); + when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of("edc.control.endpoint", configuredEndpoint))); - extension.initialize(context); + objectFactory.constructInstance(ControlApiConfigurationExtension.class).initialize(context); var url = context.getService(ControlApiUrl.class); assertThat(url.get().toString()).isEqualTo(configuredEndpoint); } @Test - void shouldThrowError_whenUrlIsNotValid(ControlApiConfigurationExtension extension, ServiceExtensionContext context) { + void shouldThrowError_whenUrlIsNotValid(ServiceExtensionContext context, ObjectFactory objectFactory) { var endpoint = "http:// invalid"; - when(context.getConfig()).thenReturn(ConfigFactory.empty()); - when(context.getSetting(eq(CONTROL_API_ENDPOINT), any())).thenReturn(endpoint); + when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of("edc.control.endpoint", endpoint))); + + var extension = objectFactory.constructInstance(ControlApiConfigurationExtension.class); assertThatThrownBy(() -> extension.initialize(context)).isInstanceOf(EdcException.class); } diff --git a/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java b/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java index 45b476d0dc7..9ef3e076f5e 100644 --- a/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java +++ b/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java @@ -61,6 +61,7 @@ import java.util.stream.Stream; import static java.lang.String.format; +import static java.util.Optional.ofNullable; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX; import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; @@ -91,13 +92,14 @@ public class ManagementApiConfigurationExtension implements ServiceExtension { .useDefaultContext(true) .name(WEB_SERVICE_NAME) .build(); - @Setting(value = "Configures endpoint for reaching the Management API.", defaultValue = "") - private static final String MANAGEMENT_API_ENDPOINT = "edc.management.endpoint"; + + @Setting(description = "Configures endpoint for reaching the Management API, in the format \"\"", key = "edc.management.endpoint", required = false) + private String managementApiEndpoint; private static final boolean DEFAULT_MANAGEMENT_API_ENABLE_CONTEXT = false; - @Setting(value = "If set enable the usage of management api JSON-LD context.", defaultValue = "" + DEFAULT_MANAGEMENT_API_ENABLE_CONTEXT) - private static final String MANAGEMENT_API_ENABLE_CONTEXT = "edc.management.context.enabled"; + @Setting(description = "If set enable the usage of management api JSON-LD context.", defaultValue = "" + DEFAULT_MANAGEMENT_API_ENABLE_CONTEXT, key = "edc.management.context.enabled") + private boolean managementApiContextEnabled; @Inject private WebService webService; @@ -136,9 +138,7 @@ public void initialize(ServiceExtensionContext context) { var authenticationFilter = new AuthenticationRequestFilter(authenticationRegistry, "management-api"); webService.registerResource(ApiContext.MANAGEMENT, authenticationFilter); - var isManagementContextEnabled = context.getSetting(MANAGEMENT_API_ENABLE_CONTEXT, DEFAULT_MANAGEMENT_API_ENABLE_CONTEXT); - - if (isManagementContextEnabled) { + if (managementApiContextEnabled) { jsonLd.registerContext(EDC_CONNECTOR_MANAGEMENT_CONTEXT, MANAGEMENT_SCOPE); } else { jsonLd.registerNamespace(VOCAB, EDC_NAMESPACE, MANAGEMENT_SCOPE); @@ -185,7 +185,7 @@ private void registerVersionInfo(ClassLoader resourceClassLoader) { } private ManagementApiUrl managementApiUrl(ServiceExtensionContext context, WebServiceConfiguration config) { - var callbackAddress = context.getSetting(MANAGEMENT_API_ENDPOINT, format("http://%s:%s%s", hostname.get(), config.getPort(), config.getPath())); + var callbackAddress = ofNullable(managementApiEndpoint).orElseGet(() -> format("http://%s:%s%s", hostname.get(), config.getPort(), config.getPath())); try { var url = URI.create(callbackAddress); return () -> url; diff --git a/extensions/common/api/management-api-configuration/src/test/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtensionTest.java b/extensions/common/api/management-api-configuration/src/test/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtensionTest.java index 67abaee4371..998ea0f1aed 100644 --- a/extensions/common/api/management-api-configuration/src/test/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtensionTest.java +++ b/extensions/common/api/management-api-configuration/src/test/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtensionTest.java @@ -95,12 +95,13 @@ void initialize_shouldConfigureAndRegisterResource() { } @Test - void initialize_WithContextEnabled() { - var context = contextWithConfig(ConfigFactory.fromMap(Map.of("edc.management.context.enabled", "true"))); + void initialize_withContextEnabled(ObjectFactory factory, ServiceExtensionContext context) { + when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of("edc.management.context.enabled", "true"))); + var configuration = WebServiceConfiguration.Builder.newInstance().path("/path").port(1234).build(); when(configurer.configure(any(), any(), any())).thenReturn(configuration); - extension.initialize(context); + factory.constructInstance(ManagementApiConfigurationExtension.class).initialize(context); verify(jsonLd, times(0)).registerNamespace(any(), any(), any()); verify(jsonLd).registerContext(EDC_CONNECTOR_MANAGEMENT_CONTEXT, MANAGEMENT_SCOPE); diff --git a/extensions/common/auth/auth-delegated/src/main/java/org/eclipse/edc/api/auth/delegated/DelegatedAuthenticationExtension.java b/extensions/common/auth/auth-delegated/src/main/java/org/eclipse/edc/api/auth/delegated/DelegatedAuthenticationExtension.java index 901c62708c6..04ebd41c130 100644 --- a/extensions/common/auth/auth-delegated/src/main/java/org/eclipse/edc/api/auth/delegated/DelegatedAuthenticationExtension.java +++ b/extensions/common/auth/auth-delegated/src/main/java/org/eclipse/edc/api/auth/delegated/DelegatedAuthenticationExtension.java @@ -47,21 +47,25 @@ public class DelegatedAuthenticationExtension implements ServiceExtension { public static final int DEFAULT_VALIDATION_TOLERANCE = 5_000; public static final String NAME = "Delegating Authentication Service Extension"; - @Setting(value = "Duration (in ms) that the internal key cache is valid", type = "Long", defaultValue = "" + DEFAULT_CACHE_TIME_TO_LIVE) + private static final String KEY_URL_PROPERTY = "edc.api.auth.dac.key.url"; + @Deprecated(since = "0.7.1") - public static final String AUTH_SETTING_CACHE_VALIDITY_MS = "edc.api.auth.dac.cache.validity"; + @Setting(description = "Duration (in ms) that the internal key cache is valid", defaultValue = "" + DEFAULT_CACHE_TIME_TO_LIVE, key = "edc.api.auth.dac.cache.validity", required = false) + private long cacheValidityMs; + @Deprecated(since = "0.7.1") - @Setting(value = "URL where the third-party IdP's public key(s) can be resolved") - public static final String AUTH_SETTING_KEY_URL = "edc.api.auth.dac.key.url"; + @Setting(description = "URL where the third-party IdP's public key(s) can be resolved", key = KEY_URL_PROPERTY, required = false, warnOnMissingConfig = true) + private String keyUrl; + public static final String AUTH_KEY = "auth"; public static final String CONFIG_ALIAS = WEB_HTTP_PREFIX + ".." + AUTH_KEY + "."; - @Setting(context = CONFIG_ALIAS, value = "URL where the third-party IdP's public key(s) can be resolved for the configured ") + @Setting(context = CONFIG_ALIAS, description = "URL where the third-party IdP's public key(s) can be resolved for the configured ") public static final String AUTH_KEY_URL = "dac.key.url"; - @Setting(context = CONFIG_ALIAS, value = "Duration (in ms) that the internal key cache is valid for the configured ", type = "Long", defaultValue = "" + DEFAULT_CACHE_TIME_TO_LIVE) + @Setting(context = CONFIG_ALIAS, description = "Duration (in ms) that the internal key cache is valid for the configured ", type = "Long", defaultValue = "" + DEFAULT_CACHE_TIME_TO_LIVE) public static final String AUTH_CACHE_VALIDITY_MS = "dac.cache.validity"; public static final String DELEGATED_TYPE = "delegated"; - @Setting(value = "Default token validation time tolerance (in ms), e.g. for nbf or exp claims", defaultValue = "" + DEFAULT_VALIDATION_TOLERANCE) - private static final String AUTH_SETTING_VALIDATION_TOLERANCE_MS = "edc.api.auth.dac.validation.tolerance"; + @Setting(description = "Default token validation time tolerance (in ms), e.g. for nbf or exp claims", defaultValue = "" + DEFAULT_VALIDATION_TOLERANCE, key = "edc.api.auth.dac.validation.tolerance") + private int validationTolerance; @Inject private ApiAuthenticationRegistry authenticationRegistry; @Inject @@ -84,19 +88,16 @@ public String name() { public void initialize(ServiceExtensionContext context) { var monitor = context.getMonitor().withPrefix("Delegated API Authentication"); - var keyUrl = context.getConfig().getString(AUTH_SETTING_KEY_URL, null); if (keyUrl == null) { - monitor.warning("The '%s' setting was not provided, so the DelegatedAuthenticationService will NOT be registered. In this case, the TokenBasedAuthenticationService usually acts as fallback.".formatted(AUTH_SETTING_KEY_URL)); + monitor.warning("The '%s' setting was not provided, so the DelegatedAuthenticationService will NOT be registered. In this case, the TokenBasedAuthenticationService usually acts as fallback.".formatted(KEY_URL_PROPERTY)); return; } - var cacheValidityMs = context.getConfig().getLong(AUTH_SETTING_CACHE_VALIDITY_MS, DEFAULT_CACHE_TIME_TO_LIVE); - var tolerance = context.getConfig().getInteger(AUTH_SETTING_VALIDATION_TOLERANCE_MS, DEFAULT_VALIDATION_TOLERANCE); //todo: currently, only JWKS urls are supported var resolver = JwksPublicKeyResolver.create(keyParserRegistry, keyUrl, monitor, cacheValidityMs); - tokenValidationRulesRegistry.addRule(MANAGEMENT_API_CONTEXT, new NotBeforeValidationRule(clock, tolerance, true)); - tokenValidationRulesRegistry.addRule(MANAGEMENT_API_CONTEXT, new ExpirationIssuedAtValidationRule(clock, tolerance, true)); + tokenValidationRulesRegistry.addRule(MANAGEMENT_API_CONTEXT, new NotBeforeValidationRule(clock, validationTolerance, true)); + tokenValidationRulesRegistry.addRule(MANAGEMENT_API_CONTEXT, new ExpirationIssuedAtValidationRule(clock, validationTolerance, true)); // always register - this would potentially overwrite other services authenticationRegistry.register("management-api", new DelegatedAuthenticationService(resolver, monitor, tokenValidationService, tokenValidationRulesRegistry)); diff --git a/extensions/common/auth/auth-delegated/src/test/java/org/eclipse/edc/api/auth/delegated/DelegatedAuthenticationExtensionTest.java b/extensions/common/auth/auth-delegated/src/test/java/org/eclipse/edc/api/auth/delegated/DelegatedAuthenticationExtensionTest.java index 61ddf674eb6..2a1502c8d89 100644 --- a/extensions/common/auth/auth-delegated/src/test/java/org/eclipse/edc/api/auth/delegated/DelegatedAuthenticationExtensionTest.java +++ b/extensions/common/auth/auth-delegated/src/test/java/org/eclipse/edc/api/auth/delegated/DelegatedAuthenticationExtensionTest.java @@ -15,20 +15,24 @@ package org.eclipse.edc.api.auth.delegated; import org.eclipse.edc.api.auth.spi.registry.ApiAuthenticationRegistry; +import org.eclipse.edc.boot.system.injection.ObjectFactory; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.configuration.Config; +import org.eclipse.edc.spi.system.configuration.ConfigFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import java.util.Map; + import static com.nimbusds.jose.jwk.source.JWKSourceBuilder.DEFAULT_CACHE_TIME_TO_LIVE; import static org.eclipse.edc.api.auth.delegated.DelegatedAuthenticationExtension.AUTH_CACHE_VALIDITY_MS; import static org.eclipse.edc.api.auth.delegated.DelegatedAuthenticationExtension.AUTH_KEY_URL; -import static org.eclipse.edc.api.auth.delegated.DelegatedAuthenticationExtension.AUTH_SETTING_KEY_URL; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.endsWith; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; @@ -50,12 +54,12 @@ void setUp(ServiceExtensionContext context) { } @Test - void initialize(DelegatedAuthenticationExtension extension, ServiceExtensionContext context) { + void initialize(ServiceExtensionContext context, ObjectFactory factory) { - var configMock = mock(Config.class); - when(configMock.getString(eq(AUTH_SETTING_KEY_URL), eq(null))).thenReturn("http://foo.bar/.well-known/jwks.json"); + var configMock = ConfigFactory.fromMap(Map.of("edc.api.auth.dac.key.url", "http://foo.bar/.well-known/jwks.json")); when(context.getConfig()).thenReturn(configMock); + var extension = factory.constructInstance(DelegatedAuthenticationExtension.class); extension.initialize(context); verify(registry).register(eq("management-api"), isA(DelegatedAuthenticationService.class)); @@ -66,7 +70,7 @@ void initialize_noUrlGiven_shouldNotRegister(DelegatedAuthenticationExtension ex extension.initialize(context); - verify(monitor).warning("The '%s' setting was not provided, so the DelegatedAuthenticationService will NOT be registered. In this case, the TokenBasedAuthenticationService usually acts as fallback.".formatted(AUTH_SETTING_KEY_URL)); + verify(monitor).warning(endsWith("setting was not provided, so the DelegatedAuthenticationService will NOT be registered. In this case, the TokenBasedAuthenticationService usually acts as fallback.")); verify(registry, never()).register(eq("management-api"), isA(DelegatedAuthenticationService.class)); } diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/DcpDefaultServicesExtension.java b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/DcpDefaultServicesExtension.java index afc48d4b62d..b03449c668b 100644 --- a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/DcpDefaultServicesExtension.java +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/DcpDefaultServicesExtension.java @@ -48,16 +48,22 @@ @Extension("Identity And Trust Extension to register default services") public class DcpDefaultServicesExtension implements ServiceExtension { - @Setting(value = "Alias of private key used for signing tokens, retrieved from private key resolver", defaultValue = "A random EC private key") - public static final String STS_PRIVATE_KEY_ALIAS = "edc.iam.sts.privatekey.alias"; - @Setting(value = "Id used by the counterparty to resolve the public key for token validation, e.g. did:example:123#public-key-0", defaultValue = "A random EC public key") - public static final String STS_PUBLIC_KEY_ID = "edc.iam.sts.publickey.id"; + @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 CLAIMTOKEN_VC_KEY = "vc"; // not a setting, it's defined in Oauth2ServiceExtension private static final String OAUTH_TOKENURL_PROPERTY = "edc.oauth.token.url"; - @Setting(value = "Self-issued ID Token expiration in minutes. By default is 5 minutes", defaultValue = "" + DcpDefaultServicesExtension.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 Clock clock; @Inject @@ -68,7 +74,6 @@ public class DcpDefaultServicesExtension implements ServiceExtension { @Provider(isDefault = true) public SecureTokenService createDefaultTokenService(ServiceExtensionContext context) { context.getMonitor().info("Using the Embedded STS client, as no other implementation was provided."); - var tokenExpiration = context.getSetting(STS_TOKEN_EXPIRATION, DEFAULT_STS_TOKEN_EXPIRATION_MIN); if (context.getSetting(OAUTH_TOKENURL_PROPERTY, null) != null) { @@ -77,10 +82,7 @@ public SecureTokenService createDefaultTokenService(ServiceExtensionContext cont } - var publicKeyId = context.getSetting(STS_PUBLIC_KEY_ID, null); - var privateKeyAlias = context.getSetting(STS_PRIVATE_KEY_ALIAS, null); - - return new EmbeddedSecureTokenService(new JwtGenerationService(externalSigner), () -> privateKeyAlias, () -> publicKeyId, clock, TimeUnit.MINUTES.toSeconds(tokenExpiration), jtiValidationStore); + return new EmbeddedSecureTokenService(new JwtGenerationService(externalSigner), () -> privateKeyAlias, () -> publicKeyId, clock, TimeUnit.MINUTES.toSeconds(stsTokenExpirationMin), jtiValidationStore); } @Provider(isDefault = true) diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtension.java b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtension.java index 47169c90cdb..621af09c73c 100644 --- a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtension.java +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtension.java @@ -78,17 +78,19 @@ public class IdentityAndTrustExtension implements ServiceExtension { public static final long DEFAULT_REVOCATION_CACHE_VALIDITY_MILLIS = 15 * 60 * 1000L; - @Setting(value = "Validity period of cached StatusList2021 credential entries in milliseconds.", defaultValue = DEFAULT_REVOCATION_CACHE_VALIDITY_MILLIS + "", type = "long") - public static final String REVOCATION_CACHE_VALIDITY = "edc.iam.credential.revocation.cache.validity"; - @Setting(value = "DID of this connector", required = true) - public static final String CONNECTOR_DID_PROPERTY = "edc.iam.issuer.id"; - public static final String DCP_SELF_ISSUED_TOKEN_CONTEXT = "dcp-si"; + @Setting(description = "Validity period of cached StatusList2021 credential entries in milliseconds.", defaultValue = DEFAULT_REVOCATION_CACHE_VALIDITY_MILLIS + "", key = "edc.iam.credential.revocation.cache.validity") + private long revocationCacheValidity; - public static final String JSON_2020_SIGNATURE_SUITE = "JsonWebSignature2020"; + @Setting(description = "DID of this connector", key = "edc.iam.issuer.id") + private String issuerId; + @Setting(description = "The period of the JTI entry reaper thread in seconds", defaultValue = DEFAULT_CLEANUP_PERIOD_SECONDS + "", key = "edc.sql.store.jti.cleanup.period") + private long reaperCleanupPeriod; + + public static final String DCP_SELF_ISSUED_TOKEN_CONTEXT = "dcp-si"; + public static final String JSON_2020_SIGNATURE_SUITE = "JsonWebSignature2020"; public static final long DEFAULT_CLEANUP_PERIOD_SECONDS = 60; - @Setting(value = "The period of the JTI entry reaper thread in seconds", defaultValue = DEFAULT_CLEANUP_PERIOD_SECONDS + "") - public static final String CLEANUP_PERIOD = "edc.sql.store.jti.cleanup.period"; + @Inject private SecureTokenService secureTokenService; @@ -142,7 +144,6 @@ public class IdentityAndTrustExtension implements ServiceExtension { private ExecutorInstrumentation executorInstrumentation; private PresentationVerifier presentationVerifier; private CredentialServiceClient credentialServiceClient; - private long reaperThreadPeriod; private ScheduledFuture jtiEntryReaperThread; @Override @@ -151,7 +152,7 @@ public void initialize(ServiceExtensionContext context) { // add all rules for self-issued ID tokens rulesRegistry.addRule(DCP_SELF_ISSUED_TOKEN_CONTEXT, new IssuerEqualsSubjectRule()); rulesRegistry.addRule(DCP_SELF_ISSUED_TOKEN_CONTEXT, new SubJwkIsNullRule()); - rulesRegistry.addRule(DCP_SELF_ISSUED_TOKEN_CONTEXT, new AudienceValidationRule(getOwnDid(context))); + rulesRegistry.addRule(DCP_SELF_ISSUED_TOKEN_CONTEXT, new AudienceValidationRule(issuerId)); rulesRegistry.addRule(DCP_SELF_ISSUED_TOKEN_CONTEXT, new ExpirationIssuedAtValidationRule(clock, 5)); rulesRegistry.addRule(DCP_SELF_ISSUED_TOKEN_CONTEXT, new TokenNotNullRule()); @@ -161,7 +162,6 @@ public void initialize(ServiceExtensionContext context) { // TODO move in a separated extension? signatureSuiteRegistry.register(JSON_2020_SIGNATURE_SUITE, new Jws2020SignatureSuite(typeManager.getMapper(JSON_LD))); - reaperThreadPeriod = context.getSetting(CLEANUP_PERIOD, DEFAULT_CLEANUP_PERIOD_SECONDS); try { jsonLd.registerCachedDocument(STATUSLIST_2021_URL, getClass().getClassLoader().getResource("statuslist2021.json").toURI()); @@ -172,15 +172,14 @@ public void initialize(ServiceExtensionContext context) { participantAgentService.register(participantAgentServiceExtension); // register revocation services - var validity = context.getConfig().getLong(REVOCATION_CACHE_VALIDITY, DEFAULT_REVOCATION_CACHE_VALIDITY_MILLIS); - revocationServiceRegistry.addService(StatusList2021Status.TYPE, new StatusList2021RevocationService(typeManager.getMapper(), validity)); - revocationServiceRegistry.addService(BitstringStatusListStatus.TYPE, new BitstringStatusListRevocationService(typeManager.getMapper(), validity)); + revocationServiceRegistry.addService(StatusList2021Status.TYPE, new StatusList2021RevocationService(typeManager.getMapper(), revocationCacheValidity)); + revocationServiceRegistry.addService(BitstringStatusListStatus.TYPE, new BitstringStatusListRevocationService(typeManager.getMapper(), revocationCacheValidity)); } @Override public void start() { jtiEntryReaperThread = executorInstrumentation.instrument(Executors.newSingleThreadScheduledExecutor(), "JTI Validation Entry Reaper Thread") - .scheduleAtFixedRate(jtiValidationStore::deleteExpired, reaperThreadPeriod, reaperThreadPeriod, TimeUnit.SECONDS); + .scheduleAtFixedRate(jtiValidationStore::deleteExpired, reaperCleanupPeriod, reaperCleanupPeriod, TimeUnit.SECONDS); } @Override @@ -196,7 +195,7 @@ public IdentityService createIdentityService(ServiceExtensionContext context) { var credentialValidationService = new VerifiableCredentialValidationServiceImpl(createPresentationVerifier(context), trustedIssuerRegistry, revocationServiceRegistry, clock); - return new IdentityAndTrustService(secureTokenService, getOwnDid(context), + return new IdentityAndTrustService(secureTokenService, issuerId, getCredentialServiceClient(context), validationAction, credentialServiceUrlResolver, claimTokenFunction, credentialValidationService); } @@ -223,7 +222,7 @@ public PresentationVerifier createPresentationVerifier(ServiceExtensionContext c .methodResolver(new DidMethodResolver(didResolverRegistry)) .build(); - presentationVerifier = new MultiFormatPresentationVerifier(getOwnDid(context), jwtVerifier, ldpVerifier); + presentationVerifier = new MultiFormatPresentationVerifier(issuerId, jwtVerifier, ldpVerifier); } return presentationVerifier; } @@ -237,12 +236,5 @@ private TokenValidationAction tokenValidationAction() { }; } - private String getOwnDid(ServiceExtensionContext context) { - var ownDid = context.getConfig().getString(CONNECTOR_DID_PROPERTY, null); - if (ownDid == null) { - context.getMonitor().severe("Mandatory config value missing: '%s'. This runtime will not be fully operational!".formatted(CONNECTOR_DID_PROPERTY)); - } - return ownDid; - } } diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/DcpDefaultServicesExtensionTest.java b/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/DcpDefaultServicesExtensionTest.java index 377e06170ee..9a26084c719 100644 --- a/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/DcpDefaultServicesExtensionTest.java +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/DcpDefaultServicesExtensionTest.java @@ -26,17 +26,17 @@ import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.configuration.ConfigFactory; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import java.security.PrivateKey; +import java.util.Map; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; -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; @@ -59,18 +59,20 @@ private static PrivateKey privateKey() throws JOSEException { @BeforeEach void setup(ServiceExtensionContext context) throws JOSEException { + var publicKeyId = "did:web:" + UUID.randomUUID() + "#key-id"; + var privateKeyAlias = "private"; + var config = ConfigFactory.fromMap(Map.of("edc.iam.sts.publickey.id", publicKeyId, "edc.iam.sts.privatekey.alias", privateKeyAlias)); + when(context.getConfig()).thenReturn(config); when(privateKeyResolver.resolvePrivateKey(any())).thenReturn(Result.success(privateKey())); context.registerService(PrivateKeyResolver.class, privateKeyResolver); } @Test void verify_defaultService(ServiceExtensionContext context, DcpDefaultServicesExtension ext) { - var publicKeyId = "did:web:" + UUID.randomUUID() + "#key-id"; - var privateKeyAlias = "private"; + Monitor mockedMonitor = mock(); context.registerService(Monitor.class, mockedMonitor); - when(context.getSetting(STS_PUBLIC_KEY_ID, null)).thenReturn(publicKeyId); - when(context.getSetting(STS_PRIVATE_KEY_ALIAS, null)).thenReturn(privateKeyAlias); + var sts = ext.createDefaultTokenService(context); assertThat(sts).isInstanceOf(EmbeddedSecureTokenService.class); diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtensionTest.java b/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtensionTest.java index d3d2fe55da8..15601ad0485 100644 --- a/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtensionTest.java +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtensionTest.java @@ -14,6 +14,7 @@ package org.eclipse.edc.iam.identitytrust.core; +import org.eclipse.edc.boot.system.injection.ObjectFactory; import org.eclipse.edc.iam.identitytrust.service.IdentityAndTrustService; import org.eclipse.edc.iam.identitytrust.spi.SecureTokenService; import org.eclipse.edc.json.JacksonTypeManager; @@ -21,20 +22,17 @@ import org.eclipse.edc.jwt.validation.jti.JtiValidationStore; import org.eclipse.edc.spi.system.ExecutorInstrumentation; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.configuration.Config; +import org.eclipse.edc.spi.system.configuration.ConfigFactory; import org.eclipse.edc.spi.types.TypeManager; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import java.time.Duration; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.eclipse.edc.iam.identitytrust.core.IdentityAndTrustExtension.CLEANUP_PERIOD; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -43,6 +41,8 @@ @ExtendWith(DependencyInjectionExtension.class) class IdentityAndTrustExtensionTest { + private static final String CONNECTOR_DID_PROPERTY = "edc.iam.issuer.id"; + private static final String CLEANUP_PERIOD = "edc.sql.store.jti.cleanup.period"; private final JtiValidationStore storeMock = mock(); @BeforeEach @@ -51,24 +51,26 @@ void setUp(ServiceExtensionContext context) { context.registerService(TypeManager.class, new JacksonTypeManager()); context.registerService(JtiValidationStore.class, storeMock); context.registerService(ExecutorInstrumentation.class, ExecutorInstrumentation.noop()); + + var config = ConfigFactory.fromMap(Map.of( + CONNECTOR_DID_PROPERTY, "did:web:test", + CLEANUP_PERIOD, "1" + )); + when(context.getConfig()).thenReturn(config); } @Test - void verifyCorrectService(IdentityAndTrustExtension extension, ServiceExtensionContext context) { - var configMock = mock(Config.class); - when(configMock.getString(eq(IdentityAndTrustExtension.CONNECTOR_DID_PROPERTY), isNull())).thenReturn("did:web:test"); - when(context.getConfig()).thenReturn(configMock); + void verifyCorrectService(ServiceExtensionContext context, ObjectFactory objectFactory) { + - var is = extension.createIdentityService(context); + var is = objectFactory.constructInstance(IdentityAndTrustExtension.class).createIdentityService(context); assertThat(is).isInstanceOf(IdentityAndTrustService.class); - verify(configMock, atLeastOnce()).getString(eq(IdentityAndTrustExtension.CONNECTOR_DID_PROPERTY), isNull()); } @Test - void assertReaperThreadRunning(IdentityAndTrustExtension extension, ServiceExtensionContext context) { - when(context.getSetting(eq(CLEANUP_PERIOD), anyLong())).thenReturn(1L); - + void assertReaperThreadRunning(ServiceExtensionContext context, ObjectFactory objectFactory) { + var extension = objectFactory.constructInstance(IdentityAndTrustExtension.class); extension.initialize(context); extension.start(); diff --git a/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-accounts-api/src/main/java/org/eclipse/edc/api/iam/identitytrust/sts/accounts/StsAccountsApiExtension.java b/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-accounts-api/src/main/java/org/eclipse/edc/api/iam/identitytrust/sts/accounts/StsAccountsApiExtension.java index 3944bb31adb..a3d3e16d06d 100644 --- a/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-accounts-api/src/main/java/org/eclipse/edc/api/iam/identitytrust/sts/accounts/StsAccountsApiExtension.java +++ b/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-accounts-api/src/main/java/org/eclipse/edc/api/iam/identitytrust/sts/accounts/StsAccountsApiExtension.java @@ -36,8 +36,8 @@ public class StsAccountsApiExtension implements ServiceExtension { public static final String NAME = "Secure Token Service Accounts API Extension"; public static final String STS_ACCOUNTS_API_CONTEXT = "sts-accounts-api"; - @Setting(value = "API key (or Vault alias) for the STS Accounts API's default authentication mechanism (token-based).") - public static final String STS_ACCOUNTS_API_KEY = "edc.api.accounts.key"; + @Setting(description = "API key (or Vault alias) for the STS Accounts API's default authentication mechanism (token-based).", key = "edc.api.accounts.key") + private String accountsApiKeyOrAlias; @Inject private StsAccountService clientService; @@ -68,8 +68,7 @@ public void initialize(ServiceExtensionContext context) { } private String resolveApiKey(ServiceExtensionContext context) { - var keyOrAlias = context.getConfig().getString(STS_ACCOUNTS_API_KEY); - return ofNullable(vault.resolveSecret(keyOrAlias)) - .orElse(keyOrAlias); + return ofNullable(vault.resolveSecret(accountsApiKeyOrAlias)) + .orElse(accountsApiKeyOrAlias); } } diff --git a/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-accounts-api/src/test/java/org/eclipse/edc/api/iam/identitytrust/sts/accounts/StsAccountsApiExtensionTest.java b/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-accounts-api/src/test/java/org/eclipse/edc/api/iam/identitytrust/sts/accounts/StsAccountsApiExtensionTest.java index 2b9864c2705..dba1903f2a4 100644 --- a/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-accounts-api/src/test/java/org/eclipse/edc/api/iam/identitytrust/sts/accounts/StsAccountsApiExtensionTest.java +++ b/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-accounts-api/src/test/java/org/eclipse/edc/api/iam/identitytrust/sts/accounts/StsAccountsApiExtensionTest.java @@ -22,13 +22,15 @@ import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.configuration.Config; +import org.eclipse.edc.spi.system.configuration.ConfigFactory; import org.eclipse.edc.web.spi.WebService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import java.util.Map; + import static org.eclipse.edc.api.iam.identitytrust.sts.accounts.StsAccountsApiExtension.STS_ACCOUNTS_API_CONTEXT; -import static org.eclipse.edc.api.iam.identitytrust.sts.accounts.StsAccountsApiExtension.STS_ACCOUNTS_API_KEY; import static org.eclipse.edc.web.spi.configuration.ApiContext.STS_ACCOUNTS; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; @@ -40,6 +42,7 @@ @ExtendWith(DependencyInjectionExtension.class) class StsAccountsApiExtensionTest { + private static final String STS_ACCOUNTS_API_KEY = "edc.api.accounts.key"; private final ApiAuthenticationRegistry apiAuthenticationRegistry = mock(); private final WebService webService = mock(); private final Vault vault = mock(); @@ -49,6 +52,9 @@ void setUp(ServiceExtensionContext context) { context.registerService(ApiAuthenticationRegistry.class, apiAuthenticationRegistry); context.registerService(WebService.class, webService); context.registerService(Vault.class, vault); + + var config = ConfigFactory.fromMap(Map.of(STS_ACCOUNTS_API_KEY, "test-api-key")); + when(context.getConfig()).thenReturn(config); } @Test @@ -69,10 +75,7 @@ void initialize_noAuthServicePresent_withApiKeyInVault(StsAccountsApiExtension e @Test void initialize_noAuthServicePresent_withApiKeyInConfig(StsAccountsApiExtension extension, ServiceExtensionContext context) { - var config = mock(Config.class); - when(config.getString(eq(STS_ACCOUNTS_API_KEY))) - .thenReturn("test-api-key"); - when(context.getConfig()).thenReturn(config); + when(apiAuthenticationRegistry.hasService(eq(STS_ACCOUNTS_API_CONTEXT))).thenReturn(false); extension.initialize(context); @@ -85,10 +88,6 @@ void initialize_noAuthServicePresent_withApiKeyInConfig(StsAccountsApiExtension @Test void initialize_otherAuthServicePresent_withApiKeyInConfig(StsAccountsApiExtension extension, ServiceExtensionContext context) { - var config = mock(Config.class); - when(config.getString(eq(STS_ACCOUNTS_API_KEY))) - .thenReturn("test-api-key"); - when(context.getConfig()).thenReturn(config); when(apiAuthenticationRegistry.hasService(eq(STS_ACCOUNTS_API_CONTEXT))).thenReturn(true); extension.initialize(context); diff --git a/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-core/src/main/java/org/eclipse/edc/iam/identitytrust/sts/defaults/StsDefaultServicesExtension.java b/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-core/src/main/java/org/eclipse/edc/iam/identitytrust/sts/defaults/StsDefaultServicesExtension.java index 42e051bd5a7..7106502c1ac 100644 --- a/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-core/src/main/java/org/eclipse/edc/iam/identitytrust/sts/defaults/StsDefaultServicesExtension.java +++ b/extensions/common/iam/identity-trust/identity-trust-sts/identity-trust-sts-core/src/main/java/org/eclipse/edc/iam/identitytrust/sts/defaults/StsDefaultServicesExtension.java @@ -43,8 +43,8 @@ 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 + @Setting(description = "Self-issued ID Token expiration in minutes. By default is 5 minutes", defaultValue = "" + StsDefaultServicesExtension.DEFAULT_STS_TOKEN_EXPIRATION_MIN, key = "edc.iam.sts.token.expiration") + private int tokenExpirationMinutes; private static final int DEFAULT_STS_TOKEN_EXPIRATION_MIN = 5; @@ -75,12 +75,11 @@ public String name() { @Provider public StsClientTokenGeneratorService clientTokenService(ServiceExtensionContext context) { - var tokenExpiration = context.getSetting(STS_TOKEN_EXPIRATION, DEFAULT_STS_TOKEN_EXPIRATION_MIN); return new StsClientTokenGeneratorServiceImpl( (client) -> new JwtGenerationService(jwsSignerProvider), StsAccount::getPrivateKeyAlias, clock, - TimeUnit.MINUTES.toSeconds(tokenExpiration), + TimeUnit.MINUTES.toSeconds(tokenExpirationMinutes), jtiValidationStore); } diff --git a/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceConfiguration.java b/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceConfiguration.java index 9ba6cf73913..f28200348b5 100644 --- a/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceConfiguration.java +++ b/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceConfiguration.java @@ -16,21 +16,40 @@ package org.eclipse.edc.iam.oauth2; import org.eclipse.edc.iam.oauth2.identity.Oauth2ServiceImpl; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.runtime.metamodel.annotation.Settings; /** * Configuration values and dependencies for {@link Oauth2ServiceImpl}. */ +@Settings public class Oauth2ServiceConfiguration { + static final String ISSUED_AT_LEEWAY = "edc.oauth.validation.issued.at.leeway"; + private static final int DEFAULT_TOKEN_EXPIRATION = 5; + @Setting(description = "URL to obtain OAuth2 JSON Web Key Sets", key = "edc.oauth.provider.jwks.url", defaultValue = "http://localhost/empty_jwks_url") + private String jwksUrl; + @Setting(description = "OAuth2 Token URL", key = "edc.oauth.token.url") private String tokenUrl; + @Setting(description = "OAuth2 client ID", key = "edc.oauth.client.id") private String clientId; + @Setting(description = "Vault alias for the private key", key = "edc.oauth.private.key.alias") private String privateKeyAlias; + @Setting(description = "Vault alias for the certificate", key = "edc.oauth.certificate.alias") private String publicCertificateAlias; + @Setting(description = "outgoing tokens 'aud' claim value, by default it's the connector id", key = "edc.oauth.provider.audience", required = false) private String providerAudience; + @Setting(description = "Leeway in seconds for validating the not before (nbf) claim in the token.", defaultValue = "10", key = "edc.oauth.validation.nbf.leeway") private int notBeforeValidationLeeway; + @Setting(description = "Leeway in seconds for validating the issuedAt claim in the token. By default it is 0 seconds.", defaultValue = "0", key = ISSUED_AT_LEEWAY) private int issuedAtLeeway; + @Setting(description = "incoming tokens 'aud' claim required value, by default it's the provider audience value", key = "edc.oauth.endpoint.audience", required = false) private String endpointAudience; + @Setting(description = "Refresh time for the JWKS, in minutes", key = "edc.oauth.provider.jwks.refresh", defaultValue = "5") + private int providerJwksRefresh; // in minutes + + @Setting(description = "Token expiration in minutes. By default is 5 minutes", key = "edc.oauth.token.expiration", defaultValue = DEFAULT_TOKEN_EXPIRATION + "") private Long tokenExpiration; private Oauth2ServiceConfiguration() { @@ -73,14 +92,27 @@ public Long getTokenExpiration() { return tokenExpiration; } + public int getProviderJwksRefresh() { + return providerJwksRefresh; + } + + public String getJwksUrl() { + return jwksUrl; + } + + public Builder toBuilder() { + return new Builder(this); + } + public static class Builder { - private final Oauth2ServiceConfiguration configuration = new Oauth2ServiceConfiguration(); + private final Oauth2ServiceConfiguration configuration; - private Builder() { + private Builder(Oauth2ServiceConfiguration configuration) { + this.configuration = configuration; } public static Builder newInstance() { - return new Builder(); + return new Builder(new Oauth2ServiceConfiguration()); } public Builder tokenUrl(String url) { diff --git a/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceExtension.java b/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceExtension.java index c6f9ef8e856..94aa811778a 100644 --- a/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceExtension.java +++ b/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceExtension.java @@ -25,12 +25,13 @@ import org.eclipse.edc.jwt.signer.spi.JwsSignerProvider; import org.eclipse.edc.keys.spi.CertificateResolver; import org.eclipse.edc.keys.spi.PrivateKeyResolver; +import org.eclipse.edc.runtime.metamodel.annotation.Configuration; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provides; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.iam.IdentityService; +import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; @@ -44,45 +45,22 @@ import org.jetbrains.annotations.NotNull; import java.time.Clock; -import java.util.Optional; -import java.util.concurrent.TimeUnit; import java.util.function.Supplier; -import static java.lang.String.format; +import static java.util.Optional.ofNullable; /** * Provides OAuth2 client credentials flow support. */ -@Provides({IdentityService.class}) +@Provides({ IdentityService.class }) @Extension(value = Oauth2ServiceExtension.NAME) public class Oauth2ServiceExtension implements ServiceExtension { public static final String NAME = "OAuth2 Identity Service"; public static final String OAUTH2_TOKEN_CONTEXT = "oauth2"; - private static final int DEFAULT_TOKEN_EXPIRATION = 5; - @Setting - private static final String PROVIDER_JWKS_URL = "edc.oauth.provider.jwks.url"; - @Setting(value = "outgoing tokens 'aud' claim value, by default it's the connector id") - private static final String PROVIDER_AUDIENCE = "edc.oauth.provider.audience"; - @Setting(value = "incoming tokens 'aud' claim required value, by default it's the provider audience value") - private static final String ENDPOINT_AUDIENCE = "edc.oauth.endpoint.audience"; - - @Setting - private static final String PUBLIC_CERTIFICATE_ALIAS = "edc.oauth.certificate.alias"; - @Setting - private static final String PRIVATE_KEY_ALIAS = "edc.oauth.private.key.alias"; - @Setting - private static final String PROVIDER_JWKS_REFRESH = "edc.oauth.provider.jwks.refresh"; // in minutes - @Setting - private static final String TOKEN_URL = "edc.oauth.token.url"; - @Setting(value = "Token expiration in minutes. By default is 5 minutes") - private static final String TOKEN_EXPIRATION = "edc.oauth.token.expiration"; // in minutes - @Setting - private static final String CLIENT_ID = "edc.oauth.client.id"; - @Setting(value = "Leeway in seconds for validating the not before (nbf) claim in the token.", defaultValue = "10", type = "int") - private static final String NOT_BEFORE_LEEWAY = "edc.oauth.validation.nbf.leeway"; - @Setting(value = "Leeway in seconds for validating the issuedAt claim in the token. By default it is 0 seconds.", defaultValue = "0", type = "int") - private static final String ISSUED_AT_LEEWAY = "edc.oauth.validation.issued.at.leeway"; + + @Configuration + private Oauth2ServiceConfiguration config; private IdentityProviderKeyResolver providerKeyResolver; @Inject @@ -121,27 +99,36 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var configuration = createConfig(context); + config = withDefaults(config, context); + warnIfNoLeeway(config, context.getMonitor()); - var certificate = Optional.ofNullable(certificateResolver.resolveCertificate(configuration.getPublicCertificateAlias())) - .orElseThrow(() -> new EdcException("Public certificate not found: " + configuration.getPublicCertificateAlias())); + var certificate = ofNullable(certificateResolver.resolveCertificate(config.getPublicCertificateAlias())) + .orElseThrow(() -> new EdcException("Public certificate not found: " + config.getPublicCertificateAlias())); jwtDecoratorRegistry.register(OAUTH2_TOKEN_CONTEXT, Oauth2AssertionDecorator.Builder.newInstance() - .audience(configuration.getProviderAudience()) - .clientId(configuration.getClientId()) + .audience(config.getProviderAudience()) + .clientId(config.getClientId()) .clock(clock) - .validity(configuration.getTokenExpiration()) + .validity(config.getTokenExpiration()) .build()); jwtDecoratorRegistry.register(OAUTH2_TOKEN_CONTEXT, new X509CertificateDecorator(certificate)); providerKeyResolver = identityProviderKeyResolver(context); - var oauth2Service = createOauth2Service(configuration, jwtDecoratorRegistry, providerKeyResolver); + var oauth2Service = createOauth2Service(config, jwtDecoratorRegistry, providerKeyResolver); context.registerService(IdentityService.class, oauth2Service); // add oauth2-specific validation rules - tokenValidationRulesRegistry.addRule(OAUTH2_TOKEN_CONTEXT, new AudienceValidationRule(configuration.getEndpointAudience())); - tokenValidationRulesRegistry.addRule(OAUTH2_TOKEN_CONTEXT, new NotBeforeValidationRule(clock, configuration.getNotBeforeValidationLeeway())); - tokenValidationRulesRegistry.addRule(OAUTH2_TOKEN_CONTEXT, new ExpirationIssuedAtValidationRule(clock, configuration.getIssuedAtLeeway())); + tokenValidationRulesRegistry.addRule(OAUTH2_TOKEN_CONTEXT, new AudienceValidationRule(config.getEndpointAudience())); + tokenValidationRulesRegistry.addRule(OAUTH2_TOKEN_CONTEXT, new NotBeforeValidationRule(clock, config.getNotBeforeValidationLeeway())); + tokenValidationRulesRegistry.addRule(OAUTH2_TOKEN_CONTEXT, new ExpirationIssuedAtValidationRule(clock, config.getIssuedAtLeeway())); + } + + private Oauth2ServiceConfiguration withDefaults(Oauth2ServiceConfiguration config, ServiceExtensionContext context) { + var providerAudience = ofNullable(config.getProviderAudience()).orElseGet(context::getComponentId); + return config.toBuilder() + .providerAudience(providerAudience) + .endpointAudience(ofNullable(config.getEndpointAudience()).orElse(providerAudience)) + .build(); } @Override @@ -155,9 +142,7 @@ public void shutdown() { } private IdentityProviderKeyResolver identityProviderKeyResolver(ServiceExtensionContext context) { - var jwksUrl = context.getSetting(PROVIDER_JWKS_URL, "http://localhost/empty_jwks_url"); - var keyRefreshInterval = context.getSetting(PROVIDER_JWKS_REFRESH, 5); - return new IdentityProviderKeyResolver(context.getMonitor(), httpClient, typeManager, jwksUrl, keyRefreshInterval); + return new IdentityProviderKeyResolver(context.getMonitor(), httpClient, typeManager, config.getJwksUrl(), config.getProviderJwksRefresh()); } @NotNull @@ -167,7 +152,7 @@ private Oauth2ServiceImpl createOauth2Service(Oauth2ServiceConfiguration configu Supplier privateKeySupplier = configuration::getPrivateKeyAlias; return new Oauth2ServiceImpl( - configuration, + configuration.getTokenUrl(), new JwtGenerationService(jwsSignerProvider), privateKeySupplier, oauth2Client, @@ -178,37 +163,11 @@ private Oauth2ServiceImpl createOauth2Service(Oauth2ServiceConfiguration configu ); } - private Oauth2ServiceConfiguration createConfig(ServiceExtensionContext context) { - var providerAudience = context.getSetting(PROVIDER_AUDIENCE, context.getComponentId()); - var endpointAudience = context.getSetting(ENDPOINT_AUDIENCE, providerAudience); - var tokenUrl = context.getConfig().getString(TOKEN_URL); - var publicCertificateAlias = context.getConfig().getString(PUBLIC_CERTIFICATE_ALIAS); - var privateKeyAlias = context.getConfig().getString(PRIVATE_KEY_ALIAS); - var clientId = context.getConfig().getString(CLIENT_ID); - var tokenExpiration = context.getSetting(TOKEN_EXPIRATION, DEFAULT_TOKEN_EXPIRATION); - return Oauth2ServiceConfiguration.Builder.newInstance() - .tokenUrl(tokenUrl) - .providerAudience(providerAudience) - .endpointAudience(endpointAudience) - .publicCertificateAlias(publicCertificateAlias) - .privateKeyAlias(privateKeyAlias) - .clientId(clientId) - .notBeforeValidationLeeway(context.getSetting(NOT_BEFORE_LEEWAY, 10)) - .issuedAtLeeway(getIssuedAtLeeway(context)) - .tokenExpiration(TimeUnit.MINUTES.toSeconds(tokenExpiration)) - .build(); - } - - private int getIssuedAtLeeway(ServiceExtensionContext context) { - if (!context.getConfig().hasKey(ISSUED_AT_LEEWAY)) { - var message = format( - "No value was configured for '%s'. Consider setting a leeway of 2-5s in production to avoid problems with clock skew.", - ISSUED_AT_LEEWAY - ); - context.getMonitor().info(message); + private void warnIfNoLeeway(Oauth2ServiceConfiguration configuration, Monitor monitor) { + if (configuration.getIssuedAtLeeway() == 0) { + var message = "No value was configured for '%s'. Consider setting a leeway of 2-5s in production to avoid problems with clock skew.".formatted(Oauth2ServiceConfiguration.ISSUED_AT_LEEWAY); + monitor.info(message); } - - return context.getSetting(ISSUED_AT_LEEWAY, 0); } } diff --git a/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/identity/Oauth2ServiceImpl.java b/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/identity/Oauth2ServiceImpl.java index 7300bb8ce82..6c0eb800e38 100644 --- a/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/identity/Oauth2ServiceImpl.java +++ b/extensions/common/iam/oauth2/oauth2-core/src/main/java/org/eclipse/edc/iam/oauth2/identity/Oauth2ServiceImpl.java @@ -17,7 +17,6 @@ package org.eclipse.edc.iam.oauth2.identity; -import org.eclipse.edc.iam.oauth2.Oauth2ServiceConfiguration; import org.eclipse.edc.iam.oauth2.spi.client.Oauth2Client; import org.eclipse.edc.iam.oauth2.spi.client.Oauth2CredentialsRequest; import org.eclipse.edc.iam.oauth2.spi.client.PrivateKeyOauth2CredentialsRequest; @@ -47,7 +46,7 @@ public class Oauth2ServiceImpl implements IdentityService { private static final String GRANT_TYPE = "client_credentials"; - private final Oauth2ServiceConfiguration configuration; + private final String tokenUrl; private final Supplier privateKeySupplier; private final Oauth2Client client; private final TokenDecoratorRegistry jwtDecoratorRegistry; @@ -59,16 +58,16 @@ public class Oauth2ServiceImpl implements IdentityService { /** * Creates a new instance of the OAuth2 Service * - * @param configuration The configuration + * @param tokenUrl Token URL * @param tokenGenerationService Service used to generate the signed tokens * @param client client for Oauth2 server * @param jwtDecoratorRegistry Registry containing the decorator for build the JWT * @param tokenValidationService Service used for token validation */ - public Oauth2ServiceImpl(Oauth2ServiceConfiguration configuration, TokenGenerationService tokenGenerationService, Supplier privateKeyIdSupplier, + public Oauth2ServiceImpl(String tokenUrl, TokenGenerationService tokenGenerationService, Supplier privateKeyIdSupplier, Oauth2Client client, TokenDecoratorRegistry jwtDecoratorRegistry, TokenValidationRulesRegistry tokenValidationRuleRegistry, TokenValidationService tokenValidationService, PublicKeyResolver publicKeyResolver) { - this.configuration = configuration; + this.tokenUrl = tokenUrl; this.privateKeySupplier = privateKeyIdSupplier; this.client = client; this.jwtDecoratorRegistry = jwtDecoratorRegistry; @@ -100,7 +99,7 @@ private Result generateClientAssertion() { @NotNull private Oauth2CredentialsRequest createRequest(TokenParameters parameters, String assertion) { return PrivateKeyOauth2CredentialsRequest.Builder.newInstance() - .url(configuration.getTokenUrl()) + .url(tokenUrl) .clientAssertion(assertion) .scope(parameters.getStringClaim(JwtRegisteredClaimNames.SCOPE)) .grantType(GRANT_TYPE) diff --git a/extensions/common/iam/oauth2/oauth2-core/src/test/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceExtensionTest.java b/extensions/common/iam/oauth2/oauth2-core/src/test/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceExtensionTest.java index 88970f1348f..58d29e79b4a 100644 --- a/extensions/common/iam/oauth2/oauth2-core/src/test/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceExtensionTest.java +++ b/extensions/common/iam/oauth2/oauth2-core/src/test/java/org/eclipse/edc/iam/oauth2/Oauth2ServiceExtensionTest.java @@ -15,6 +15,7 @@ package org.eclipse.edc.iam.oauth2; +import org.eclipse.edc.boot.system.injection.ObjectFactory; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.keys.spi.CertificateResolver; import org.eclipse.edc.keys.spi.PrivateKeyResolver; @@ -53,7 +54,7 @@ void setup(ServiceExtensionContext context) { } @Test - void verifyExtensionWithCertificateAlias(Oauth2ServiceExtension extension, ServiceExtensionContext context) { + void verifyExtensionWithCertificateAlias(ServiceExtensionContext context, ObjectFactory objectFactory) { var config = spy(ConfigFactory.fromMap(Map.of( "edc.oauth.client.id", "id", "edc.oauth.token.url", "url", @@ -63,14 +64,14 @@ void verifyExtensionWithCertificateAlias(Oauth2ServiceExtension extension, Servi mockRsaPrivateKey("p_alias"); when(context.getConfig(any())).thenReturn(config); - extension.initialize(context); + objectFactory.constructInstance(Oauth2ServiceExtension.class).initialize(context); verify(config, times(1)).getString("edc.oauth.certificate.alias"); verify(config, never()).getString("edc.oauth.public.key.alias"); } @Test - void leewayWarningLoggedWhenLeewayUnconfigured(Oauth2ServiceExtension extension, ServiceExtensionContext context) { + void leewayWarningLoggedWhenLeewayUnconfigured(ServiceExtensionContext context, ObjectFactory objectFactory) { var config = spy(ConfigFactory.fromMap(Map.of( "edc.oauth.client.id", "id", "edc.oauth.token.url", "url", @@ -81,15 +82,15 @@ void leewayWarningLoggedWhenLeewayUnconfigured(Oauth2ServiceExtension extension, var monitor = mock(Monitor.class); when(context.getMonitor()).thenReturn(monitor); - when(context.getConfig(any())).thenReturn(config); - extension.initialize(context); + when(context.getConfig()).thenReturn(config); + objectFactory.constructInstance(Oauth2ServiceExtension.class).initialize(context); var message = "No value was configured for 'edc.oauth.validation.issued.at.leeway'."; verify(monitor, times(1)).info(contains(message)); } @Test - void leewayNoWarningWhenLeewayConfigured(Oauth2ServiceExtension extension, ServiceExtensionContext context) { + void leewayNoWarningWhenLeewayConfigured(ServiceExtensionContext context, ObjectFactory objectFactory) { var config = spy(ConfigFactory.fromMap(Map.of( "edc.oauth.client.id", "id", "edc.oauth.token.url", "url", @@ -102,7 +103,7 @@ void leewayNoWarningWhenLeewayConfigured(Oauth2ServiceExtension extension, Servi var monitor = mock(Monitor.class); when(context.getMonitor()).thenReturn(monitor); when(context.getConfig(any())).thenReturn(config); - extension.initialize(context); + objectFactory.constructInstance(Oauth2ServiceExtension.class).initialize(context); var message = "No value was configured for 'edc.oauth.validation.issued.at.leeway'."; verify(monitor, never()).info(contains(message)); diff --git a/extensions/common/iam/oauth2/oauth2-core/src/test/java/org/eclipse/edc/iam/oauth2/identity/Oauth2ServiceImplTest.java b/extensions/common/iam/oauth2/oauth2-core/src/test/java/org/eclipse/edc/iam/oauth2/identity/Oauth2ServiceImplTest.java index 05988d9cc57..ec09c37f048 100644 --- a/extensions/common/iam/oauth2/oauth2-core/src/test/java/org/eclipse/edc/iam/oauth2/identity/Oauth2ServiceImplTest.java +++ b/extensions/common/iam/oauth2/oauth2-core/src/test/java/org/eclipse/edc/iam/oauth2/identity/Oauth2ServiceImplTest.java @@ -52,7 +52,6 @@ import java.time.Clock; import java.time.Instant; import java.util.Date; -import java.util.Map; import java.util.UUID; import static com.nimbusds.jwt.JWTClaimNames.AUDIENCE; @@ -114,7 +113,7 @@ void setUp() throws JOSEException { registry.addRule(OAUTH2_TOKEN_CONTEXT, new NotBeforeValidationRule(Clock.systemUTC(), configuration.getNotBeforeValidationLeeway())); registry.addRule(OAUTH2_TOKEN_CONTEXT, new ExpirationIssuedAtValidationRule(Clock.systemUTC(), configuration.getIssuedAtLeeway())); - authService = new Oauth2ServiceImpl(configuration, tokenGenerationService, () -> TEST_PRIVATE_KEY_ID, client, jwtDecoratorRegistry, registry, + authService = new Oauth2ServiceImpl(configuration.getTokenUrl(), tokenGenerationService, () -> TEST_PRIVATE_KEY_ID, client, jwtDecoratorRegistry, registry, tokenValidationService, publicKeyResolverMock); } @@ -214,15 +213,6 @@ void verifyValidJwt() { assertThat(result.getContent().getClaims()).hasSize(3).containsKeys(AUDIENCE, NOT_BEFORE, EXPIRATION_TIME); } - private PrivateKeyOauth2CredentialsRequest createRequest(Map additional) { - return PrivateKeyOauth2CredentialsRequest.Builder.newInstance() - .grantType("client_credentials") - .clientAssertion("assertion-token") - .scope("scope") - .params(additional) - .build(); - } - private RSAKey testKey() throws JOSEException { return new RSAKeyGenerator(2048) .keyUse(KeyUse.SIGNATURE) // indicate the intended use of the key diff --git a/extensions/common/iam/oauth2/oauth2-daps/src/main/java/org/eclipse/edc/iam/oauth2/daps/DapsExtension.java b/extensions/common/iam/oauth2/oauth2-daps/src/main/java/org/eclipse/edc/iam/oauth2/daps/DapsExtension.java index a9fd84a4a6e..a908576f56a 100644 --- a/extensions/common/iam/oauth2/oauth2-daps/src/main/java/org/eclipse/edc/iam/oauth2/daps/DapsExtension.java +++ b/extensions/common/iam/oauth2/oauth2-daps/src/main/java/org/eclipse/edc/iam/oauth2/daps/DapsExtension.java @@ -34,10 +34,11 @@ public class DapsExtension implements ServiceExtension { public static final String NAME = "DAPS"; public static final String DEFAULT_TOKEN_SCOPE = "idsc:IDS_CONNECTOR_ATTRIBUTES_ALL"; - @Setting(value = "The value of the scope claim that is passed to DAPS to obtain a DAT", defaultValue = DEFAULT_TOKEN_SCOPE) - public static final String DAPS_TOKEN_SCOPE = "edc.iam.token.scope"; public static final String OAUTH_2_DAPS_TOKEN_CONTEXT = "oauth2-daps"; + @Setting(description = "The value of the scope claim that is passed to DAPS to obtain a DAT", defaultValue = DEFAULT_TOKEN_SCOPE, key = "edc.iam.token.scope") + private String scope; + @Inject private TokenDecoratorRegistry jwtDecoratorRegistry; @@ -54,8 +55,6 @@ public void initialize(ServiceExtensionContext context) { @Provider public TokenDecorator createDapsTokenDecorator(ServiceExtensionContext context) { - var scope = context.getConfig().getString(DAPS_TOKEN_SCOPE); - return new DapsTokenDecorator(scope); } } diff --git a/extensions/common/json-ld/src/main/java/org/eclipse/edc/jsonld/JsonLdExtension.java b/extensions/common/json-ld/src/main/java/org/eclipse/edc/jsonld/JsonLdExtension.java index 1e407625335..6faea41ee95 100644 --- a/extensions/common/json-ld/src/main/java/org/eclipse/edc/jsonld/JsonLdExtension.java +++ b/extensions/common/json-ld/src/main/java/org/eclipse/edc/jsonld/JsonLdExtension.java @@ -56,16 +56,19 @@ public class JsonLdExtension implements ServiceExtension { public static final String CONFIG_VALUE_URL = "url"; private static final boolean DEFAULT_HTTP_HTTPS_RESOLUTION = false; - @Setting(value = "If set enable http json-ld document resolution", type = "boolean", defaultValue = DEFAULT_HTTP_HTTPS_RESOLUTION + "") - private static final String HTTP_ENABLE_SETTING = "edc.jsonld.http.enabled"; - @Setting(value = "If set enable https json-ld document resolution", type = "boolean", defaultValue = DEFAULT_HTTP_HTTPS_RESOLUTION + "") - private static final String HTTPS_ENABLE_SETTING = "edc.jsonld.https.enabled"; + @Setting(description = "If set enable http json-ld document resolution", defaultValue = DEFAULT_HTTP_HTTPS_RESOLUTION + "", key = "edc.jsonld.http.enabled") + private boolean httpResolutionEnabled; + + @Setting(description = "If set enable https json-ld document resolution", type = "boolean", defaultValue = DEFAULT_HTTP_HTTPS_RESOLUTION + "", key = "edc.jsonld.https.enabled") + private boolean httpsResolutionEnabled; + private static final boolean DEFAULT_AVOID_VOCAB_CONTEXT = false; - @Setting(value = "If true disable the @vocab context definition. This could be used to avoid api breaking changes", type = "boolean", defaultValue = DEFAULT_AVOID_VOCAB_CONTEXT + "") - private static final String AVOID_VOCAB_CONTEXT = "edc.jsonld.vocab.disable"; + @Setting(description = "If true disable the @vocab context definition. This could be used to avoid api breaking changes", defaultValue = DEFAULT_AVOID_VOCAB_CONTEXT + "", key = "edc.jsonld.vocab.disable") + private boolean avoidVocab; + private static final boolean DEFAULT_CHECK_PREFIXES = true; - @Setting(value = "If true a validation on expended object will be made against configured prefixes", type = "boolean", defaultValue = DEFAULT_CHECK_PREFIXES + "") - private static final String CHECK_PREFIXES = "edc.jsonld.prefixes.check"; + @Setting(description = "If true a validation on expended object will be made against configured prefixes", type = "boolean", defaultValue = DEFAULT_CHECK_PREFIXES + "", key = "edc.jsonld.prefixes.check") + private boolean checkPrefixes; @Inject private TypeManager typeManager; @@ -82,12 +85,11 @@ public void initialize(ServiceExtensionContext context) { @Provider public JsonLd createJsonLdService(ServiceExtensionContext context) { - var config = context.getConfig(); var configuration = JsonLdConfiguration.Builder.newInstance() - .httpEnabled(config.getBoolean(HTTP_ENABLE_SETTING, DEFAULT_HTTP_HTTPS_RESOLUTION)) - .httpsEnabled(config.getBoolean(HTTPS_ENABLE_SETTING, DEFAULT_HTTP_HTTPS_RESOLUTION)) - .avoidVocab(config.getBoolean(AVOID_VOCAB_CONTEXT, DEFAULT_AVOID_VOCAB_CONTEXT)) - .checkPrefixes(config.getBoolean(CHECK_PREFIXES, DEFAULT_CHECK_PREFIXES)) + .httpEnabled(httpResolutionEnabled) + .httpsEnabled(httpsResolutionEnabled) + .avoidVocab(avoidVocab) + .checkPrefixes(checkPrefixes) .build(); var monitor = context.getMonitor(); var service = new TitaniumJsonLd(monitor, configuration); diff --git a/extensions/common/json-ld/src/test/java/org/eclipse/edc/jsonld/JsonLdExtensionTest.java b/extensions/common/json-ld/src/test/java/org/eclipse/edc/jsonld/JsonLdExtensionTest.java index 71a6fc5d1ce..4690f712ac1 100644 --- a/extensions/common/json-ld/src/test/java/org/eclipse/edc/jsonld/JsonLdExtensionTest.java +++ b/extensions/common/json-ld/src/test/java/org/eclipse/edc/jsonld/JsonLdExtensionTest.java @@ -24,7 +24,6 @@ import java.io.File; import java.net.URI; -import java.net.URISyntaxException; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -41,7 +40,7 @@ void createService(ServiceExtensionContext context, JsonLdExtension extension) { } @Test - void verifyCachedDocsFromConfig_oneValidEntry(ServiceExtensionContext context, JsonLdExtension extension) throws URISyntaxException { + void verifyCachedDocsFromConfig_oneValidEntry(ServiceExtensionContext context, JsonLdExtension extension) { var config = ConfigFactory.fromMap(Map.of( "edc.jsonld.document.foo.url", "http://foo.org/doc.json", "edc.jsonld.document.foo.path", "/tmp/foo/doc.json") @@ -56,7 +55,7 @@ void verifyCachedDocsFromConfig_oneValidEntry(ServiceExtensionContext context, J } @Test - void verifyCachedDocsFromConfig_oneValidEntry_withSuperfluous(ServiceExtensionContext context, JsonLdExtension extension) throws URISyntaxException { + void verifyCachedDocsFromConfig_oneValidEntry_withSuperfluous(ServiceExtensionContext context, JsonLdExtension extension) { var config = ConfigFactory.fromMap(Map.of( "edc.jsonld.document.foo.url", "http://foo.org/doc.json", "edc.jsonld.document.foo.invalid", "should be ignored", @@ -72,7 +71,7 @@ void verifyCachedDocsFromConfig_oneValidEntry_withSuperfluous(ServiceExtensionCo } @Test - void verifyCachedDocsFromConfig_multipleValidEntries(ServiceExtensionContext context, JsonLdExtension extension) throws URISyntaxException { + void verifyCachedDocsFromConfig_multipleValidEntries(ServiceExtensionContext context, JsonLdExtension extension) { var config = ConfigFactory.fromMap(Map.of( "edc.jsonld.document.foo.url", "http://foo.org/doc.json", "edc.jsonld.document.foo.path", "/tmp/foo/doc.json", @@ -90,7 +89,7 @@ void verifyCachedDocsFromConfig_multipleValidEntries(ServiceExtensionContext con } @Test - void verifyCachedDocsFromConfig_multipleEntries_oneIncomplete(ServiceExtensionContext context, JsonLdExtension extension) throws URISyntaxException { + void verifyCachedDocsFromConfig_multipleEntries_oneIncomplete(ServiceExtensionContext context, JsonLdExtension extension) { var config = ConfigFactory.fromMap(Map.of( "edc.jsonld.document.foo.url", "http://foo.org/doc.json", "edc.jsonld.document.foo.path", "/tmp/foo/doc.json", @@ -108,7 +107,7 @@ void verifyCachedDocsFromConfig_multipleEntries_oneIncomplete(ServiceExtensionCo } @Test - void verifyCachedDocsFromConfig_multipleEntries_oneInvalid(ServiceExtensionContext context, JsonLdExtension extension) throws URISyntaxException { + void verifyCachedDocsFromConfig_multipleEntries_oneInvalid(ServiceExtensionContext context, JsonLdExtension extension) { var config = ConfigFactory.fromMap(Map.of( "edc.jsonld.document.foo.url", "http://foo.org/doc.json", "edc.jsonld.document.foo.path", "/tmp/foo/doc.json", diff --git a/extensions/common/sql/sql-core/src/main/java/org/eclipse/edc/sql/SqlCoreExtension.java b/extensions/common/sql/sql-core/src/main/java/org/eclipse/edc/sql/SqlCoreExtension.java index 6b3a9aeaf83..ec40c4ceff6 100644 --- a/extensions/common/sql/sql-core/src/main/java/org/eclipse/edc/sql/SqlCoreExtension.java +++ b/extensions/common/sql/sql-core/src/main/java/org/eclipse/edc/sql/SqlCoreExtension.java @@ -24,16 +24,14 @@ import org.eclipse.edc.transaction.spi.NoopTransactionContext; import org.eclipse.edc.transaction.spi.TransactionContext; -import static java.lang.Integer.parseInt; - @Extension(value = SqlCoreExtension.NAME) public class SqlCoreExtension implements ServiceExtension { public static final String NAME = "SQL Core"; public static final String DEFAULT_EDC_SQL_FETCH_SIZE = "5000"; - @Setting(value = "Fetch size value used in SQL queries", defaultValue = DEFAULT_EDC_SQL_FETCH_SIZE) - public static final String EDC_SQL_FETCH_SIZE = "edc.sql.fetch.size"; + @Setting(description = "Fetch size value used in SQL queries", defaultValue = DEFAULT_EDC_SQL_FETCH_SIZE, key = "edc.sql.fetch.size") + private int fetchSize; @Inject private TransactionContext transactionContext; @@ -52,7 +50,6 @@ public void initialize(ServiceExtensionContext context) { @Provider public QueryExecutor sqlQueryExecutor(ServiceExtensionContext context) { - var fetchSize = context.getSetting(EDC_SQL_FETCH_SIZE, parseInt(DEFAULT_EDC_SQL_FETCH_SIZE)); var configuration = new SqlQueryExecutorConfiguration(fetchSize); return new SqlQueryExecutor(configuration); } diff --git a/extensions/common/sql/sql-pool/sql-pool-apache-commons/src/main/java/org/eclipse/edc/sql/pool/commons/CommonsConnectionPoolServiceExtension.java b/extensions/common/sql/sql-pool/sql-pool-apache-commons/src/main/java/org/eclipse/edc/sql/pool/commons/CommonsConnectionPoolServiceExtension.java index 4bcfe82c19f..157ff11bf45 100644 --- a/extensions/common/sql/sql-pool/sql-pool-apache-commons/src/main/java/org/eclipse/edc/sql/pool/commons/CommonsConnectionPoolServiceExtension.java +++ b/extensions/common/sql/sql-pool/sql-pool-apache-commons/src/main/java/org/eclipse/edc/sql/pool/commons/CommonsConnectionPoolServiceExtension.java @@ -46,28 +46,28 @@ public class CommonsConnectionPoolServiceExtension implements ServiceExtension { public static final String EDC_DATASOURCE_PREFIX = "edc.datasource"; private static final String EDC_DATASOURCE_CONFIG_CONTEXT = EDC_DATASOURCE_PREFIX + "."; - @Setting(value = "JDBC url", required = true, context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "JDBC url", required = true, context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String URL = "url"; - @Setting(value = "Username to be used for the JDBC connection. Can be omitted if not required, or if the user is encoded in the JDBC url.", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Username to be used for the JDBC connection. Can be omitted if not required, or if the user is encoded in the JDBC url.", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String USER = "user"; - @Setting(value = "Username to be used for the JDBC connection. Can be omitted if not required, or if the password is encoded in the JDBC url.", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Username to be used for the JDBC connection. Can be omitted if not required, or if the password is encoded in the JDBC url.", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String PASSWORD = "password"; - @Setting(value = "Pool max idle connections", type = "int", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Pool max idle connections", type = "int", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String POOL_CONNECTIONS_MAX_IDLE = "pool.connections.max-idle"; - @Setting(value = "Pool max total connections", type = "int", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Pool max total connections", type = "int", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String POOL_CONNECTIONS_MAX_TOTAL = "pool.connections.max-total"; - @Setting(value = "Pool min idle connections", type = "int", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Pool min idle connections", type = "int", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String POOL_CONNECTIONS_MIN_IDLE = "pool.connections.min-idle"; - @Setting(value = "Pool test on borrow", type = "boolean", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Pool test on borrow", type = "boolean", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String POOL_CONNECTION_TEST_ON_BORROW = "pool.connection.test.on-borrow"; - @Setting(value = "Pool test on create", type = "boolean", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Pool test on create", type = "boolean", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String POOL_CONNECTION_TEST_ON_CREATE = "pool.connection.test.on-create"; - @Setting(value = "Pool test on return", type = "boolean", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Pool test on return", type = "boolean", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String POOL_CONNECTION_TEST_ON_RETURN = "pool.connection.test.on-return"; - @Setting(value = "Pool test while idle", type = "boolean", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Pool test while idle", type = "boolean", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String POOL_CONNECTION_TEST_WHILE_IDLE = "pool.connection.test.while-idle"; - @Setting(value = "Pool test query", context = EDC_DATASOURCE_CONFIG_CONTEXT) + @Setting(description = "Pool test query", context = EDC_DATASOURCE_CONFIG_CONTEXT) public static final String POOL_CONNECTION_TEST_QUERY = "pool.connection.test.query"; @Inject diff --git a/extensions/common/store/sql/edr-index-sql/src/main/java/org/eclipse/edc/edr/store/index/SqlEndpointDataReferenceEntryIndexExtension.java b/extensions/common/store/sql/edr-index-sql/src/main/java/org/eclipse/edc/edr/store/index/SqlEndpointDataReferenceEntryIndexExtension.java index 1ced68fa511..24a5f078aa0 100644 --- a/extensions/common/store/sql/edr-index-sql/src/main/java/org/eclipse/edc/edr/store/index/SqlEndpointDataReferenceEntryIndexExtension.java +++ b/extensions/common/store/sql/edr-index-sql/src/main/java/org/eclipse/edc/edr/store/index/SqlEndpointDataReferenceEntryIndexExtension.java @@ -27,7 +27,6 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -35,11 +34,8 @@ @Extension(value = "SQL edr entry store") public class SqlEndpointDataReferenceEntryIndexExtension implements ServiceExtension { - @Deprecated(since = "0.8.1") - public static final String DATASOURCE_SETTING_NAME = "edc.datasource.edr.name"; - - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.edr.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.edr.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -61,8 +57,6 @@ public class SqlEndpointDataReferenceEntryIndexExtension implements ServiceExten @Override public void initialize(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); - var sqlStore = new SqlEndpointDataReferenceEntryIndex(dataSourceRegistry, dataSourceName, transactionContext, typeManager.getMapper(), getStatementImpl(), queryExecutor); diff --git a/extensions/common/store/sql/edr-index-sql/src/test/java/org/eclipse/edc/edr/store/index/sql/SqlEndpointDataReferenceEntryIndexExtensionTest.java b/extensions/common/store/sql/edr-index-sql/src/test/java/org/eclipse/edc/edr/store/index/sql/SqlEndpointDataReferenceEntryIndexExtensionTest.java index 33717c5708a..99127a6b913 100644 --- a/extensions/common/store/sql/edr-index-sql/src/test/java/org/eclipse/edc/edr/store/index/sql/SqlEndpointDataReferenceEntryIndexExtensionTest.java +++ b/extensions/common/store/sql/edr-index-sql/src/test/java/org/eclipse/edc/edr/store/index/sql/SqlEndpointDataReferenceEntryIndexExtensionTest.java @@ -27,11 +27,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.edr.store.index.SqlEndpointDataReferenceEntryIndexExtension.DATASOURCE_NAME; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -53,6 +50,5 @@ void shouldInitializeTheStore(SqlEndpointDataReferenceEntryIndexExtension extens var service = context.getService(EndpointDataReferenceEntryIndex.class); assertThat(service).isInstanceOf(SqlEndpointDataReferenceEntryIndex.class); - verify(config).getString(eq(DATASOURCE_NAME), any()); } } diff --git a/extensions/common/store/sql/jti-validation-store-sql/src/main/java/org/eclipse/edc/jtivalidation/store/sql/SqlJtiValidationStoreExtension.java b/extensions/common/store/sql/jti-validation-store-sql/src/main/java/org/eclipse/edc/jtivalidation/store/sql/SqlJtiValidationStoreExtension.java index b8c8bda1d09..353102f0244 100644 --- a/extensions/common/store/sql/jti-validation-store-sql/src/main/java/org/eclipse/edc/jtivalidation/store/sql/SqlJtiValidationStoreExtension.java +++ b/extensions/common/store/sql/jti-validation-store-sql/src/main/java/org/eclipse/edc/jtivalidation/store/sql/SqlJtiValidationStoreExtension.java @@ -34,10 +34,8 @@ @Extension(value = "SQL JTI Validation store") public class SqlJtiValidationStoreExtension implements ServiceExtension { - - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.jti.datasource"; - + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.jti.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -60,8 +58,6 @@ public class SqlJtiValidationStoreExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var dataSourceName = context.getConfig().getString(DATASOURCE_NAME, DataSourceRegistry.DEFAULT_DATASOURCE); - var sqlStore = new SqlJtiValidationStore(dataSourceRegistry, dataSourceName, transactionContext, typeManager.getMapper(), getStatementImpl(), queryExecutor, context.getMonitor()); diff --git a/extensions/common/store/sql/jti-validation-store-sql/src/test/java/org/eclipse/edc/jtivalidation/store/sql/SqlJtiValidationStoreExtensionTest.java b/extensions/common/store/sql/jti-validation-store-sql/src/test/java/org/eclipse/edc/jtivalidation/store/sql/SqlJtiValidationStoreExtensionTest.java index 6a6b895b45a..ff9783276ad 100644 --- a/extensions/common/store/sql/jti-validation-store-sql/src/test/java/org/eclipse/edc/jtivalidation/store/sql/SqlJtiValidationStoreExtensionTest.java +++ b/extensions/common/store/sql/jti-validation-store-sql/src/test/java/org/eclipse/edc/jtivalidation/store/sql/SqlJtiValidationStoreExtensionTest.java @@ -25,11 +25,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.jtivalidation.store.sql.SqlJtiValidationStoreExtension.DATASOURCE_NAME; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -51,6 +48,5 @@ void shouldInitializeTheStore(SqlJtiValidationStoreExtension extension, ServiceE var service = context.getService(JtiValidationStore.class); assertThat(service).isInstanceOf(SqlJtiValidationStore.class); - verify(config).getString(eq(DATASOURCE_NAME), any()); } } diff --git a/extensions/common/store/sql/sts-client-store-sql/src/main/java/org/eclipse/edc/iam/identitytrust/sts/store/SqlStsClientStoreExtension.java b/extensions/common/store/sql/sts-client-store-sql/src/main/java/org/eclipse/edc/iam/identitytrust/sts/store/SqlStsClientStoreExtension.java index 8522beff987..79a876f3b14 100644 --- a/extensions/common/store/sql/sts-client-store-sql/src/main/java/org/eclipse/edc/iam/identitytrust/sts/store/SqlStsClientStoreExtension.java +++ b/extensions/common/store/sql/sts-client-store-sql/src/main/java/org/eclipse/edc/iam/identitytrust/sts/store/SqlStsClientStoreExtension.java @@ -36,8 +36,8 @@ @Extension(value = "SQL sts accounts store") public class SqlStsClientStoreExtension implements ServiceExtension { - @Setting(value = "The datasource to be used", defaultValue = DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.stsclient.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DEFAULT_DATASOURCE, key = "edc.sql.store.stsclient.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -59,7 +59,6 @@ public class SqlStsClientStoreExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var dataSourceName = context.getSetting(DATASOURCE_NAME, DEFAULT_DATASOURCE); var sqlStore = new SqlStsAccountStore(dataSourceRegistry, dataSourceName, transactionContext, typeManager.getMapper(), getStatementImpl(), queryExecutor); diff --git a/extensions/common/store/sql/sts-client-store-sql/src/test/java/org/eclipse/edc/iam/identitytrust/sts/store/SqlStsAccountStoreExtensionTest.java b/extensions/common/store/sql/sts-client-store-sql/src/test/java/org/eclipse/edc/iam/identitytrust/sts/store/SqlStsAccountStoreExtensionTest.java index 25787206563..317cc01e161 100644 --- a/extensions/common/store/sql/sts-client-store-sql/src/test/java/org/eclipse/edc/iam/identitytrust/sts/store/SqlStsAccountStoreExtensionTest.java +++ b/extensions/common/store/sql/sts-client-store-sql/src/test/java/org/eclipse/edc/iam/identitytrust/sts/store/SqlStsAccountStoreExtensionTest.java @@ -25,11 +25,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.iam.identitytrust.sts.store.SqlStsClientStoreExtension.DATASOURCE_NAME; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -51,6 +48,5 @@ void shouldInitializeTheStore(SqlStsClientStoreExtension extension, ServiceExten var service = context.getService(StsAccountStore.class); assertThat(service).isInstanceOf(SqlStsAccountStore.class); - verify(config).getString(eq(DATASOURCE_NAME), any()); } } diff --git a/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultExtension.java b/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultExtension.java index d7e192b1ac4..5f9734c6531 100644 --- a/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultExtension.java +++ b/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultExtension.java @@ -17,10 +17,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.edc.http.spi.EdcHttpClient; +import org.eclipse.edc.runtime.metamodel.annotation.Configuration; 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.monitor.Monitor; import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ExecutorInstrumentation; @@ -36,54 +36,18 @@ public class HashicorpVaultExtension implements ServiceExtension { public static final String NAME = "Hashicorp Vault"; - public static final boolean VAULT_HEALTH_CHECK_ENABLED_DEFAULT = true; - public static final boolean VAULT_HEALTH_CHECK_STANDBY_OK_DEFAULT = false; - public static final String VAULT_API_HEALTH_PATH_DEFAULT = "/v1/sys/health"; - public static final boolean VAULT_TOKEN_SCHEDULED_RENEW_ENABLED_DEFAULT = true; - public static final long VAULT_TOKEN_RENEW_BUFFER_DEFAULT = 30; - public static final long VAULT_TOKEN_TTL_DEFAULT = 300; - public static final String VAULT_API_SECRET_PATH_DEFAULT = "/v1/secret"; - - @Setting(value = "The URL of the Hashicorp Vault", required = true) - public static final String VAULT_URL = "edc.vault.hashicorp.url"; - - @Setting(value = "Whether or not the vault health check is enabled", defaultValue = "true", type = "boolean") - public static final String VAULT_HEALTH_CHECK_ENABLED = "edc.vault.hashicorp.health.check.enabled"; - - @Setting(value = "The URL path of the vault's /health endpoint", defaultValue = VAULT_API_HEALTH_PATH_DEFAULT) - public static final String VAULT_API_HEALTH_PATH = "edc.vault.hashicorp.api.health.check.path"; - - @Setting(value = "Specifies if being a standby should still return the active status code instead of the standby status code", defaultValue = "false", type = "boolean") - public static final String VAULT_HEALTH_CHECK_STANDBY_OK = "edc.vault.hashicorp.health.check.standby.ok"; - - @Setting(value = "The token used to access the Hashicorp Vault", required = true) - public static final String VAULT_TOKEN = "edc.vault.hashicorp.token"; - - @Setting(value = "Whether the automatic token renewal process will be triggered or not. Should be disabled only for development and testing purposes", defaultValue = "true") - public static final String VAULT_TOKEN_SCHEDULED_RENEW_ENABLED = "edc.vault.hashicorp.token.scheduled-renew-enabled"; - - @Setting(value = "The time-to-live (ttl) value of the Hashicorp Vault token in seconds", defaultValue = "300", type = "long") - public static final String VAULT_TOKEN_TTL = "edc.vault.hashicorp.token.ttl"; - - @Setting(value = "The renew buffer of the Hashicorp Vault token in seconds", defaultValue = "30", type = "long") - public static final String VAULT_TOKEN_RENEW_BUFFER = "edc.vault.hashicorp.token.renew-buffer"; - - @Setting(value = "The URL path of the vault's /secret endpoint", defaultValue = VAULT_API_SECRET_PATH_DEFAULT) - public static final String VAULT_API_SECRET_PATH = "edc.vault.hashicorp.api.secret.path"; - - @Setting(value = "The path of the folder that the secret is stored in, relative to VAULT_FOLDER_PATH") - public static final String VAULT_FOLDER_PATH = "edc.vault.hashicorp.folder"; - @Inject private EdcHttpClient httpClient; @Inject private ExecutorInstrumentation executorInstrumentation; + @Configuration + private HashicorpVaultSettings config; + private HashicorpVaultClient client; private HashicorpVaultTokenRenewTask tokenRenewalTask; private Monitor monitor; - private HashicorpVaultSettings settings; @Override public String name() { @@ -97,11 +61,7 @@ public HashicorpVaultClient hashicorpVaultClient() { var mapper = new ObjectMapper(); mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false); - client = new HashicorpVaultClient( - httpClient, - mapper, - monitor, - settings); + client = new HashicorpVaultClient(httpClient, mapper, monitor, config); } return client; } @@ -114,18 +74,17 @@ public Vault hashicorpVault() { @Override public void initialize(ServiceExtensionContext context) { monitor = context.getMonitor().withPrefix(NAME); - settings = getSettings(context); tokenRenewalTask = new HashicorpVaultTokenRenewTask( NAME, executorInstrumentation, hashicorpVaultClient(), - settings.renewBuffer(), + config.renewBuffer(), monitor); } @Override public void start() { - if (settings.scheduledTokenRenewEnabled()) { + if (config.scheduledTokenRenewEnabled()) { tokenRenewalTask.start(); } } @@ -136,30 +95,4 @@ public void shutdown() { tokenRenewalTask.stop(); } } - - private HashicorpVaultSettings getSettings(ServiceExtensionContext context) { - var url = context.getSetting(VAULT_URL, null); - var healthCheckEnabled = context.getSetting(VAULT_HEALTH_CHECK_ENABLED, VAULT_HEALTH_CHECK_ENABLED_DEFAULT); - var healthCheckPath = context.getSetting(VAULT_API_HEALTH_PATH, VAULT_API_HEALTH_PATH_DEFAULT); - var healthStandbyOk = context.getSetting(VAULT_HEALTH_CHECK_STANDBY_OK, VAULT_HEALTH_CHECK_STANDBY_OK_DEFAULT); - var token = context.getSetting(VAULT_TOKEN, null); - var isScheduledTokenRenewEnabled = context.getSetting(VAULT_TOKEN_SCHEDULED_RENEW_ENABLED, VAULT_TOKEN_SCHEDULED_RENEW_ENABLED_DEFAULT); - var ttl = context.getSetting(VAULT_TOKEN_TTL, VAULT_TOKEN_TTL_DEFAULT); - var renewBuffer = context.getSetting(VAULT_TOKEN_RENEW_BUFFER, VAULT_TOKEN_RENEW_BUFFER_DEFAULT); - var secretPath = context.getSetting(VAULT_API_SECRET_PATH, VAULT_API_SECRET_PATH_DEFAULT); - var folderPath = context.getSetting(VAULT_FOLDER_PATH, null); - - return HashicorpVaultSettings.Builder.newInstance() - .url(url) - .healthCheckEnabled(healthCheckEnabled) - .healthCheckPath(healthCheckPath) - .healthStandbyOk(healthStandbyOk) - .token(token) - .scheduledTokenRenewEnabled(isScheduledTokenRenewEnabled) - .ttl(ttl) - .renewBuffer(renewBuffer) - .secretPath(secretPath) - .folderPath(folderPath) - .build(); - } } diff --git a/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultClient.java b/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultClient.java index fe935571034..1c5514de603 100644 --- a/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultClient.java +++ b/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultClient.java @@ -40,6 +40,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; /** * This is a client implementation for interacting with Hashicorp Vault. @@ -119,7 +120,7 @@ public Result doHealthCheck() { * @return boolean indicating if the token is renewable */ public Result isTokenRenewable() { - var uri = settings.url() + var uri = baseUrl(settings) .newBuilder() .addPathSegments(TOKEN_LOOK_UP_SELF_PATH) .build(); @@ -156,7 +157,7 @@ public Result isTokenRenewable() { * @return long representing the remaining ttl of the token in seconds */ public Result renewToken() { - var uri = settings.url() + var uri = baseUrl(settings) .newBuilder() .addPathSegments(TOKEN_RENEW_SELF_PATH) .build(); @@ -261,7 +262,7 @@ private HttpUrl getHealthCheckUrl() { // status // code instead of the standby status codes - return settings.url() + return baseUrl(settings) .newBuilder() .addPathSegments(PathUtil.trimLeadingOrEndingSlash(vaultHealthPath)) .addQueryParameter("standbyok", isVaultHealthStandbyOk ? "true" : "false") @@ -278,7 +279,7 @@ private HttpUrl getSecretUrl(String key, String entryType) { var vaultApiPath = settings.secretPath(); var folderPath = settings.getFolderPath(); - var builder = settings.url() + var builder = baseUrl(settings) .newBuilder() .addPathSegments(PathUtil.trimLeadingOrEndingSlash(vaultApiPath)) .addPathSegment(entryType); @@ -310,6 +311,12 @@ private Request httpPost(HttpUrl requestUri, Object requestBody) { .build(); } + @NotNull + private HttpUrl baseUrl(HashicorpVaultSettings settings) { + var url = settings.url(); + return Objects.requireNonNull(HttpUrl.parse(url)); + } + @NotNull private Headers getHeaders() { var headersBuilder = new Headers.Builder().add(VAULT_REQUEST_HEADER, Boolean.toString(true)); diff --git a/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultSettings.java b/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultSettings.java index 0795cddffe5..e6908309993 100644 --- a/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultSettings.java +++ b/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultSettings.java @@ -14,31 +14,51 @@ package org.eclipse.edc.vault.hashicorp.client; -import okhttp3.HttpUrl; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.runtime.metamodel.annotation.Settings; import static java.util.Objects.requireNonNull; /** * Settings for the {@link HashicorpVaultClient}. */ +@Settings public class HashicorpVaultSettings { - - private HttpUrl url; + public static final String VAULT_API_HEALTH_PATH_DEFAULT = "/v1/sys/health"; + public static final String VAULT_API_SECRET_PATH_DEFAULT = "/v1/secret"; + public static final boolean VAULT_HEALTH_CHECK_STANDBY_OK_DEFAULT = false; + public static final long VAULT_TOKEN_RENEW_BUFFER_DEFAULT = 30; + public static final long VAULT_TOKEN_TTL_DEFAULT = 300; + public static final boolean VAULT_HEALTH_CHECK_ENABLED_DEFAULT = true; + public static final boolean VAULT_TOKEN_SCHEDULED_RENEW_ENABLED_DEFAULT = true; + + @Setting(description = "The URL of the Hashicorp Vault", key = "edc.vault.hashicorp.url") + private String url; + @Setting(description = "Whether or not the vault health check is enabled", defaultValue = VAULT_HEALTH_CHECK_ENABLED_DEFAULT + "", key = "edc.vault.hashicorp.health.check.enabled") private boolean healthCheckEnabled; + @Setting(description = "The URL path of the vault's /health endpoint", defaultValue = VAULT_API_HEALTH_PATH_DEFAULT, key = "edc.vault.hashicorp.api.health.check.path") private String healthCheckPath; + @Setting(description = "Specifies if being a standby should still return the active status code instead of the standby status code", defaultValue = VAULT_HEALTH_CHECK_STANDBY_OK_DEFAULT + "", key = "edc.vault.hashicorp.health.check.standby.ok") private boolean healthStandbyOk; + @Setting(description = "The token used to access the Hashicorp Vault", key = "edc.vault.hashicorp.token") private String token; + @Setting(description = "Whether the automatic token renewal process will be triggered or not. Should be disabled only for development and testing purposes", + defaultValue = VAULT_TOKEN_SCHEDULED_RENEW_ENABLED_DEFAULT + "", key = "edc.vault.hashicorp.token.scheduled-renew-enabled") private boolean scheduledTokenRenewEnabled; + @Setting(description = "The time-to-live (ttl) value of the Hashicorp Vault token in seconds", defaultValue = VAULT_TOKEN_TTL_DEFAULT + "", key = "edc.vault.hashicorp.token.ttl") private long ttl; + @Setting(description = "The renew buffer of the Hashicorp Vault token in seconds", defaultValue = VAULT_TOKEN_RENEW_BUFFER_DEFAULT + "", key = "edc.vault.hashicorp.token.renew-buffer") private long renewBuffer; + @Setting(description = "The URL path of the vault's /secret endpoint", defaultValue = VAULT_API_SECRET_PATH_DEFAULT, key = "edc.vault.hashicorp.api.secret.path") private String secretPath; + @Setting(description = "The path of the folder that the secret is stored in, relative to VAULT_FOLDER_PATH", required = false, key = "edc.vault.hashicorp.folder") private String folderPath; private HashicorpVaultSettings() { } - public HttpUrl url() { + public String url() { return url; } @@ -91,7 +111,7 @@ public static Builder newInstance() { public Builder url(String url) { requireNonNull(url, "Vault url must not be null"); - values.url = HttpUrl.parse(url); + values.url = url; return this; } diff --git a/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/health/HashicorpVaultHealthExtension.java b/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/health/HashicorpVaultHealthExtension.java index 4f8ac3c6556..c448d3df12a 100644 --- a/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/health/HashicorpVaultHealthExtension.java +++ b/extensions/common/vault/vault-hashicorp/src/main/java/org/eclipse/edc/vault/hashicorp/health/HashicorpVaultHealthExtension.java @@ -15,6 +15,7 @@ package org.eclipse.edc.vault.hashicorp.health; +import org.eclipse.edc.runtime.metamodel.annotation.Configuration; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Requires; @@ -22,9 +23,8 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.health.HealthCheckService; import org.eclipse.edc.vault.hashicorp.client.HashicorpVaultClient; +import org.eclipse.edc.vault.hashicorp.client.HashicorpVaultSettings; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_HEALTH_CHECK_ENABLED; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_HEALTH_CHECK_ENABLED_DEFAULT; @Requires(HealthCheckService.class) @Extension(value = HashicorpVaultHealthExtension.NAME) @@ -38,6 +38,9 @@ public class HashicorpVaultHealthExtension implements ServiceExtension { @Inject private HashicorpVaultClient client; + @Configuration + private HashicorpVaultSettings settings; + @Override public String name() { return NAME; @@ -46,8 +49,7 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { var monitor = context.getMonitor().withPrefix(NAME); - var healthCheckEnabled = context.getSetting(VAULT_HEALTH_CHECK_ENABLED, VAULT_HEALTH_CHECK_ENABLED_DEFAULT); - if (healthCheckEnabled) { + if (settings.healthCheckEnabled()) { var healthCheck = new HashicorpVaultHealthCheck(client, monitor); healthCheckService.addLivenessProvider(healthCheck); healthCheckService.addReadinessProvider(healthCheck); diff --git a/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultExtensionTest.java b/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultExtensionTest.java index dee356161da..ffb03fe4679 100644 --- a/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultExtensionTest.java +++ b/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultExtensionTest.java @@ -20,18 +20,16 @@ import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.system.ExecutorInstrumentation; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.configuration.ConfigFactory; import org.eclipse.edc.spi.types.TypeManager; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_TOKEN; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_TOKEN_SCHEDULED_RENEW_ENABLED; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_TOKEN_SCHEDULED_RENEW_ENABLED_DEFAULT; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_URL; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; @@ -44,6 +42,9 @@ class HashicorpVaultExtensionTest { private static final String URL = "https://test.com/vault"; private static final String TOKEN = "some-token"; + private static final String VAULT_URL = "edc.vault.hashicorp.url"; + private static final String VAULT_TOKEN = "edc.vault.hashicorp.token"; + private static final String VAULT_TOKEN_SCHEDULED_RENEW_ENABLED = "edc.vault.hashicorp.token.scheduled-renew-enabled"; private HashicorpVaultExtension extension; private final ExecutorInstrumentation executorInstrumentation = mock(); @@ -55,8 +56,12 @@ void beforeEach(ObjectFactory factory, ServiceExtensionContext context) { context.registerService(EdcHttpClient.class, httpClient); context.registerService(TypeManager.class, mock(TypeManager.class)); context.registerService(ExecutorInstrumentation.class, executorInstrumentation); - when(context.getSetting(VAULT_URL, null)).thenReturn(URL); - when(context.getSetting(VAULT_TOKEN, null)).thenReturn(TOKEN); + + var config = ConfigFactory.fromMap(Map.of( + VAULT_URL, URL, + VAULT_TOKEN, TOKEN + )); + when(context.getConfig()).thenReturn(config); when(executorInstrumentation.instrument(any(), anyString())).thenReturn(scheduledExecutorService); extension = factory.constructInstance(HashicorpVaultExtension.class); } @@ -76,10 +81,17 @@ void start_withTokenRenewEnabled_shouldStartTokenRenewTask(ServiceExtensionConte } @Test - void start_withTokenRenewDisabled_shouldNotStartTokenRenewTask(ServiceExtensionContext context) { - when(context.getSetting(VAULT_TOKEN_SCHEDULED_RENEW_ENABLED, VAULT_TOKEN_SCHEDULED_RENEW_ENABLED_DEFAULT)).thenReturn(false); - extension.initialize(context); - extension.start(); + void start_withTokenRenewDisabled_shouldNotStartTokenRenewTask(ServiceExtensionContext context, ObjectFactory factory) { + + var config = ConfigFactory.fromMap(Map.of( + VAULT_URL, URL, + VAULT_TOKEN, TOKEN, + VAULT_TOKEN_SCHEDULED_RENEW_ENABLED, "false" + )); + when(context.getConfig()).thenReturn(config); + var ext = factory.constructInstance(HashicorpVaultExtension.class); + ext.initialize(context); + ext.start(); verify(executorInstrumentation, never()).instrument(any(), anyString()); verify(scheduledExecutorService, never()).execute(any()); } diff --git a/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultIntegrationTest.java b/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultIntegrationTest.java index ea4bfab02ea..24fcf572506 100644 --- a/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultIntegrationTest.java +++ b/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/HashicorpVaultIntegrationTest.java @@ -16,14 +16,16 @@ package org.eclipse.edc.vault.hashicorp; import org.eclipse.edc.junit.annotations.ComponentTest; -import org.eclipse.edc.junit.extensions.EdcExtension; +import org.eclipse.edc.junit.extensions.EmbeddedRuntime; +import org.eclipse.edc.junit.extensions.RuntimeExtension; +import org.eclipse.edc.junit.extensions.RuntimePerClassExtension; import org.eclipse.edc.spi.security.Vault; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.vault.VaultContainer; @@ -34,12 +36,9 @@ import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_TOKEN; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_URL; @ComponentTest @Testcontainers -@ExtendWith(EdcExtension.class) class HashicorpVaultIntegrationTest { static final String DOCKER_IMAGE_NAME = "vault:1.9.6"; static final String VAULT_ENTRY_KEY = "testing"; @@ -48,14 +47,16 @@ class HashicorpVaultIntegrationTest { static final String TOKEN = UUID.randomUUID().toString(); @Container - public static final VaultContainer VAULTCONTAINER = new VaultContainer<>(DOCKER_IMAGE_NAME) + private static final VaultContainer VAULTCONTAINER = new VaultContainer<>(DOCKER_IMAGE_NAME) .withVaultToken(TOKEN) .withSecretInVault("secret/" + VAULT_ENTRY_KEY, format("%s=%s", VAULT_DATA_ENTRY_NAME, VAULT_ENTRY_VALUE)); + private static final String VAULT_URL = "edc.vault.hashicorp.url"; + private static final String VAULT_TOKEN = "edc.vault.hashicorp.token"; + + + @RegisterExtension + protected static RuntimeExtension runtime = new RuntimePerClassExtension(new EmbeddedRuntime("vault-runtime", getConfig(), "extensions:common:vault:vault-hashicorp")); - @BeforeEach - void beforeEach(EdcExtension extension) { - extension.setConfiguration(getConfig()); - } @Test @DisplayName("Resolve a secret that exists") @@ -136,10 +137,15 @@ void testDeleteSecret_doesNotExist(Vault vault) { assertThat(vault.resolveSecret(key)).isNull(); } - private Map getConfig() { + private static Map getConfig() { + // container might not be started, lazily start and wait for it to come up + if (!VAULTCONTAINER.isRunning()) { + VAULTCONTAINER.start(); + VAULTCONTAINER.waitingFor(Wait.forHealthcheck()); + } return new HashMap<>() { { - put(VAULT_URL, format("http://%s:%s", VAULTCONTAINER.getHost(), VAULTCONTAINER.getFirstMappedPort())); + put(VAULT_URL, "http://%s:%d".formatted(VAULTCONTAINER.getHost(), VAULTCONTAINER.getFirstMappedPort())); put(VAULT_TOKEN, TOKEN); } }; diff --git a/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultSettingsTest.java b/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultSettingsTest.java index 70f216e7921..df6c03c93ec 100644 --- a/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultSettingsTest.java +++ b/extensions/common/vault/vault-hashicorp/src/test/java/org/eclipse/edc/vault/hashicorp/client/HashicorpVaultSettingsTest.java @@ -14,14 +14,13 @@ package org.eclipse.edc.vault.hashicorp.client; -import okhttp3.HttpUrl; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_TOKEN_RENEW_BUFFER_DEFAULT; -import static org.eclipse.edc.vault.hashicorp.HashicorpVaultExtension.VAULT_TOKEN_TTL_DEFAULT; +import static org.eclipse.edc.vault.hashicorp.client.HashicorpVaultSettings.VAULT_TOKEN_RENEW_BUFFER_DEFAULT; +import static org.eclipse.edc.vault.hashicorp.client.HashicorpVaultSettings.VAULT_TOKEN_TTL_DEFAULT; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -29,7 +28,6 @@ class HashicorpVaultSettingsTest { private static final String TOKEN = "token"; private static final String URL = "https://test.com/vault"; - private static final HttpUrl HTTP_URL = HttpUrl.parse(URL); private static final String HEALTH_CHECK_PATH = "/healthcheck/path"; private static final String SECRET_PATH = "/secret/path"; @@ -40,7 +38,7 @@ void createSettings_withDefaultValues_shouldSucceed() { TOKEN, HEALTH_CHECK_PATH, VAULT_TOKEN_TTL_DEFAULT, VAULT_TOKEN_RENEW_BUFFER_DEFAULT)); - assertThat(settings.url()).isEqualTo(HTTP_URL); + assertThat(settings.url()).isEqualTo(URL); assertThat(settings.healthCheckEnabled()).isEqualTo(true); assertThat(settings.healthCheckPath()).isEqualTo(HEALTH_CHECK_PATH); assertThat(settings.healthStandbyOk()).isEqualTo(true); @@ -61,17 +59,6 @@ void createSettings_withVaultUrlNull_shouldThrowException() { assertThat(throwable.getMessage()).isEqualTo("Vault url must not be null"); } - @Test - void createSettings_withVaultUrlInvalid_shouldThrowException() { - var throwable = assertThrows(Exception.class, () -> createSettings( - "this is not valid", - TOKEN, - HEALTH_CHECK_PATH, - VAULT_TOKEN_TTL_DEFAULT, - VAULT_TOKEN_RENEW_BUFFER_DEFAULT)); - assertThat(throwable.getMessage()).isEqualTo("Vault url must be valid"); - } - @Test void createSettings_withHealthCheckPathNull_shouldThrowException() { var throwable = assertThrows(Exception.class, () -> createSettings( diff --git a/extensions/control-plane/edr/edr-store-receiver/src/main/java/org/eclipse/edc/connector/controlplane/edr/store/receiver/EndpointDataReferenceStoreReceiverExtension.java b/extensions/control-plane/edr/edr-store-receiver/src/main/java/org/eclipse/edc/connector/controlplane/edr/store/receiver/EndpointDataReferenceStoreReceiverExtension.java index 9ec892067a9..8380a5137bf 100644 --- a/extensions/control-plane/edr/edr-store-receiver/src/main/java/org/eclipse/edc/connector/controlplane/edr/store/receiver/EndpointDataReferenceStoreReceiverExtension.java +++ b/extensions/control-plane/edr/edr-store-receiver/src/main/java/org/eclipse/edc/connector/controlplane/edr/store/receiver/EndpointDataReferenceStoreReceiverExtension.java @@ -34,8 +34,9 @@ public class EndpointDataReferenceStoreReceiverExtension implements ServiceExten public static final String NAME = "Endpoint Data Reference Store Receiver Extension"; private static final String DEFAULT_SYNC_LISTENER = "false"; - @Setting(value = "If true the EDR receiver will be registered as synchronous listener", defaultValue = DEFAULT_SYNC_LISTENER) - private static final String EDC_EDR_RECEIVER_SYNC = "edc.edr.receiver.sync"; + @Setting(description = "If true the EDR receiver will be registered as synchronous listener", defaultValue = DEFAULT_SYNC_LISTENER, key = "edc.edr.receiver.sync") + private boolean isSyncMode; + @Inject private EventRouter router; @@ -61,7 +62,6 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var isSyncMode = context.getSetting(EDC_EDR_RECEIVER_SYNC, Boolean.parseBoolean(EDC_EDR_RECEIVER_SYNC)); var receiver = new EndpointDataReferenceStoreReceiver(dataReferenceStore, policyArchive, agreementService, transactionContext, monitor.withPrefix("EDR Receiver")); if (isSyncMode) { router.registerSync(TransferProcessEvent.class, receiver); diff --git a/extensions/control-plane/edr/edr-store-receiver/src/test/java/org/eclipse/edc/connector/controlplane/edr/store/receiver/EndpointDataReferenceStoreReceiverExtensionTest.java b/extensions/control-plane/edr/edr-store-receiver/src/test/java/org/eclipse/edc/connector/controlplane/edr/store/receiver/EndpointDataReferenceStoreReceiverExtensionTest.java index 802db3b0536..5cae2e7e3b0 100644 --- a/extensions/control-plane/edr/edr-store-receiver/src/test/java/org/eclipse/edc/connector/controlplane/edr/store/receiver/EndpointDataReferenceStoreReceiverExtensionTest.java +++ b/extensions/control-plane/edr/edr-store-receiver/src/test/java/org/eclipse/edc/connector/controlplane/edr/store/receiver/EndpointDataReferenceStoreReceiverExtensionTest.java @@ -14,14 +14,18 @@ package org.eclipse.edc.connector.controlplane.edr.store.receiver; +import org.eclipse.edc.boot.system.injection.ObjectFactory; import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessEvent; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.event.EventRouter; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.configuration.ConfigFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import java.util.Map; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; @@ -48,9 +52,11 @@ void initialize(ServiceExtensionContext context, EndpointDataReferenceStoreRecei } @Test - void initialize_withSyncConfig(ServiceExtensionContext context, EndpointDataReferenceStoreReceiverExtension extension) { - when(context.getSetting("edc.edr.receiver.sync", false)).thenReturn(true); - extension.initialize(context); + void initialize_withSyncConfig(ServiceExtensionContext context, ObjectFactory objectFactory) { + + when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of("edc.edr.receiver.sync", "true"))); + + objectFactory.constructInstance(EndpointDataReferenceStoreReceiverExtension.class).initialize(context); verify(eventRouter).registerSync(eq(TransferProcessEvent.class), isA(EndpointDataReferenceStoreReceiver.class)); verify(eventRouter, never()).register(any(), any()); } diff --git a/extensions/control-plane/store/sql/asset-index-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtension.java b/extensions/control-plane/store/sql/asset-index-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtension.java index b0833c2df22..94566ef5676 100644 --- a/extensions/control-plane/store/sql/asset-index-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtension.java +++ b/extensions/control-plane/store/sql/asset-index-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtension.java @@ -28,7 +28,6 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -39,8 +38,8 @@ public class SqlAssetIndexServiceExtension implements ServiceExtension { @Deprecated(since = "0.8.1") public static final String DATASOURCE_SETTING_NAME = "edc.datasource.asset.name"; - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.asset.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.asset.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -62,8 +61,6 @@ public class SqlAssetIndexServiceExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); - var sqlAssetLoader = new SqlAssetIndex(dataSourceRegistry, dataSourceName, transactionContext, typeManager.getMapper(), getDialect(), queryExecutor); context.registerService(AssetIndex.class, sqlAssetLoader); diff --git a/extensions/control-plane/store/sql/asset-index-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtensionTest.java b/extensions/control-plane/store/sql/asset-index-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtensionTest.java index 0972a8f7c98..883e4d89396 100644 --- a/extensions/control-plane/store/sql/asset-index-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtensionTest.java +++ b/extensions/control-plane/store/sql/asset-index-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/assetindex/SqlAssetIndexServiceExtensionTest.java @@ -26,11 +26,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.connector.controlplane.store.sql.assetindex.SqlAssetIndexServiceExtension.DATASOURCE_NAME; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -55,6 +52,5 @@ void shouldInitializeTheStore(SqlAssetIndexServiceExtension extension, ServiceEx var dataAddressResolver = context.getService(DataAddressResolver.class); assertThat(dataAddressResolver).isInstanceOf(SqlAssetIndex.class); - verify(config).getString(eq(DATASOURCE_NAME), any()); } } diff --git a/extensions/control-plane/store/sql/contract-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtension.java b/extensions/control-plane/store/sql/contract-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtension.java index e64f8f9e7fb..3aa9e7126c9 100644 --- a/extensions/control-plane/store/sql/contract-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtension.java +++ b/extensions/control-plane/store/sql/contract-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtension.java @@ -28,7 +28,6 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -36,11 +35,9 @@ @Extension(value = "SQL contract definition store") public class SqlContractDefinitionStoreExtension implements ServiceExtension { - @Deprecated(since = "0.8.1") - public static final String DATASOURCE_SETTING_NAME = "edc.datasource.contractdefinition.name"; - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.contractdefinition.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.contractdefinition.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -62,8 +59,6 @@ public class SqlContractDefinitionStoreExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); - var sqlContractDefinitionStore = new SqlContractDefinitionStore(dataSourceRegistry, dataSourceName, transactionContext, getStatementImpl(), typeManager.getMapper(), queryExecutor); diff --git a/extensions/control-plane/store/sql/contract-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtensionTest.java b/extensions/control-plane/store/sql/contract-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtensionTest.java index 85de18e1f49..6f2a99a040e 100644 --- a/extensions/control-plane/store/sql/contract-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtensionTest.java +++ b/extensions/control-plane/store/sql/contract-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractdefinition/SqlContractDefinitionStoreExtensionTest.java @@ -25,11 +25,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.connector.controlplane.store.sql.contractdefinition.SqlContractDefinitionStoreExtension.DATASOURCE_NAME; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -51,6 +48,5 @@ void shouldInitializeTheStore(SqlContractDefinitionStoreExtension extension, Ser var service = context.getService(ContractDefinitionStore.class); assertThat(service).isInstanceOf(ContractDefinitionStore.class); - verify(config).getString(eq(DATASOURCE_NAME), any()); } } diff --git a/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java b/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java index 84543e37bd4..614b316dc1b 100644 --- a/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java +++ b/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtension.java @@ -27,7 +27,6 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -37,11 +36,8 @@ @Extension(value = "SQL contract negotiation store") public class SqlContractNegotiationStoreExtension implements ServiceExtension { - @Deprecated(since = "0.8.1") - public static final String DATASOURCE_SETTING_NAME = "edc.datasource.contractnegotiation.name"; - - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.contractnegotiation.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.contractnegotiation.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -66,8 +62,6 @@ public class SqlContractNegotiationStoreExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); - var sqlStore = new SqlContractNegotiationStore(dataSourceRegistry, dataSourceName, trxContext, typeManager.getMapper(), getStatementImpl(), context.getRuntimeId(), clock, queryExecutor); context.registerService(ContractNegotiationStore.class, sqlStore); @@ -81,8 +75,4 @@ public void initialize(ServiceExtensionContext context) { private ContractNegotiationStatements getStatementImpl() { return statements != null ? statements : new PostgresDialectStatements(); } - - private String getDataSourceName(ServiceExtensionContext context) { - return context.getConfig().getString(DATASOURCE_SETTING_NAME, DataSourceRegistry.DEFAULT_DATASOURCE); - } } diff --git a/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java b/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java index 410f0947212..627cf89346e 100644 --- a/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java +++ b/extensions/control-plane/store/sql/contract-negotiation-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/contractnegotiation/SqlContractNegotiationStoreExtensionTest.java @@ -33,12 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.edc.connector.controlplane.store.sql.contractnegotiation.SqlContractNegotiationStoreExtension.DATASOURCE_NAME; -import static org.eclipse.edc.connector.controlplane.store.sql.contractnegotiation.SqlContractNegotiationStoreExtension.DATASOURCE_SETTING_NAME; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -50,7 +45,6 @@ class SqlContractNegotiationStoreExtensionTest { void initialize(ServiceExtensionContext context, ObjectFactory factory) { var config = mock(Config.class); when(context.getConfig()).thenReturn(config); - when(config.getString(DATASOURCE_SETTING_NAME, DataSourceRegistry.DEFAULT_DATASOURCE)).thenReturn("test"); context.registerService(DataSourceRegistry.class, mock(DataSourceRegistry.class)); context.registerService(TransactionContext.class, mock(TransactionContext.class)); @@ -64,7 +58,6 @@ void initialize(ServiceExtensionContext context, ObjectFactory factory) { var service = context.getService(ContractNegotiationStore.class); assertThat(service).isInstanceOf(SqlContractNegotiationStore.class); assertThat(service).extracting("statements").isInstanceOf(BaseSqlDialectStatements.class); - verify(config).getString(eq(DATASOURCE_NAME), any()); } diff --git a/extensions/control-plane/store/sql/policy-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyStoreExtension.java b/extensions/control-plane/store/sql/policy-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyStoreExtension.java index 2c0ee1b1dd2..e2a7da45615 100644 --- a/extensions/control-plane/store/sql/policy-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyStoreExtension.java +++ b/extensions/control-plane/store/sql/policy-definition-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyStoreExtension.java @@ -27,7 +27,6 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -35,11 +34,8 @@ @Extension("SQL policy store") public class SqlPolicyStoreExtension implements ServiceExtension { - @Deprecated(since = "0.8.1") - public static final String DATASOURCE_SETTING_NAME = "edc.datasource.policy.name"; - - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.policy.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.policy.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -60,7 +56,6 @@ public class SqlPolicyStoreExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); var sqlPolicyStore = new SqlPolicyDefinitionStore(dataSourceRegistry, dataSourceName, transactionContext, typeManager.getMapper(), getStatementImpl(), queryExecutor); @@ -77,7 +72,4 @@ private SqlPolicyStoreStatements getStatementImpl() { return statements != null ? statements : new PostgresDialectStatements(); } - private String getDataSourceName(ServiceExtensionContext context) { - return context.getConfig().getString(DATASOURCE_SETTING_NAME, DataSourceRegistry.DEFAULT_DATASOURCE); - } } diff --git a/extensions/control-plane/store/sql/policy-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyDefinitionStoreExtensionTest.java b/extensions/control-plane/store/sql/policy-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyDefinitionStoreExtensionTest.java index 1dadbaca162..a750f539647 100644 --- a/extensions/control-plane/store/sql/policy-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyDefinitionStoreExtensionTest.java +++ b/extensions/control-plane/store/sql/policy-definition-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/policydefinition/SqlPolicyDefinitionStoreExtensionTest.java @@ -26,11 +26,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.connector.controlplane.store.sql.policydefinition.SqlPolicyStoreExtension.DATASOURCE_NAME; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -53,6 +50,5 @@ void shouldInitializeTheStore(SqlPolicyStoreExtension extension, ServiceExtensio var service = context.getService(PolicyDefinitionStore.class); assertThat(service).isInstanceOf(SqlPolicyDefinitionStore.class); - verify(config).getString(eq(DATASOURCE_NAME), any()); } } diff --git a/extensions/control-plane/store/sql/transfer-process-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtension.java b/extensions/control-plane/store/sql/transfer-process-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtension.java index 81ee4b8eaba..fffc3bb96e7 100644 --- a/extensions/control-plane/store/sql/transfer-process-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtension.java +++ b/extensions/control-plane/store/sql/transfer-process-store-sql/src/main/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtension.java @@ -27,7 +27,6 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -37,11 +36,8 @@ @Extension(value = "SQL transfer process store") public class SqlTransferProcessStoreExtension implements ServiceExtension { - @Deprecated(since = "0.8.1") - public static final String DATASOURCE_SETTING_NAME = "edc.datasource.transferprocess.name"; - - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.transferprocess.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.transferprocess.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -64,7 +60,6 @@ public class SqlTransferProcessStoreExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); var store = new SqlTransferProcessStore(dataSourceRegistry, dataSourceName, trxContext, typeManager.getMapper(), getStatementImpl(), context.getRuntimeId(), clock, queryExecutor); diff --git a/extensions/control-plane/store/sql/transfer-process-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtensionTest.java b/extensions/control-plane/store/sql/transfer-process-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtensionTest.java index f55cc38b075..9f48a28417f 100644 --- a/extensions/control-plane/store/sql/transfer-process-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtensionTest.java +++ b/extensions/control-plane/store/sql/transfer-process-store-sql/src/test/java/org/eclipse/edc/connector/controlplane/store/sql/transferprocess/SqlTransferProcessStoreExtensionTest.java @@ -26,11 +26,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.connector.controlplane.store.sql.transferprocess.SqlTransferProcessStoreExtension.DATASOURCE_NAME; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -52,6 +49,5 @@ void shouldInitializeTheStore(SqlTransferProcessStoreExtension extension, Servic var service = context.getService(TransferProcessStore.class); assertThat(service).isInstanceOf(SqlTransferProcessStore.class); - verify(config).getString(eq(DATASOURCE_NAME), any()); } } diff --git a/extensions/control-plane/transfer/transfer-data-plane-signaling/src/main/java/org/eclipse/edc/connector/controlplane/transfer/dataplane/TransferDataPlaneSignalingExtension.java b/extensions/control-plane/transfer/transfer-data-plane-signaling/src/main/java/org/eclipse/edc/connector/controlplane/transfer/dataplane/TransferDataPlaneSignalingExtension.java index d9384a86eaf..25cd7178ef3 100644 --- a/extensions/control-plane/transfer/transfer-data-plane-signaling/src/main/java/org/eclipse/edc/connector/controlplane/transfer/dataplane/TransferDataPlaneSignalingExtension.java +++ b/extensions/control-plane/transfer/transfer-data-plane-signaling/src/main/java/org/eclipse/edc/connector/controlplane/transfer/dataplane/TransferDataPlaneSignalingExtension.java @@ -39,8 +39,8 @@ public class TransferDataPlaneSignalingExtension implements ServiceExtension { private static final String DEFAULT_DATAPLANE_SELECTOR_STRATEGY = "random"; - @Setting(value = "Defines strategy for Data Plane instance selection in case Data Plane is not embedded in current runtime", defaultValue = DEFAULT_DATAPLANE_SELECTOR_STRATEGY) - private static final String DPF_SELECTOR_STRATEGY = "edc.dataplane.client.selector.strategy"; + @Setting(description = "Defines strategy for Data Plane instance selection in case Data Plane is not embedded in current runtime", defaultValue = DEFAULT_DATAPLANE_SELECTOR_STRATEGY, key = "edc.dataplane.client.selector.strategy") + private String selectionStrategy; @Inject private DataFlowManager dataFlowManager; @@ -62,7 +62,6 @@ public class TransferDataPlaneSignalingExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var selectionStrategy = context.getSetting(DPF_SELECTOR_STRATEGY, DEFAULT_DATAPLANE_SELECTOR_STRATEGY); var controller = new DataPlaneSignalingFlowController(callbackUrl, selectorService, getPropertiesProvider(), clientFactory, selectionStrategy, transferTypeParser); dataFlowManager.register(controller); diff --git a/extensions/control-plane/transfer/transfer-pull-http-dynamic-receiver/src/main/java/org/eclipse/edc/connector/controlplane/receiver/http/dynamic/HttpDynamicEndpointDataReferenceReceiverExtension.java b/extensions/control-plane/transfer/transfer-pull-http-dynamic-receiver/src/main/java/org/eclipse/edc/connector/controlplane/receiver/http/dynamic/HttpDynamicEndpointDataReferenceReceiverExtension.java index 7a0cac1e576..2e8d1a60ce2 100644 --- a/extensions/control-plane/transfer/transfer-pull-http-dynamic-receiver/src/main/java/org/eclipse/edc/connector/controlplane/receiver/http/dynamic/HttpDynamicEndpointDataReferenceReceiverExtension.java +++ b/extensions/control-plane/transfer/transfer-pull-http-dynamic-receiver/src/main/java/org/eclipse/edc/connector/controlplane/receiver/http/dynamic/HttpDynamicEndpointDataReferenceReceiverExtension.java @@ -31,13 +31,14 @@ public class HttpDynamicEndpointDataReferenceReceiverExtension implements Servic public static final String NAME = "Http Dynamic Endpoint Data Reference Receiver"; - @Setting(value = "Fallback endpoint when url is missing the the transfer process") - private static final String HTTP_RECEIVER_ENDPOINT = "edc.receiver.http.dynamic.endpoint"; + @Setting(description = "Fallback endpoint when url is missing the the transfer process", key = "edc.receiver.http.dynamic.endpoint", required = false) + private String fallbackEndpoint; - @Setting(value = "Header name that will be sent with the EDR") - private static final String HTTP_RECEIVER_AUTH_KEY = "edc.receiver.http.dynamic.auth-key"; - @Setting(value = "Header value that will be sent with the EDR") - private static final String HTTP_RECEIVER_AUTH_CODE = "edc.receiver.http.dynamic.auth-code"; + @Setting(description = "Header name that will be sent with the EDR", key = "edc.receiver.http.dynamic.auth-key", required = false) + private String authKey; + + @Setting(description = "Header value that will be sent with the EDR", key = "edc.receiver.http.dynamic.auth-code", required = false) + private String authCode; @Inject private EndpointDataReferenceReceiverRegistry receiverRegistry; @@ -65,10 +66,6 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var fallbackEndpoint = context.getSetting(HTTP_RECEIVER_ENDPOINT, null); - var authKey = context.getSetting(HTTP_RECEIVER_AUTH_KEY, null); - var authCode = context.getSetting(HTTP_RECEIVER_AUTH_CODE, null); - var receiver = HttpDynamicEndpointDataReferenceReceiver.Builder.newInstance() .httpClient(httpClient) .typeManager(typeManager) diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java index cd396708296..b6a3c652143 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java @@ -40,11 +40,11 @@ public class DataPlaneSelectorClientExtension implements ServiceExtension { public static final String NAME = "DataPlane Selector client"; - @Setting(value = "DataPlane selector api URL", required = true) - static final String DPF_SELECTOR_URL_SETTING = "edc.dpf.selector.url"; + @Setting(description = "DataPlane selector api URL", key = "edc.dpf.selector.url") + private String selectorApiUrl; - @Setting(value = "Defines strategy for Data Plane instance selection in case Data Plane is not embedded in current runtime", defaultValue = DataPlaneSelectorService.DEFAULT_STRATEGY) - private static final String DPF_SELECTOR_STRATEGY = "edc.dataplane.client.selector.strategy"; + @Setting(description = "Defines strategy for Data Plane instance selection in case Data Plane is not embedded in current runtime", defaultValue = DataPlaneSelectorService.DEFAULT_STRATEGY, key = "edc.dataplane.client.selector.strategy") + private String selectionStrategy; @Inject private ControlApiHttpClient httpClient; @@ -76,10 +76,7 @@ public void initialize(ServiceExtensionContext context) { @Provider public DataPlaneSelectorService dataPlaneSelectorService(ServiceExtensionContext context) { - var config = context.getConfig(); - var url = config.getString(DPF_SELECTOR_URL_SETTING); - var selectionStrategy = config.getString(DPF_SELECTOR_STRATEGY, DataPlaneSelectorService.DEFAULT_STRATEGY); - return new RemoteDataPlaneSelectorService(httpClient, url, typeManager.getMapper(JSON_LD), typeTransformerRegistry, + return new RemoteDataPlaneSelectorService(httpClient, selectorApiUrl, typeManager.getMapper(JSON_LD), typeTransformerRegistry, selectionStrategy, jsonLd); } } diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java b/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java index a9316bc1114..ddb31fa2405 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java @@ -14,6 +14,7 @@ package org.eclipse.edc.connector.dataplane.selector; +import org.eclipse.edc.boot.system.injection.ObjectFactory; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.system.ServiceExtensionContext; @@ -29,7 +30,6 @@ import static java.util.Collections.emptyMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.edc.connector.dataplane.selector.DataPlaneSelectorClientExtension.DPF_SELECTOR_URL_SETTING; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -43,11 +43,14 @@ class DataPlaneSelectorClientExtensionTest { @BeforeEach void setUp(ServiceExtensionContext context) { context.registerService(TypeTransformerRegistry.class, typeTransformerRegistry); + when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of("edc.dataplane.client.selector.strategy", "http://any", + "edc.dpf.selector.url", "http://any"))); + } @Test void dataPlaneSelectorService_shouldReturnRemoteService(DataPlaneSelectorClientExtension extension, ServiceExtensionContext context) { - when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of(DPF_SELECTOR_URL_SETTING, "http://any"))); + when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of())); var client = extension.dataPlaneSelectorService(context); @@ -55,11 +58,11 @@ void dataPlaneSelectorService_shouldReturnRemoteService(DataPlaneSelectorClientE } @Test - void dataPlaneSelectorService_shouldThrowException_whenUrlNotConfigured(DataPlaneSelectorClientExtension extension, ServiceExtensionContext context) { + void dataPlaneSelectorService_shouldThrowException_whenUrlNotConfigured(ServiceExtensionContext context, ObjectFactory objectFactory) { when(context.getConfig()).thenReturn(ConfigFactory.fromMap(emptyMap())); - assertThatThrownBy(() -> extension.dataPlaneSelectorService(context)).isInstanceOf(EdcException.class) - .hasMessageContaining("No setting found"); + assertThatThrownBy(() -> objectFactory.constructInstance(DataPlaneSelectorClientExtension.class).dataPlaneSelectorService(context)).isInstanceOf(EdcException.class) + .hasMessageContaining("No config value and no default value found for injected field"); } @Test diff --git a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtension.java b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtension.java index 7df92adda69..6e0f0773829 100644 --- a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtension.java +++ b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtension.java @@ -27,7 +27,6 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -41,12 +40,9 @@ public class SqlDataPlaneInstanceStoreExtension implements ServiceExtension { public static final String NAME = "Sql Data Plane Instance Store"; - @Deprecated(since = "0.8.1") - @Setting(value = "Name of the datasource to use for accessing data plane instances") - public static final String DATASOURCE_SETTING_NAME = "edc.datasource.dataplaneinstance.name"; - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.dataplaneinstance.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.dataplaneinstance.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -76,8 +72,6 @@ public String name() { @Provider public DataPlaneInstanceStore dataPlaneInstanceStore(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); - sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "dataplane-instance-schema.sql"); return new SqlDataPlaneInstanceStore(dataSourceRegistry, dataSourceName, transactionContext, getStatementImpl(), typeManager.getMapper(), queryExecutor, clock, context.getRuntimeId()); diff --git a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtensionTest.java b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtensionTest.java index 2c813bc488d..05572e75731 100644 --- a/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtensionTest.java +++ b/extensions/data-plane-selector/store/sql/data-plane-instance-store-sql/src/test/java/org/eclipse/edc/connector/dataplane/selector/store/sql/SqlDataPlaneInstanceStoreExtensionTest.java @@ -24,11 +24,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.connector.dataplane.selector.store.sql.SqlDataPlaneInstanceStoreExtension.DATASOURCE_NAME; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -48,6 +45,5 @@ void shouldInitializeTheStore(ServiceExtensionContext context, SqlDataPlaneInsta var store = extension.dataPlaneInstanceStore(context); assertThat(store).isInstanceOf(SqlDataPlaneInstanceStore.class); - verify(config).getString(eq(DATASOURCE_NAME), any()); } } diff --git a/extensions/data-plane/data-plane-http/src/main/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpExtension.java b/extensions/data-plane/data-plane-http/src/main/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpExtension.java index 910bff9a77c..84d3760da7e 100644 --- a/extensions/data-plane/data-plane-http/src/main/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpExtension.java +++ b/extensions/data-plane/data-plane-http/src/main/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpExtension.java @@ -41,8 +41,8 @@ public class DataPlaneHttpExtension implements ServiceExtension { public static final String NAME = "Data Plane HTTP"; private static final int DEFAULT_PARTITION_SIZE = 5; - @Setting(value = "Number of partitions for parallel message push in the HttpDataSink", type = "int", defaultValue = DEFAULT_PARTITION_SIZE + "") - private static final String EDC_DATAPLANE_HTTP_SINK_PARTITION_SIZE = "edc.dataplane.http.sink.partition.size"; + @Setting(description = "Number of partitions for parallel message push in the HttpDataSink", defaultValue = DEFAULT_PARTITION_SIZE + "", key = "edc.dataplane.http.sink.partition.size") + private int partitionSize; @Inject private EdcHttpClient httpClient; @@ -67,7 +67,6 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { var monitor = context.getMonitor(); - var sinkPartitionSize = context.getSetting(EDC_DATAPLANE_HTTP_SINK_PARTITION_SIZE, DEFAULT_PARTITION_SIZE); var paramsProvider = new HttpRequestParamsProviderImpl(vault, typeManager); context.registerService(HttpRequestParamsProvider.class, paramsProvider); @@ -77,7 +76,7 @@ public void initialize(ServiceExtensionContext context) { var sourceFactory = new HttpDataSourceFactory(httpClient, paramsProvider, monitor, httpRequestFactory); pipelineService.registerFactory(sourceFactory); - var sinkFactory = new HttpDataSinkFactory(httpClient, executorContainer.getExecutorService(), sinkPartitionSize, monitor, paramsProvider, httpRequestFactory); + var sinkFactory = new HttpDataSinkFactory(httpClient, executorContainer.getExecutorService(), partitionSize, monitor, paramsProvider, httpRequestFactory); pipelineService.registerFactory(sinkFactory); } diff --git a/extensions/data-plane/data-plane-iam/src/main/java/org/eclipse/edc/connector/dataplane/iam/DataPlaneIamDefaultServicesExtension.java b/extensions/data-plane/data-plane-iam/src/main/java/org/eclipse/edc/connector/dataplane/iam/DataPlaneIamDefaultServicesExtension.java index c799bd88e97..2e09a1c12e8 100644 --- a/extensions/data-plane/data-plane-iam/src/main/java/org/eclipse/edc/connector/dataplane/iam/DataPlaneIamDefaultServicesExtension.java +++ b/extensions/data-plane/data-plane-iam/src/main/java/org/eclipse/edc/connector/dataplane/iam/DataPlaneIamDefaultServicesExtension.java @@ -35,10 +35,11 @@ public class DataPlaneIamDefaultServicesExtension implements ServiceExtension { public static final String NAME = "Data Plane Default IAM Services"; - @Setting(value = "Alias of private key used for signing tokens, retrieved from private key resolver") - public static final String TOKEN_SIGNER_PRIVATE_KEY_ALIAS = "edc.transfer.proxy.token.signer.privatekey.alias"; - @Setting(value = "Alias of public key used for verifying the tokens, retrieved from the vault") - public static final String TOKEN_VERIFIER_PUBLIC_KEY_ALIAS = "edc.transfer.proxy.token.verifier.publickey.alias"; + @Setting(description = "Alias of private key used for signing tokens, retrieved from private key resolver", key = "edc.transfer.proxy.token.signer.privatekey.alias") + private String tokenSignerPrivateKeyAlias; + + @Setting(description = "Alias of public key used for verifying the tokens, retrieved from the vault", key = "edc.transfer.proxy.token.verifier.publickey.alias") + private String tokenVerifierPublicKeyAlias; @Inject private AccessTokenDataStore accessTokenDataStore; @@ -62,8 +63,6 @@ public DataPlaneAccessControlService defaultAccessControlService(ServiceExtensio @Provider(isDefault = true) public DataPlaneAccessTokenService defaultAccessTokenService(ServiceExtensionContext context) { - var tokenVerifierPublicKeyAlias = context.getConfig().getString(TOKEN_VERIFIER_PUBLIC_KEY_ALIAS); - var tokenSignerPrivateKeyAlias = context.getConfig().getString(TOKEN_SIGNER_PRIVATE_KEY_ALIAS); var monitor = context.getMonitor().withPrefix("DataPlane IAM"); return new DefaultDataPlaneAccessTokenServiceImpl(new JwtGenerationService(jwsSignerProvider), accessTokenDataStore, monitor, diff --git a/extensions/data-plane/data-plane-kafka/src/main/java/org/eclipse/edc/connector/dataplane/kafka/DataPlaneKafkaExtension.java b/extensions/data-plane/data-plane-kafka/src/main/java/org/eclipse/edc/connector/dataplane/kafka/DataPlaneKafkaExtension.java index 89d93eeb5bb..c7e1f3bc2ad 100644 --- a/extensions/data-plane/data-plane-kafka/src/main/java/org/eclipse/edc/connector/dataplane/kafka/DataPlaneKafkaExtension.java +++ b/extensions/data-plane/data-plane-kafka/src/main/java/org/eclipse/edc/connector/dataplane/kafka/DataPlaneKafkaExtension.java @@ -34,8 +34,8 @@ public class DataPlaneKafkaExtension implements ServiceExtension { private static final int DEFAULT_PARTITION_SIZE = 5; - @Setting(value = "The partitionSize used by the kafka data sink", type = "int", defaultValue = DEFAULT_PARTITION_SIZE + "", min = 1) - private static final String EDC_DATAPLANE_KAFKA_SINK_PARTITION_SIZE = "edc.dataplane.kafka.sink.partition.size"; + @Setting(description = "The partitionSize used by the kafka data sink", defaultValue = DEFAULT_PARTITION_SIZE + "", min = 1, key = "edc.dataplane.kafka.sink.partition.size") + private int partitionSize; @Inject private DataTransferExecutorServiceContainer executorContainer; @@ -56,9 +56,8 @@ public void initialize(ServiceExtensionContext context) { var monitor = context.getMonitor(); var propertiesFactory = new KafkaPropertiesFactory(); - var sinkPartitionSize = context.getSetting(EDC_DATAPLANE_KAFKA_SINK_PARTITION_SIZE, DEFAULT_PARTITION_SIZE); pipelineService.registerFactory(new KafkaDataSourceFactory(monitor, propertiesFactory, clock)); - pipelineService.registerFactory(new KafkaDataSinkFactory(executorContainer.getExecutorService(), monitor, propertiesFactory, sinkPartitionSize)); + pipelineService.registerFactory(new KafkaDataSinkFactory(executorContainer.getExecutorService(), monitor, propertiesFactory, partitionSize)); } } diff --git a/extensions/data-plane/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlanePublicApiV2Extension.java b/extensions/data-plane/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlanePublicApiV2Extension.java index 8fccc2cfed8..0b392be5c3e 100644 --- a/extensions/data-plane/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlanePublicApiV2Extension.java +++ b/extensions/data-plane/data-plane-public-api-v2/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlanePublicApiV2Extension.java @@ -49,12 +49,14 @@ public class DataPlanePublicApiV2Extension implements ServiceExtension { @SettingContext("Public API context setting key") private static final String PUBLIC_CONFIG_KEY = "web.http." + ApiContext.PUBLIC; - @Setting(value = "Base url of the public API endpoint without the trailing slash. This should correspond to the values configured " + - "in '" + DEFAULT_PUBLIC_PORT + "' and '" + PUBLIC_CONTEXT_PATH + "'.", defaultValue = "http://:" + DEFAULT_PUBLIC_PORT + PUBLIC_CONTEXT_PATH) - private static final String PUBLIC_ENDPOINT = "edc.dataplane.api.public.baseurl"; + @Setting(description = "Base url of the public API endpoint without the trailing slash. This should correspond to the values configured " + + "in '" + DEFAULT_PUBLIC_PORT + "' and '" + PUBLIC_CONTEXT_PATH + "'.", + required = false, + key = "edc.dataplane.api.public.baseurl", warnOnMissingConfig = true) + private String publicBaseUrl; - @Setting(value = "Optional base url of the response channel endpoint without the trailing slash. A common practice is to use /responseChannel") - private static final String PUBLIC_RESPONSE_ENDPOINT = "edc.dataplane.api.public.response.baseurl"; + @Setting(description = "Optional base url of the response channel endpoint without the trailing slash. A common practice is to use /responseChannel", key = "edc.dataplane.api.public.response.baseurl", required = false) + private String publicApiResponseUrl; private static final int DEFAULT_THREAD_POOL = 10; private static final WebServiceSettings PUBLIC_SETTINGS = WebServiceSettings.Builder.newInstance() @@ -103,17 +105,16 @@ public void initialize(ServiceExtensionContext context) { "Data plane proxy transfers" ); - var publicEndpoint = context.getSetting(PUBLIC_ENDPOINT, null); - if (publicEndpoint == null) { - publicEndpoint = "http://%s:%d%s".formatted(hostname.get(), configuration.getPort(), configuration.getPath()); - context.getMonitor().warning("Config property '%s' was not specified, the default '%s' will be used.".formatted(PUBLIC_ENDPOINT, publicEndpoint)); + + if (publicBaseUrl == null) { + publicBaseUrl = "http://%s:%d%s".formatted(hostname.get(), configuration.getPort(), configuration.getPath()); + context.getMonitor().warning("The public API endpoint was not explicitly configured, the default '%s' will be used.".formatted(publicBaseUrl)); } - var endpoint = Endpoint.url(publicEndpoint); + var endpoint = Endpoint.url(publicBaseUrl); generatorService.addGeneratorFunction("HttpData", dataAddress -> endpoint); - var responseEndpoint = context.getSetting(PUBLIC_RESPONSE_ENDPOINT, null); - if (responseEndpoint != null) { - generatorService.addGeneratorFunction("HttpData", () -> Endpoint.url(responseEndpoint)); + if (publicApiResponseUrl != null) { + generatorService.addGeneratorFunction("HttpData", () -> Endpoint.url(publicApiResponseUrl)); } var publicApiController = new DataPlanePublicApiV2Controller(pipelineService, executorService, authorizationService); diff --git a/extensions/data-plane/data-plane-self-registration/src/main/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtension.java b/extensions/data-plane/data-plane-self-registration/src/main/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtension.java index 922747eca10..300465fb841 100644 --- a/extensions/data-plane/data-plane-self-registration/src/main/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtension.java +++ b/extensions/data-plane/data-plane-self-registration/src/main/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtension.java @@ -48,8 +48,9 @@ public class DataplaneSelfRegistrationExtension implements ServiceExtension { public static final boolean DEFAULT_SELF_UNREGISTRATION = false; public static final String NAME = "Dataplane Self Registration"; - @Setting(value = "Enable data-plane un-registration at shutdown (not suggested for clustered environments)", type = "boolean", defaultValue = DEFAULT_SELF_UNREGISTRATION + "") - static final String SELF_UNREGISTRATION = "edc.data.plane.self.unregistration"; + @Setting(description = "Enable data-plane un-registration at shutdown (not suggested for clustered environments)", defaultValue = DEFAULT_SELF_UNREGISTRATION + "", key = "edc.data.plane.self.unregistration") + private boolean selfUnregistration; + private final AtomicBoolean isRegistered = new AtomicBoolean(false); private final AtomicReference registrationError = new AtomicReference<>("Data plane self registration not complete"); @Inject @@ -108,7 +109,7 @@ public void start() { @Override public void shutdown() { - if (context.getConfig().getBoolean(SELF_UNREGISTRATION, DEFAULT_SELF_UNREGISTRATION)) { + if (selfUnregistration) { dataPlaneSelectorService.unregister(context.getComponentId()) .onSuccess(it -> context.getMonitor().debug("data plane successfully unregistered")) .onFailure(failure -> context.getMonitor().severe("error during data plane de-registration. %s: %s" diff --git a/extensions/data-plane/data-plane-self-registration/src/test/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtensionTest.java b/extensions/data-plane/data-plane-self-registration/src/test/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtensionTest.java index e8e51baee06..a00b25888df 100644 --- a/extensions/data-plane/data-plane-self-registration/src/test/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtensionTest.java +++ b/extensions/data-plane/data-plane-self-registration/src/test/java/org/eclipse/edc/connector/dataplane/registration/DataplaneSelfRegistrationExtensionTest.java @@ -14,6 +14,7 @@ package org.eclipse.edc.connector.dataplane.registration; +import org.eclipse.edc.boot.system.injection.ObjectFactory; import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; import org.eclipse.edc.connector.dataplane.selector.spi.instance.DataPlaneInstance; import org.eclipse.edc.connector.dataplane.spi.iam.PublicEndpointGeneratorService; @@ -39,7 +40,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.edc.connector.dataplane.registration.DataplaneSelfRegistrationExtension.SELF_UNREGISTRATION; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; @@ -117,13 +117,15 @@ void shouldNotUnregisterInstanceAtShutdown(DataplaneSelfRegistrationExtension ex } @Test - void shouldUnregisterInstanceAtShutdown_whenConfigured(DataplaneSelfRegistrationExtension extension, ServiceExtensionContext context) { + void shouldUnregisterInstanceAtShutdown_whenConfigured(ServiceExtensionContext context, ObjectFactory objectFactory) { when(context.getComponentId()).thenReturn("componentId"); - when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of(SELF_UNREGISTRATION, "true"))); + when(context.getConfig()).thenReturn(ConfigFactory.fromMap(Map.of("edc.data.plane.self.unregistration", "true"))); when(dataPlaneSelectorService.unregister(any())).thenReturn(ServiceResult.success()); - extension.initialize(context); - extension.shutdown(); + var ext = objectFactory.constructInstance(DataplaneSelfRegistrationExtension.class); + ext.initialize(context); + + ext.shutdown(); verify(dataPlaneSelectorService).unregister("componentId"); } diff --git a/extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreExtension.java b/extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreExtension.java index 7a7c8922711..0419022ad71 100644 --- a/extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreExtension.java +++ b/extensions/data-plane/store/sql/accesstokendata-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlAccessTokenDataStoreExtension.java @@ -27,7 +27,6 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -41,12 +40,8 @@ public class SqlAccessTokenDataStoreExtension implements ServiceExtension { public static final String NAME = "Sql AccessTokenData Store"; - @Deprecated(since = "0.8.1") - @Setting(value = "Name of the datasource to use for accessing data plane store") - private static final String DATASOURCE_SETTING_NAME = "edc.datasource.accesstokendata.name"; - - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.accesstokendata.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.accesstokendata.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -75,8 +70,6 @@ public String name() { @Provider public AccessTokenDataStore dataPlaneStore(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); - sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "accesstoken-data-schema.sql"); return new SqlAccessTokenDataStore(dataSourceRegistry, dataSourceName, transactionContext, getStatementImpl(), typeManager.getMapper(), queryExecutor); diff --git a/extensions/data-plane/store/sql/data-plane-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlDataPlaneStoreExtension.java b/extensions/data-plane/store/sql/data-plane-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlDataPlaneStoreExtension.java index 874df08169c..c66a4836fc5 100644 --- a/extensions/data-plane/store/sql/data-plane-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlDataPlaneStoreExtension.java +++ b/extensions/data-plane/store/sql/data-plane-store-sql/src/main/java/org/eclipse/edc/connector/dataplane/store/sql/SqlDataPlaneStoreExtension.java @@ -26,7 +26,6 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; @@ -40,12 +39,8 @@ public class SqlDataPlaneStoreExtension implements ServiceExtension { public static final String NAME = "Sql Data Plane Store"; - @Deprecated(since = "0.8.1") - @Setting(value = "Name of the datasource to use for accessing data plane store") - private static final String DATASOURCE_SETTING_NAME = "edc.datasource.dataplane.name"; - - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.dataplane.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.dataplane.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -74,8 +69,6 @@ public String name() { @Provider public DataPlaneStore dataPlaneStore(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); - sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "dataplane-schema.sql"); return new SqlDataPlaneStore(dataSourceRegistry, dataSourceName, transactionContext, getStatementImpl(), typeManager.getMapper(), clock, queryExecutor, context.getRuntimeId()); diff --git a/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/java/org/eclipse/edc/connector/policy/monitor/store/sql/SqlPolicyMonitorStoreExtension.java b/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/java/org/eclipse/edc/connector/policy/monitor/store/sql/SqlPolicyMonitorStoreExtension.java index 3420ebdff23..1a500046ca7 100644 --- a/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/java/org/eclipse/edc/connector/policy/monitor/store/sql/SqlPolicyMonitorStoreExtension.java +++ b/extensions/policy-monitor/store/sql/policy-monitor-store-sql/src/main/java/org/eclipse/edc/connector/policy/monitor/store/sql/SqlPolicyMonitorStoreExtension.java @@ -25,22 +25,15 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.bootstrapper.SqlSchemaBootstrapper; -import org.eclipse.edc.sql.configuration.DataSourceName; import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; import org.eclipse.edc.transaction.spi.TransactionContext; import java.time.Clock; -import static org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry.DEFAULT_DATASOURCE; - public class SqlPolicyMonitorStoreExtension implements ServiceExtension { - @Deprecated(since = "0.8.1") - @Setting(value = "Name of the datasource to use for accessing policy monitor store", defaultValue = DEFAULT_DATASOURCE) - private static final String DATASOURCE_SETTING_NAME = "edc.datasource.policy-monitor.name"; - - @Setting(value = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_NAME = "edc.sql.store.policy-monitor.datasource"; + @Setting(description = "The datasource to be used", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE, key = "edc.sql.store.policy-monitor.datasource") + private String dataSourceName; @Inject private DataSourceRegistry dataSourceRegistry; @@ -65,7 +58,6 @@ public class SqlPolicyMonitorStoreExtension implements ServiceExtension { @Provider public PolicyMonitorStore policyMonitorStore(ServiceExtensionContext context) { - var dataSourceName = DataSourceName.getDataSourceName(DATASOURCE_NAME, DATASOURCE_SETTING_NAME, context.getConfig(), context.getMonitor()); sqlSchemaBootstrapper.addStatementFromResource(dataSourceName, "policy-monitor-schema.sql"); diff --git a/system-tests/bom-tests/src/test/java/org/eclipse/edc/test/bom/BomSmokeTests.java b/system-tests/bom-tests/src/test/java/org/eclipse/edc/test/bom/BomSmokeTests.java index 1846433a131..e680c272c87 100644 --- a/system-tests/bom-tests/src/test/java/org/eclipse/edc/test/bom/BomSmokeTests.java +++ b/system-tests/bom-tests/src/test/java/org/eclipse/edc/test/bom/BomSmokeTests.java @@ -78,6 +78,9 @@ class ControlPlaneDcp extends SmokeTest { put("web.http.control.path", "/api/control"); put("web.http.management.port", "8081"); put("web.http.management.path", "/api/management"); + put("edc.iam.sts.privatekey.alias", "privatekey"); + put("edc.iam.sts.publickey.id", "publickey"); + put("edc.iam.issuer.id", "did:web:someone"); } }, ":dist:bom:controlplane-dcp-bom"