diff --git a/deployment/helm/ditto/Chart.yaml b/deployment/helm/ditto/Chart.yaml index fc975f04da..f21668b955 100644 --- a/deployment/helm/ditto/Chart.yaml +++ b/deployment/helm/ditto/Chart.yaml @@ -16,7 +16,7 @@ description: | A digital twin is a virtual, cloud based, representation of his real world counterpart (real world “Things”, e.g. devices like sensors, smart heating, connected cars, smart grids, EV charging stations etc). type: application -version: 3.5.8 # chart version is effectively set by release-job +version: 3.5.9-0 # chart version is effectively set by release-job appVersion: 3.5.6 keywords: - iot-chart diff --git a/deployment/helm/ditto/templates/gateway-deployment.yaml b/deployment/helm/ditto/templates/gateway-deployment.yaml index 580e3d8115..f7e610a92c 100644 --- a/deployment/helm/ditto/templates/gateway-deployment.yaml +++ b/deployment/helm/ditto/templates/gateway-deployment.yaml @@ -149,6 +149,12 @@ spec: "{{ printf "%s%s%s%d=%s" "-Dditto.gateway.authentication.devops.oauth.openid-connect-issuers." $key ".auth-subjects." $index $subject }}" {{- end }} {{- end }} + {{- range $index, $oauthSubject := .Values.gateway.config.authentication.devops.oauthSubjects }} + "{{ printf "%s%d=%s" "-Dditto.gateway.authentication.devops.devops-oauth2-subjects." $index $oauthSubject }}" + {{- end }} + {{- range $index, $oauthSubject := .Values.gateway.config.authentication.devops.statusOauthSubjects }} + "{{ printf "%s%d=%s" "-Dditto.gateway.authentication.devops.status-oauth2-subjects." $index $oauthSubject }}" + {{- end }} {{ join " " .Values.gateway.systemProps }} - name: CLUSTER_BS_REQUIRED_CONTACTS value: "{{ .Values.global.cluster.requiredContactPoints }}" @@ -191,10 +197,6 @@ spec: secretKeyRef: name: {{ .Values.gateway.config.authentication.devops.existingSecret | default ( printf "%s-gateway-secret" ( include "ditto.fullname" . )) }} key: devops-password - {{- range $index, $oauthSubject := .Values.gateway.config.authentication.devops.oauthSubjects }} - - name: DEVOPS_OAUTH2_SUBJECTS.{{ $index }} - value: "{{ $oauthSubject }}" - {{- end }} - name: DEVOPS_STATUS_SECURED value: "{{ .Values.gateway.config.authentication.devops.statusSecured }}" - name: STATUS_AUTHENTICATION_METHOD @@ -204,10 +206,6 @@ spec: secretKeyRef: name: {{ .Values.gateway.config.authentication.devops.existingSecret | default ( printf "%s-gateway-secret" ( include "ditto.fullname" . )) }} key: status-password - {{- range $index, $oauthSubject := .Values.gateway.config.authentication.devops.statusOauthSubjects }} - - name: STATUS_OAUTH2_SUBJECTS.{{ $index }} - value: "{{ $oauthSubject }}" - {{- end }} - name: WS_SUBSCRIBER_BACKPRESSURE value: "{{ .Values.gateway.config.websocket.subscriber.backpressureQueueSize }}" - name: WS_PUBLISHER_BACKPRESSURE diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/actors/AbstractConnectionsRetrievalActor.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/actors/AbstractConnectionsRetrievalActor.java index cc6e3135bc..d2212af6d8 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/actors/AbstractConnectionsRetrievalActor.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/actors/AbstractConnectionsRetrievalActor.java @@ -26,6 +26,11 @@ import javax.annotation.Nullable; +import org.apache.pekko.actor.AbstractActor; +import org.apache.pekko.actor.ActorRef; +import org.apache.pekko.actor.ReceiveTimeout; +import org.apache.pekko.japi.pf.ReceiveBuilder; +import org.apache.pekko.pattern.Patterns; import org.eclipse.ditto.base.model.exceptions.DittoRuntimeException; import org.eclipse.ditto.base.model.headers.DittoHeaders; import org.eclipse.ditto.base.model.headers.WithDittoHeaders; @@ -43,19 +48,13 @@ import org.eclipse.ditto.connectivity.model.signals.commands.query.RetrieveConnectionsResponse; import org.eclipse.ditto.gateway.service.util.config.DittoGatewayConfig; import org.eclipse.ditto.gateway.service.util.config.endpoints.CommandConfig; +import org.eclipse.ditto.internal.utils.config.DefaultScopedConfig; import org.eclipse.ditto.internal.utils.pekko.logging.DittoLoggerFactory; import org.eclipse.ditto.internal.utils.pekko.logging.ThreadSafeDittoLogger; -import org.eclipse.ditto.internal.utils.config.DefaultScopedConfig; import org.eclipse.ditto.json.JsonArray; import org.eclipse.ditto.json.JsonCollectors; import org.eclipse.ditto.json.JsonFieldSelector; -import org.apache.pekko.actor.AbstractActor; -import org.apache.pekko.actor.ActorRef; -import org.apache.pekko.actor.ReceiveTimeout; -import org.apache.pekko.japi.pf.ReceiveBuilder; -import org.apache.pekko.pattern.Patterns; - /** * Abstract actor for retrieving multiple connections. @@ -195,20 +194,19 @@ private CompletionStage retrieveConnection(final Ret private CompletionStage askConnectivity(final RetrieveConnection command) { - logger.withCorrelationId(command).debug("Sending command <{}> to connectivity.service.", command); + final ThreadSafeDittoLogger log = logger.withCorrelationId(command); + log.debug("Sending command <{}> to connectivity.service.", command); final var commandWithCorrelationId = ensureCommandHasCorrelationId(command); Duration askTimeout = initialCommand.getDittoHeaders().getTimeout().orElse(defaultTimeout); return Patterns.ask(edgeCommandForwarder, commandWithCorrelationId, askTimeout) .thenApply(response -> { - logger.withCorrelationId(command) - .debug("Received response <{}> from connectivity.service.", response); + log.debug("Received response <{}> from connectivity service", response); throwCauseIfErrorResponse(response); throwCauseIfDittoRuntimeException(response); final RetrieveConnectionResponse mappedResponse = mapToType(response, RetrieveConnectionResponse.class, command); - logger.withCorrelationId(command) - .info("Received response of type <{}> from connectivity.service.", - mappedResponse.getType()); + log.info("Received response of type <{}> for id <{}> from connectivity service", + mappedResponse.getType(), mappedResponse.getEntityId()); return mappedResponse; }); } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsBasicAuthenticationDirective.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsBasicAuthenticationDirective.java index f3aad54674..356caa0251 100755 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsBasicAuthenticationDirective.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsBasicAuthenticationDirective.java @@ -20,20 +20,21 @@ import java.util.Optional; import java.util.function.Function; -import org.eclipse.ditto.gateway.service.util.config.security.DevOpsConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.apache.pekko.http.javadsl.server.Directives; import org.apache.pekko.http.javadsl.server.Route; import org.apache.pekko.http.javadsl.server.directives.SecurityDirectives; +import org.eclipse.ditto.base.model.headers.DittoHeaders; +import org.eclipse.ditto.gateway.service.util.config.security.DevOpsConfig; +import org.eclipse.ditto.internal.utils.pekko.logging.DittoLoggerFactory; +import org.eclipse.ditto.internal.utils.pekko.logging.ThreadSafeDittoLogger; /** * Custom Pekko Http directive performing basic auth for a defined {@link #USER_DEVOPS devops user}. */ public final class DevOpsBasicAuthenticationDirective implements DevopsAuthenticationDirective { - private static final Logger LOGGER = LoggerFactory.getLogger(DevOpsBasicAuthenticationDirective.class); + private static final ThreadSafeDittoLogger LOGGER = + DittoLoggerFactory.getThreadSafeLogger(DevOpsBasicAuthenticationDirective.class); private static final String USER_DEVOPS = "devops"; @@ -65,15 +66,9 @@ public static DevOpsBasicAuthenticationDirective status(final DevOpsConfig devOp return new DevOpsBasicAuthenticationDirective(devOpsConfig.getPassword(), devOpsConfig.getStatusPassword()); } - /** - * Authenticates the devops resources with the chosen authentication method. - * - * @param realm the realm to apply. - * @param inner the inner route, which will be performed on successful authentication. - * @return the inner route wrapped with authentication. - */ - public Route authenticateDevOps(final String realm, final Route inner) { - LOGGER.debug("DevOps basic authentication is enabled for {}.", realm); + @Override + public Route authenticateDevOps(final String realm, final DittoHeaders dittoHeaders, final Route inner) { + LOGGER.withCorrelationId(dittoHeaders).debug("DevOps basic authentication is enabled for {}.", realm); return Directives.authenticateBasic(realm, new BasicAuthenticator(passwords), userName -> inner); } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsInsecureAuthenticationDirective.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsInsecureAuthenticationDirective.java index f363306391..c516dafcd3 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsInsecureAuthenticationDirective.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsInsecureAuthenticationDirective.java @@ -12,17 +12,17 @@ */ package org.eclipse.ditto.gateway.service.endpoints.directives.auth; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.apache.pekko.http.javadsl.server.Route; +import org.eclipse.ditto.base.model.headers.DittoHeaders; +import org.eclipse.ditto.internal.utils.pekko.logging.DittoLogger; +import org.eclipse.ditto.internal.utils.pekko.logging.DittoLoggerFactory; /** * Authentication directive which does not perform any authentication. */ public final class DevOpsInsecureAuthenticationDirective implements DevopsAuthenticationDirective { - private static final Logger LOGGER = LoggerFactory.getLogger(DevOpsInsecureAuthenticationDirective.class); + private static final DittoLogger LOGGER = DittoLoggerFactory.getLogger(DevOpsInsecureAuthenticationDirective.class); private static final DevOpsInsecureAuthenticationDirective INSTANCE = new DevOpsInsecureAuthenticationDirective(); private DevOpsInsecureAuthenticationDirective() {} @@ -32,8 +32,8 @@ public static DevOpsInsecureAuthenticationDirective getInstance() { } @Override - public Route authenticateDevOps(final String realm, final Route inner) { - LOGGER.warn("DevOps resource is not secured"); + public Route authenticateDevOps(final String realm, final DittoHeaders dittoHeaders, final Route inner) { + LOGGER.withCorrelationId(dittoHeaders).warn("DevOps resource is not secured"); return inner; } } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsOAuth2AuthenticationDirective.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsOAuth2AuthenticationDirective.java index cc96f5ac49..8dd8822bb3 100755 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsOAuth2AuthenticationDirective.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevOpsOAuth2AuthenticationDirective.java @@ -30,8 +30,8 @@ import org.eclipse.ditto.gateway.service.security.authentication.AuthenticationResult; import org.eclipse.ditto.gateway.service.security.authentication.jwt.JwtAuthenticationProvider; import org.eclipse.ditto.gateway.service.util.config.security.DevOpsConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.eclipse.ditto.internal.utils.pekko.logging.DittoLoggerFactory; +import org.eclipse.ditto.internal.utils.pekko.logging.ThreadSafeDittoLogger; import scala.util.Try; @@ -40,7 +40,8 @@ */ public final class DevOpsOAuth2AuthenticationDirective implements DevopsAuthenticationDirective { - private static final Logger LOGGER = LoggerFactory.getLogger(DevOpsOAuth2AuthenticationDirective.class); + private static final ThreadSafeDittoLogger LOGGER = + DittoLoggerFactory.getThreadSafeLogger(DevOpsOAuth2AuthenticationDirective.class); /** * The Http basic auth realm for the "ditto-devops" user used for /devops resource. @@ -92,38 +93,37 @@ public static DevOpsOAuth2AuthenticationDirective devops(final DevOpsConfig devO return new DevOpsOAuth2AuthenticationDirective(jwtAuthenticationProvider, expectedSubjects); } - /** - * Authenticates the devops resources with the chosen authentication method. - * - * @param realm the realm to apply. - * @param inner the inner route, which will be performed on successful authentication. - * @return the inner route wrapped with authentication. - */ - public Route authenticateDevOps(final String realm, final Route inner) { - LOGGER.debug("DevOps OAuth authentication is enabled for {}.", realm); + @Override + public Route authenticateDevOps(final String realm, final DittoHeaders dittoHeaders, final Route inner) { + final ThreadSafeDittoLogger logger = LOGGER.withCorrelationId(dittoHeaders); + logger.debug("DevOps OAuth authentication is enabled for {}.", realm); return extractRequestContext(requestContext -> { final String authorizationHeaderValue = requestContext.getRequest() .getHeader("authorization") .map(HttpHeader::value) .orElse(""); - LOGGER.debug("Trying to use OAuth2 authentication for authorization header <{}>", authorizationHeaderValue); + logger.debug("Trying to use OAuth2 authentication for authorization header <{}>", authorizationHeaderValue); final CompletionStage authenticationResult = - jwtAuthenticationProvider.authenticate(requestContext, DittoHeaders.empty()); + jwtAuthenticationProvider.authenticate(requestContext, dittoHeaders); final Function, Route> handleAuthenticationTry = - authenticationResultTry -> handleAuthenticationTry(authenticationResultTry, inner, requestContext); + authenticationResultTry -> + handleAuthenticationTry(authenticationResultTry, dittoHeaders, inner, requestContext); return Directives.onComplete(authenticationResult, handleAuthenticationTry); }); } - private Route handleAuthenticationTry(final Try authenticationResultTry, final Route inner, + private Route handleAuthenticationTry(final Try authenticationResultTry, + final DittoHeaders dittoHeaders, + final Route inner, final RequestContext requestContext) { if (authenticationResultTry.isSuccess()) { final AuthenticationResult authenticationResult = authenticationResultTry.get(); + final ThreadSafeDittoLogger logger = LOGGER.withCorrelationId(dittoHeaders); if (!authenticationResult.isSuccess()) { - LOGGER.info("DevOps OAuth authentication was not successful for request: '{}' because of '{}'.", + logger.info("DevOps OAuth authentication was not successful for request: '{}' because of '{}'.", requestContext.getRequest(), authenticationResult.getReasonOfFailure().getMessage()); return Directives.failWith(authenticationResult.getReasonOfFailure()); } else { @@ -131,7 +131,8 @@ private Route handleAuthenticationTry(final Try authentica authenticationResult.getAuthorizationContext().getAuthorizationSubjectIds(); final boolean isAuthorized = expectedSubjects.isEmpty() || authorizationSubjectIds.stream().anyMatch(expectedSubjects::contains); if (isAuthorized) { - LOGGER.info("DevOps Oauth authentication was successful."); + logger.info("DevOps Oauth authentication was successful, user subjects {} were " + + "part of expected subjects: {}", authorizationSubjectIds, expectedSubjects); return inner; } else { final String message = String.format( @@ -139,8 +140,8 @@ private Route handleAuthenticationTry(final Try authentica authorizationSubjectIds, expectedSubjects ); final GatewayAuthenticationFailedException reasonOfFailure = - GatewayAuthenticationFailedException.fromMessage(message, DittoHeaders.empty()); - LOGGER.warn("DevOps Oauth authentication failed.", reasonOfFailure); + GatewayAuthenticationFailedException.fromMessage(message, dittoHeaders); + logger.warn("DevOps Oauth authentication failed.", reasonOfFailure); return Directives.failWith(reasonOfFailure); } } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevopsAuthenticationDirective.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevopsAuthenticationDirective.java index 0d4baef805..35eaddb217 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevopsAuthenticationDirective.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevopsAuthenticationDirective.java @@ -13,6 +13,7 @@ package org.eclipse.ditto.gateway.service.endpoints.directives.auth; import org.apache.pekko.http.javadsl.server.Route; +import org.eclipse.ditto.base.model.headers.DittoHeaders; /** @@ -21,6 +22,14 @@ @FunctionalInterface public interface DevopsAuthenticationDirective { - Route authenticateDevOps(final String realm, final Route inner); + /** + * Authenticates the devops resources with the chosen authentication method. + * + * @param realm the realm to apply. + * @param dittoHeaders the DittoHeaders to use for logging. + * @param inner the inner route, which will be performed on successful authentication. + * @return the inner route wrapped with authentication. + */ + Route authenticateDevOps(String realm, DittoHeaders dittoHeaders, Route inner); } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevopsAuthenticationDirectiveFactory.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevopsAuthenticationDirectiveFactory.java index 19e0ec35f6..2ea6f86a99 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevopsAuthenticationDirectiveFactory.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DevopsAuthenticationDirectiveFactory.java @@ -16,6 +16,8 @@ import org.eclipse.ditto.gateway.service.security.authentication.jwt.JwtAuthenticationProvider; import org.eclipse.ditto.gateway.service.util.config.security.DevOpsConfig; +import com.typesafe.config.Config; + public final class DevopsAuthenticationDirectiveFactory { private final JwtAuthenticationProvider jwtAuthenticationProvider; @@ -29,13 +31,15 @@ private DevopsAuthenticationDirectiveFactory(final JwtAuthenticationProvider jwt } public static DevopsAuthenticationDirectiveFactory newInstance( - final JwtAuthenticationFactory jwtAuthenticationFactory, final DevOpsConfig devOpsConfig) { + final JwtAuthenticationFactory jwtAuthenticationFactory, final DevOpsConfig devOpsConfig, + final Config dittoExtensionConfig) { final JwtAuthenticationProvider jwtAuthenticationProvider = JwtAuthenticationProvider.newInstance( jwtAuthenticationFactory.newJwtAuthenticationResultProvider( - "ditto.gateway.authentication.devops.oauth" + dittoExtensionConfig, "devops" ), - jwtAuthenticationFactory.getJwtValidator()); + jwtAuthenticationFactory.getJwtValidator() + ); return new DevopsAuthenticationDirectiveFactory(jwtAuthenticationProvider, devOpsConfig); } @@ -43,15 +47,10 @@ public DevopsAuthenticationDirective status() { if (!devOpsConfig.isSecured() || !devOpsConfig.isStatusSecured()) { return DevOpsInsecureAuthenticationDirective.getInstance(); } - switch (devOpsConfig.getStatusAuthenticationMethod()) { - case BASIC: - return DevOpsBasicAuthenticationDirective.status(devOpsConfig); - case OAUTH2: - return DevOpsOAuth2AuthenticationDirective.status(devOpsConfig, jwtAuthenticationProvider); - default: - throw new IllegalStateException( - "Unknown devops authentication method: " + devOpsConfig.getStatusAuthenticationMethod()); - } + return switch (devOpsConfig.getStatusAuthenticationMethod()) { + case BASIC -> DevOpsBasicAuthenticationDirective.status(devOpsConfig); + case OAUTH2 -> DevOpsOAuth2AuthenticationDirective.status(devOpsConfig, jwtAuthenticationProvider); + }; } @@ -59,14 +58,9 @@ public DevopsAuthenticationDirective devops() { if (!devOpsConfig.isSecured()) { return DevOpsInsecureAuthenticationDirective.getInstance(); } - switch (devOpsConfig.getDevopsAuthenticationMethod()) { - case BASIC: - return DevOpsBasicAuthenticationDirective.devops(devOpsConfig); - case OAUTH2: - return DevOpsOAuth2AuthenticationDirective.devops(devOpsConfig, jwtAuthenticationProvider); - default: - throw new IllegalStateException( - "Unknown devops authentication method: " + devOpsConfig.getStatusAuthenticationMethod()); - } + return switch (devOpsConfig.getDevopsAuthenticationMethod()) { + case BASIC -> DevOpsBasicAuthenticationDirective.devops(devOpsConfig); + case OAUTH2 -> DevOpsOAuth2AuthenticationDirective.devops(devOpsConfig, jwtAuthenticationProvider); + }; } } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DittoGatewayAuthenticationDirectiveFactory.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DittoGatewayAuthenticationDirectiveFactory.java index de21c597e0..9eab428bcb 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DittoGatewayAuthenticationDirectiveFactory.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/directives/auth/DittoGatewayAuthenticationDirectiveFactory.java @@ -16,6 +16,7 @@ import java.util.Collection; import java.util.concurrent.Executor; +import org.apache.pekko.actor.ActorSystem; import org.eclipse.ditto.gateway.service.security.authentication.AuthenticationChain; import org.eclipse.ditto.gateway.service.security.authentication.AuthenticationFailureAggregator; import org.eclipse.ditto.gateway.service.security.authentication.AuthenticationFailureAggregators; @@ -27,14 +28,13 @@ import org.eclipse.ditto.gateway.service.util.config.DittoGatewayConfig; import org.eclipse.ditto.gateway.service.util.config.security.AuthenticationConfig; import org.eclipse.ditto.internal.utils.config.DefaultScopedConfig; +import org.eclipse.ditto.internal.utils.config.ScopedConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mongodb.lang.Nullable; import com.typesafe.config.Config; -import org.apache.pekko.actor.ActorSystem; - /** * Ditto's default factory for building authentication directives. */ @@ -45,6 +45,7 @@ public final class DittoGatewayAuthenticationDirectiveFactory implements Gateway private final AuthenticationConfig authConfig; private final Executor authenticationDispatcher; + private final Config dittoExtensionConfig; @Nullable private GatewayAuthenticationDirective gatewayHttpAuthenticationDirective; @Nullable private GatewayAuthenticationDirective gatewayWsAuthenticationDirective; @@ -52,6 +53,7 @@ public DittoGatewayAuthenticationDirectiveFactory(final ActorSystem actorSystem, authConfig = DittoGatewayConfig.of(DefaultScopedConfig.dittoScoped(actorSystem.settings().config())) .getAuthenticationConfig(); authenticationDispatcher = actorSystem.dispatchers().lookup(AUTHENTICATION_DISPATCHER_NAME); + dittoExtensionConfig = ScopedConfig.dittoExtension(actorSystem.settings().config()); } @Override @@ -60,10 +62,12 @@ public GatewayAuthenticationDirective buildHttpAuthentication( if (null == gatewayHttpAuthenticationDirective) { final JwtAuthenticationProvider jwtHttpAuthenticationProvider = - JwtAuthenticationProvider.newInstance(jwtAuthenticationFactory.newJwtAuthenticationResultProvider( - "ditto.gateway.authentication.oauth" + JwtAuthenticationProvider.newInstance( + jwtAuthenticationFactory.newJwtAuthenticationResultProvider( + dittoExtensionConfig, null ), - jwtAuthenticationFactory.getJwtValidator()); + jwtAuthenticationFactory.getJwtValidator() + ); gatewayHttpAuthenticationDirective = generateGatewayAuthenticationDirective(authConfig, jwtHttpAuthenticationProvider, authenticationDispatcher); @@ -79,9 +83,10 @@ public GatewayAuthenticationDirective buildWsAuthentication( final JwtAuthenticationProvider jwtWsAuthenticationProvider = JwtAuthenticationProvider.newWsInstance( jwtAuthenticationFactory.newJwtAuthenticationResultProvider( - "ditto.gateway.authentication.oauth" + dittoExtensionConfig, null ), - jwtAuthenticationFactory.getJwtValidator()); + jwtAuthenticationFactory.getJwtValidator() + ); gatewayWsAuthenticationDirective = generateGatewayAuthenticationDirective(authConfig, jwtWsAuthenticationProvider, authenticationDispatcher); diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/RootRoute.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/RootRoute.java index 1422542081..d128148ee3 100755 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/RootRoute.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/RootRoute.java @@ -24,6 +24,18 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.NotThreadSafe; +import org.apache.pekko.http.javadsl.model.HttpHeader; +import org.apache.pekko.http.javadsl.model.HttpRequest; +import org.apache.pekko.http.javadsl.model.HttpResponse; +import org.apache.pekko.http.javadsl.server.AllDirectives; +import org.apache.pekko.http.javadsl.server.ExceptionHandler; +import org.apache.pekko.http.javadsl.server.PathMatchers; +import org.apache.pekko.http.javadsl.server.RejectionHandler; +import org.apache.pekko.http.javadsl.server.RequestContext; +import org.apache.pekko.http.javadsl.server.Route; +import org.apache.pekko.http.javadsl.server.directives.RouteAdapter; +import org.apache.pekko.http.scaladsl.server.RouteResult; +import org.apache.pekko.japi.pf.PFBuilder; import org.eclipse.ditto.base.model.exceptions.DittoRuntimeException; import org.eclipse.ditto.base.model.headers.DittoHeaderDefinition; import org.eclipse.ditto.base.model.headers.DittoHeaders; @@ -58,18 +70,6 @@ import org.eclipse.ditto.internal.utils.protocol.ProtocolAdapterProvider; import org.eclipse.ditto.protocol.adapter.ProtocolAdapter; -import org.apache.pekko.http.javadsl.model.HttpHeader; -import org.apache.pekko.http.javadsl.model.HttpRequest; -import org.apache.pekko.http.javadsl.model.HttpResponse; -import org.apache.pekko.http.javadsl.server.AllDirectives; -import org.apache.pekko.http.javadsl.server.ExceptionHandler; -import org.apache.pekko.http.javadsl.server.PathMatchers; -import org.apache.pekko.http.javadsl.server.RejectionHandler; -import org.apache.pekko.http.javadsl.server.RequestContext; -import org.apache.pekko.http.javadsl.server.Route; -import org.apache.pekko.http.javadsl.server.directives.RouteAdapter; -import org.apache.pekko.http.scaladsl.server.RouteResult; -import org.apache.pekko.japi.pf.PFBuilder; import scala.Function1; import scala.compat.java8.FutureConverters; import scala.concurrent.Future; @@ -170,8 +170,8 @@ private Route buildRoute() { api(ctx, correlationId, queryParameters), // /api ws(ctx, correlationId, queryParameters), // /ws ownStatusRoute.buildStatusRoute(), // /status - overallStatusRoute.buildOverallStatusRoute(), // /overall - devopsRoute.buildDevOpsRoute(ctx, queryParameters) // /devops + overallStatusRoute.buildOverallStatusRoute(correlationId), // /overall + devopsRoute.buildDevOpsRoute(ctx, correlationId, queryParameters) // /devops ) ) ) diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/connections/ConnectionsRoute.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/connections/ConnectionsRoute.java index 259f8b40a4..69dd3573eb 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/connections/ConnectionsRoute.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/connections/ConnectionsRoute.java @@ -23,6 +23,10 @@ import javax.annotation.Nullable; +import org.apache.pekko.http.javadsl.model.MediaTypes; +import org.apache.pekko.http.javadsl.server.PathMatchers; +import org.apache.pekko.http.javadsl.server.RequestContext; +import org.apache.pekko.http.javadsl.server.Route; import org.eclipse.ditto.base.model.headers.DittoHeaders; import org.eclipse.ditto.base.model.signals.commands.Command; import org.eclipse.ditto.connectivity.model.Connection; @@ -56,11 +60,6 @@ import org.eclipse.ditto.json.JsonObjectBuilder; import org.eclipse.ditto.json.JsonPointer; -import org.apache.pekko.http.javadsl.model.MediaTypes; -import org.apache.pekko.http.javadsl.server.PathMatchers; -import org.apache.pekko.http.javadsl.server.RequestContext; -import org.apache.pekko.http.javadsl.server.Route; - /** * Builder for creating Pekko HTTP routes for {@code /connections}. */ @@ -107,8 +106,8 @@ public ConnectionsRoute(final RouteBaseProperties routeBaseProperties, public Route buildConnectionsRoute(final RequestContext ctx, final DittoHeaders dittoHeaders) { return rawPathPrefix(PathMatchers.slash().concat(PATH_CONNECTIONS), () -> // /connections Optional.ofNullable(devOpsAuthenticationDirective) - .orElse((realm, route) -> route) - .authenticateDevOps(DevOpsOAuth2AuthenticationDirective.REALM_DEVOPS, + .orElse((realm, dh, route) -> route) + .authenticateDevOps(DevOpsOAuth2AuthenticationDirective.REALM_DEVOPS, dittoHeaders, concat( // /connections connections(ctx, dittoHeaders), diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/devops/DevOpsRoute.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/devops/DevOpsRoute.java index 9cad175905..29a9ad4643 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/devops/DevOpsRoute.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/devops/DevOpsRoute.java @@ -99,12 +99,14 @@ public DevOpsRoute(final RouteBaseProperties routeBaseProperties, * @return the {@code /devops} route. * @throws NullPointerException if any argument is {@code null}. */ - public Route buildDevOpsRoute(final RequestContext ctx, final Map queryParameters) { + public Route buildDevOpsRoute(final RequestContext ctx, final String correlationId, + final Map queryParameters) { checkNotNull(ctx, "ctx"); checkNotNull(queryParameters, "queryParameters"); return rawPathPrefix(PathMatchers.slash().concat(PATH_DEVOPS), () -> // /devops devOpsAuthenticationDirective.authenticateDevOps(DevOpsOAuth2AuthenticationDirective.REALM_DEVOPS, + DittoHeaders.newBuilder().correlationId(correlationId).build(), concat( rawPathPrefix(PathMatchers.slash().concat(PATH_LOGGING), () -> // /devops/logging diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/stats/StatsRoute.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/stats/StatsRoute.java index 14b87ccafc..fec1d1542a 100755 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/stats/StatsRoute.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/stats/StatsRoute.java @@ -15,21 +15,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -import org.eclipse.ditto.base.model.common.ConditionChecker; -import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevOpsOAuth2AuthenticationDirective; -import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevopsAuthenticationDirective; -import org.eclipse.ditto.gateway.service.endpoints.routes.RouteBaseProperties; -import org.eclipse.ditto.json.JsonObject; -import org.eclipse.ditto.base.model.common.HttpStatus; -import org.eclipse.ditto.base.model.headers.DittoHeaders; -import org.eclipse.ditto.base.model.json.JsonSchemaVersion; -import org.eclipse.ditto.gateway.service.endpoints.actors.AbstractHttpRequestActor; -import org.eclipse.ditto.gateway.service.endpoints.routes.AbstractRoute; -import org.eclipse.ditto.thingsearch.api.commands.sudo.SudoCountThings; -import org.eclipse.ditto.base.api.devops.signals.commands.DevOpsCommand; -import org.eclipse.ditto.base.api.devops.signals.commands.RetrieveStatistics; -import org.eclipse.ditto.base.api.devops.signals.commands.RetrieveStatisticsDetails; - import org.apache.pekko.http.javadsl.model.ContentTypes; import org.apache.pekko.http.javadsl.model.HttpResponse; import org.apache.pekko.http.javadsl.server.Directives; @@ -41,6 +26,20 @@ import org.apache.pekko.stream.javadsl.Sink; import org.apache.pekko.stream.javadsl.Source; import org.apache.pekko.util.ByteString; +import org.eclipse.ditto.base.api.devops.signals.commands.DevOpsCommand; +import org.eclipse.ditto.base.api.devops.signals.commands.RetrieveStatistics; +import org.eclipse.ditto.base.api.devops.signals.commands.RetrieveStatisticsDetails; +import org.eclipse.ditto.base.model.common.ConditionChecker; +import org.eclipse.ditto.base.model.common.HttpStatus; +import org.eclipse.ditto.base.model.headers.DittoHeaders; +import org.eclipse.ditto.base.model.json.JsonSchemaVersion; +import org.eclipse.ditto.gateway.service.endpoints.actors.AbstractHttpRequestActor; +import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevOpsOAuth2AuthenticationDirective; +import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevopsAuthenticationDirective; +import org.eclipse.ditto.gateway.service.endpoints.routes.AbstractRoute; +import org.eclipse.ditto.gateway.service.endpoints.routes.RouteBaseProperties; +import org.eclipse.ditto.json.JsonObject; +import org.eclipse.ditto.thingsearch.api.commands.sudo.SudoCountThings; /** * Builder for Pekko HTTP route for providing statistics. @@ -111,6 +110,7 @@ private Route buildSubRoutes(final RequestContext ctx, final CharSequence correl private Route buildDetailsRoute(final RequestContext ctx, final CharSequence correlationId) { return devOpsAuthenticationDirective.authenticateDevOps(DevOpsOAuth2AuthenticationDirective.REALM_DEVOPS, + DittoHeaders.newBuilder().correlationId(correlationId).build(), parameterList(ENTITY_PARAM, shardRegions -> parameterList(NAMESPACE_PARAM, namespaces -> handleDevOpsPerRequest(ctx, RetrieveStatisticsDetails.of(shardRegions, namespaces, diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/status/OverallStatusRoute.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/status/OverallStatusRoute.java index 3a0b5d473a..44502e6302 100755 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/status/OverallStatusRoute.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/endpoints/routes/status/OverallStatusRoute.java @@ -15,17 +15,17 @@ import java.util.concurrent.CompletionStage; import java.util.function.Supplier; -import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevOpsOAuth2AuthenticationDirective; -import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevopsAuthenticationDirective; -import org.eclipse.ditto.gateway.service.health.StatusAndHealthProvider; -import org.eclipse.ditto.internal.utils.health.cluster.ClusterStatus; - import org.apache.pekko.http.javadsl.model.ContentTypes; import org.apache.pekko.http.javadsl.model.HttpResponse; import org.apache.pekko.http.javadsl.model.StatusCodes; import org.apache.pekko.http.javadsl.server.PathMatchers; import org.apache.pekko.http.javadsl.server.Route; import org.apache.pekko.http.javadsl.server.directives.RouteDirectives; +import org.eclipse.ditto.base.model.headers.DittoHeaders; +import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevOpsOAuth2AuthenticationDirective; +import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevopsAuthenticationDirective; +import org.eclipse.ditto.gateway.service.health.StatusAndHealthProvider; +import org.eclipse.ditto.internal.utils.health.cluster.ClusterStatus; /** * Builder for creating Pekko HTTP routes for {@code /status}. @@ -66,26 +66,28 @@ public OverallStatusRoute(final Supplier clusterStateSupplier, * * @return the {@code /status} route. */ - public Route buildOverallStatusRoute() { - return rawPathPrefix(PathMatchers.slash().concat(PATH_OVERALL), () -> {// /overall/* - return devOpsAuthenticationDirective.authenticateDevOps(DevOpsOAuth2AuthenticationDirective.REALM_STATUS, get(() -> // GET - // /overall/status - // /overall/status/health - // /overall/status/cluster - rawPathPrefix(PathMatchers.slash().concat(PATH_STATUS), () -> concat( - // /status - pathEndOrSingleSlash(() -> completeWithFuture(createOverallStatusResponse())), - // /status/health - path(PATH_HEALTH, () -> completeWithFuture(createOverallHealthResponse())), - // /status/cluster - path(PATH_CLUSTER, () -> complete( - HttpResponse.create().withStatus(StatusCodes.OK) - .withEntity(ContentTypes.APPLICATION_JSON, - clusterStateSupplier.get().toJson().toString())) - ) + public Route buildOverallStatusRoute(final String correlationId) { + return rawPathPrefix(PathMatchers.slash().concat(PATH_OVERALL), () -> // /overall/* + devOpsAuthenticationDirective.authenticateDevOps(DevOpsOAuth2AuthenticationDirective.REALM_STATUS, + DittoHeaders.newBuilder().correlationId(correlationId).build(), + get(() -> // GET + // /overall/status + // /overall/status/health + // /overall/status/cluster + rawPathPrefix(PathMatchers.slash().concat(PATH_STATUS), () -> concat( + // /status + pathEndOrSingleSlash(() -> completeWithFuture(createOverallStatusResponse())), + // /status/health + path(PATH_HEALTH, () -> completeWithFuture(createOverallHealthResponse())), + // /status/cluster + path(PATH_CLUSTER, () -> complete( + HttpResponse.create().withStatus(StatusCodes.OK) + .withEntity(ContentTypes.APPLICATION_JSON, + clusterStateSupplier.get().toJson().toString())) + ) + )) )) - )); - }); + ); } private CompletionStage createOverallStatusResponse() { diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/DittoJwtAuthorizationSubjectsProvider.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/DittoJwtAuthorizationSubjectsProvider.java index 43d391d9f7..f6909bc18c 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/DittoJwtAuthorizationSubjectsProvider.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/DittoJwtAuthorizationSubjectsProvider.java @@ -20,6 +20,7 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +import org.apache.pekko.actor.ActorSystem; import org.eclipse.ditto.base.model.auth.AuthorizationSubject; import org.eclipse.ditto.gateway.api.GatewayJwtIssuerNotSupportedException; import org.eclipse.ditto.gateway.service.util.config.DittoGatewayConfig; @@ -33,30 +34,40 @@ import com.typesafe.config.Config; -import org.apache.pekko.actor.ActorSystem; - /** * Implementation of {@link JwtAuthorizationSubjectsProvider} for Google JWTs. */ @Immutable public final class DittoJwtAuthorizationSubjectsProvider implements JwtAuthorizationSubjectsProvider { + private static final String EXTENSION_CONFIG_KEY_ROLE = "role"; + private final JwtSubjectIssuersConfig jwtSubjectIssuersConfig; @SuppressWarnings("unused") //Loaded via reflection by PekkoExtension. public DittoJwtAuthorizationSubjectsProvider(final ActorSystem actorSystem, final Config extensionConfig) { - this(jwtSubjectIssuersConfig(actorSystem)); + this(jwtSubjectIssuersConfig(actorSystem, extensionConfig)); } private DittoJwtAuthorizationSubjectsProvider(final JwtSubjectIssuersConfig jwtSubjectIssuersConfig) { this.jwtSubjectIssuersConfig = checkNotNull(jwtSubjectIssuersConfig); } - private static JwtSubjectIssuersConfig jwtSubjectIssuersConfig(final ActorSystem actorSystem) { + private static JwtSubjectIssuersConfig jwtSubjectIssuersConfig(final ActorSystem actorSystem, + final Config extensionConfig) { final DefaultScopedConfig dittoScoped = DefaultScopedConfig.dittoScoped(actorSystem.settings().config()); - final OAuthConfig oAuthConfig = DittoGatewayConfig.of(dittoScoped) - .getAuthenticationConfig() - .getOAuthConfig(); + var role = extensionConfig.getString(EXTENSION_CONFIG_KEY_ROLE); + final OAuthConfig oAuthConfig; + if (role.equals("devops")) { + oAuthConfig = DittoGatewayConfig.of(dittoScoped) + .getAuthenticationConfig() + .getDevOpsConfig() + .getOAuthConfig(); + } else { + oAuthConfig = DittoGatewayConfig.of(dittoScoped) + .getAuthenticationConfig() + .getOAuthConfig(); + } return JwtSubjectIssuersConfig.fromOAuthConfig(oAuthConfig); } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationFactory.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationFactory.java index e992a82a0d..9f0916ac60 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationFactory.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationFactory.java @@ -16,12 +16,12 @@ import javax.annotation.Nullable; +import org.apache.pekko.actor.ActorSystem; import org.eclipse.ditto.gateway.service.util.config.security.OAuthConfig; import org.eclipse.ditto.internal.utils.cache.config.CacheConfig; -import org.eclipse.ditto.internal.utils.config.ScopedConfig; import org.eclipse.ditto.internal.utils.http.HttpClientFacade; -import org.apache.pekko.actor.ActorSystem; +import com.typesafe.config.Config; /** * A factory for {@link org.eclipse.ditto.jwt.model.JsonWebToken} related security. @@ -95,11 +95,10 @@ private JwtSubjectIssuersConfig getJwtSubjectIssuersConfig() { return jwtSubjectIssuersConfig; } - public JwtAuthenticationResultProvider newJwtAuthenticationResultProvider(final String configLevel) { - return JwtAuthenticationResultProvider.get( - actorSystem, - ScopedConfig.getOrEmpty(actorSystem.settings().config(), configLevel) - ); + public JwtAuthenticationResultProvider newJwtAuthenticationResultProvider(final Config extensionConfig, + @Nullable final String role) { + + return JwtAuthenticationResultProvider.get(actorSystem, extensionConfig, role); } } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationProvider.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationProvider.java index b393b77bc7..3de9d7acd5 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationProvider.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationProvider.java @@ -131,11 +131,12 @@ protected CompletableFuture tryToAuthenticate(final Reques private CompletionStage getAuthenticationResult(final JsonWebToken jwt, final DittoHeaders dittoHeaders) { + final ThreadSafeDittoLogger logger = LOGGER.withCorrelationId(dittoHeaders); return jwtValidator.validate(jwt) .thenCompose(validationResult -> { if (!validationResult.isValid()) { final Throwable reasonForInvalidity = validationResult.getReasonForInvalidity(); - LOGGER.withCorrelationId(dittoHeaders).debug("The JWT is invalid.", reasonForInvalidity); + logger.debug("The JWT is invalid.", reasonForInvalidity); final DittoRuntimeException reasonForFailure = buildJwtUnauthorizedException(dittoHeaders, reasonForInvalidity); return CompletableFuture.completedFuture( @@ -144,7 +145,7 @@ private CompletionStage getAuthenticationResult(final Json return tryToGetAuthenticationResult(jwt, dittoHeaders); }) .thenApply(authenticationResult -> { - LOGGER.withCorrelationId(dittoHeaders).info("Completed JWT authentication successfully."); + logger.info("Completed JWT authentication successfully."); return authenticationResult; }); } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationResultProvider.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationResultProvider.java index 65cd8c9f48..e993c8a3a8 100644 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationResultProvider.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/JwtAuthenticationResultProvider.java @@ -16,6 +16,9 @@ import java.util.concurrent.CompletionStage; +import javax.annotation.Nullable; + +import org.apache.pekko.actor.ActorSystem; import org.eclipse.ditto.base.model.headers.DittoHeaders; import org.eclipse.ditto.internal.utils.extension.DittoExtensionIds; import org.eclipse.ditto.internal.utils.extension.DittoExtensionPoint; @@ -23,8 +26,6 @@ import com.typesafe.config.Config; -import org.apache.pekko.actor.ActorSystem; - /** * Responsible for extraction of an {@link org.eclipse.ditto.gateway.service.security.authentication.AuthenticationResult} out of a * {@link JsonWebToken JSON web token}. @@ -46,17 +47,19 @@ CompletionStage getAuthenticationResult(JsonWebToken jw * Loads the implementation of {@code JwtAuthenticationResultProvider} which is configured for the {@code ActorSystem}. * * @param actorSystem the actorSystem in which the {@code JwtAuthenticationResultProvider} should be loaded. - * @param config the configuration for this extension. + * @param extensionConfig the configuration for this extension. + * @param suffix the optional suffix of the extension. * @return the {@code JwtAuthenticationResultProvider} implementation. * @throws NullPointerException if {@code actorSystem} is {@code null}. * @since 3.0.0 */ - static JwtAuthenticationResultProvider get(final ActorSystem actorSystem, final Config config) { + static JwtAuthenticationResultProvider get(final ActorSystem actorSystem, final Config extensionConfig, + @Nullable final String suffix) { checkNotNull(actorSystem, "actorSystem"); - checkNotNull(config, "config"); - final var extensionIdConfig = ExtensionId.computeConfig(config); + checkNotNull(extensionConfig, "config"); + final var extensionIdConfig = ExtensionId.computeConfig(extensionConfig, suffix); return DittoExtensionIds.get(actorSystem) - .computeIfAbsent(extensionIdConfig, ExtensionId::new) + .computeIfAbsent(extensionIdConfig, cfg -> new ExtensionId(suffix, cfg)) .get(actorSystem); } @@ -64,17 +67,30 @@ final class ExtensionId extends DittoExtensionPoint.ExtensionId extensionIdConfig) { + @Nullable private final String suffix; + + private ExtensionId(@Nullable final String suffix, + final ExtensionIdConfig extensionIdConfig) { super(extensionIdConfig); + this.suffix = suffix; } - static ExtensionIdConfig computeConfig(final Config config) { - return ExtensionIdConfig.of(JwtAuthenticationResultProvider.class,config, CONFIG_KEY); + static ExtensionIdConfig computeConfig(final Config config, + @Nullable final String suffix) { + return ExtensionIdConfig.of(JwtAuthenticationResultProvider.class, config, buildConfigKey(suffix)); } @Override protected String getConfigKey() { - return CONFIG_KEY; + return buildConfigKey(suffix); + } + + static String buildConfigKey(@Nullable final String suffix) { + if (suffix != null) { + return CONFIG_KEY + "-" + suffix; + } else { + return CONFIG_KEY; + } } } diff --git a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/starter/GatewayRootActor.java b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/starter/GatewayRootActor.java index 4a67a06503..232e35f7f2 100755 --- a/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/starter/GatewayRootActor.java +++ b/gateway/service/src/main/java/org/eclipse/ditto/gateway/service/starter/GatewayRootActor.java @@ -14,6 +14,17 @@ import java.util.concurrent.CompletionStage; +import org.apache.pekko.actor.ActorRef; +import org.apache.pekko.actor.ActorRefFactory; +import org.apache.pekko.actor.ActorSystem; +import org.apache.pekko.actor.Props; +import org.apache.pekko.cluster.Cluster; +import org.apache.pekko.event.DiagnosticLoggingAdapter; +import org.apache.pekko.http.javadsl.Http; +import org.apache.pekko.http.javadsl.ServerBinding; +import org.apache.pekko.http.javadsl.server.Route; +import org.apache.pekko.japi.pf.ReceiveBuilder; +import org.apache.pekko.stream.SystemMaterializer; import org.eclipse.ditto.base.model.headers.translator.HeaderTranslator; import org.eclipse.ditto.base.service.RootChildActorStarter; import org.eclipse.ditto.base.service.actors.DittoRootActor; @@ -52,7 +63,6 @@ import org.eclipse.ditto.gateway.service.util.config.security.AuthenticationConfig; import org.eclipse.ditto.gateway.service.util.config.security.DevOpsConfig; import org.eclipse.ditto.gateway.service.util.config.security.OAuthConfig; -import org.eclipse.ditto.internal.utils.pekko.logging.DittoLoggerFactory; import org.eclipse.ditto.internal.utils.cache.config.CacheConfig; import org.eclipse.ditto.internal.utils.cluster.ClusterStatusSupplier; import org.eclipse.ditto.internal.utils.cluster.DistPubSubAccess; @@ -63,23 +73,12 @@ import org.eclipse.ditto.internal.utils.health.routes.StatusRoute; import org.eclipse.ditto.internal.utils.http.DefaultHttpClientFacade; import org.eclipse.ditto.internal.utils.http.HttpClientFacade; +import org.eclipse.ditto.internal.utils.pekko.logging.DittoLoggerFactory; import org.eclipse.ditto.internal.utils.protocol.ProtocolAdapterProvider; import org.eclipse.ditto.internal.utils.pubsubthings.DittoProtocolSub; import com.typesafe.config.Config; -import org.apache.pekko.actor.ActorRef; -import org.apache.pekko.actor.ActorRefFactory; -import org.apache.pekko.actor.ActorSystem; -import org.apache.pekko.actor.Props; -import org.apache.pekko.cluster.Cluster; -import org.apache.pekko.event.DiagnosticLoggingAdapter; -import org.apache.pekko.http.javadsl.Http; -import org.apache.pekko.http.javadsl.ServerBinding; -import org.apache.pekko.http.javadsl.server.Route; -import org.apache.pekko.japi.pf.ReceiveBuilder; -import org.apache.pekko.stream.SystemMaterializer; - /** * The Root Actor of the API Gateway's Pekko ActorSystem. */ @@ -124,11 +123,12 @@ private GatewayRootActor(final GatewayConfig gatewayConfig, final ActorRef pubSu JwtAuthenticationFactory.newInstance(oAuthConfig, publicKeysConfig, httpClient, actorSystem); final JwtAuthenticationResultProvider jwtAuthenticationResultProvider = - jwtAuthenticationFactory.newJwtAuthenticationResultProvider("ditto.gateway.authentication.oauth"); + jwtAuthenticationFactory.newJwtAuthenticationResultProvider(dittoExtensionConfig, null); final DevOpsConfig devOpsConfig = authenticationConfig.getDevOpsConfig(); final DevopsAuthenticationDirectiveFactory devopsAuthenticationDirectiveFactory = - getDevopsAuthenticationDirectiveFactory(httpClient, publicKeysConfig, devOpsConfig, actorSystem); + getDevopsAuthenticationDirectiveFactory(httpClient, publicKeysConfig, devOpsConfig, actorSystem, + dittoExtensionConfig); final ProtocolAdapterProvider protocolAdapterProvider = ProtocolAdapterProvider.load(gatewayConfig.getProtocolConfig(), actorSystem); @@ -303,12 +303,14 @@ private static DevopsAuthenticationDirectiveFactory getDevopsAuthenticationDirec final HttpClientFacade httpClient, final CacheConfig publicKeysConfig, final DevOpsConfig devOpsConfig, - final ActorSystem actorSystem) { + final ActorSystem actorSystem, + final Config dittoExtensionConfig) { final var devopsOauthConfig = devOpsConfig.getOAuthConfig(); final var devopsJwtAuthenticationFactory = JwtAuthenticationFactory.newInstance(devopsOauthConfig, publicKeysConfig, httpClient, actorSystem); - return DevopsAuthenticationDirectiveFactory.newInstance(devopsJwtAuthenticationFactory, devOpsConfig); + return DevopsAuthenticationDirectiveFactory.newInstance(devopsJwtAuthenticationFactory, devOpsConfig, + dittoExtensionConfig); } private String getHostname(final HttpConfig httpConfig) { diff --git a/gateway/service/src/main/resources/gateway.conf b/gateway/service/src/main/resources/gateway.conf index c50e7d3669..534454aeef 100755 --- a/gateway/service/src/main/resources/gateway.conf +++ b/gateway/service/src/main/resources/gateway.conf @@ -8,8 +8,26 @@ ditto { extension-class = org.eclipse.ditto.gateway.service.security.authentication.jwt.DefaultJwtAuthenticationResultProvider # The provider for JSON Web Token authorization subjects extension-config = { + role = regular jwt-authorization-subjects-provider = { extension-class = org.eclipse.ditto.gateway.service.security.authentication.jwt.DittoJwtAuthorizationSubjectsProvider + extension-config = { + role = regular + } + } + } + } + # The provider for JSON Web Token authentication results for "devops" and "connections" routes + jwt-authentication-result-provider-devops = { + extension-class = org.eclipse.ditto.gateway.service.security.authentication.jwt.DefaultJwtAuthenticationResultProvider + # The provider for JSON Web Token authorization subjects + extension-config = { + role = devops + jwt-authorization-subjects-provider = { + extension-class = org.eclipse.ditto.gateway.service.security.authentication.jwt.DittoJwtAuthorizationSubjectsProvider + extension-config = { + role = devops + } } } } diff --git a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/EndpointTestBase.java b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/EndpointTestBase.java index 3a73685577..10a5aee5cf 100755 --- a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/EndpointTestBase.java +++ b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/EndpointTestBase.java @@ -72,6 +72,7 @@ import org.eclipse.ditto.internal.utils.cache.config.CacheConfig; import org.eclipse.ditto.internal.utils.cache.config.DefaultCacheConfig; import org.eclipse.ditto.internal.utils.config.DefaultScopedConfig; +import org.eclipse.ditto.internal.utils.config.ScopedConfig; import org.eclipse.ditto.internal.utils.health.StatusInfo; import org.eclipse.ditto.internal.utils.health.cluster.ClusterStatus; import org.eclipse.ditto.internal.utils.http.DefaultHttpClientFacade; @@ -127,9 +128,10 @@ public abstract class EndpointTestBase extends JUnitRouteTest { @BeforeClass public static void initTestFixture() { - final var dittoScopedConfig = DefaultScopedConfig.dittoScoped(createTestConfig()); + final Config testConfig = createTestConfig(); + final var dittoScopedConfig = DefaultScopedConfig.dittoScoped(testConfig); final var gatewayScopedConfig = DefaultScopedConfig.newInstance(dittoScopedConfig, "gateway"); - final var actorSystem = ActorSystem.create(EndpointTestBase.class.getSimpleName(), createTestConfig()); + final var actorSystem = ActorSystem.create(EndpointTestBase.class.getSimpleName(), testConfig); httpConfig = GatewayHttpConfig.of(gatewayScopedConfig); healthCheckConfig = DefaultHealthCheckConfig.of(gatewayScopedConfig); commandConfig = DefaultCommandConfig.of(gatewayScopedConfig); @@ -144,7 +146,8 @@ public static void initTestFixture() { httpClientFacade = DefaultHttpClientFacade.getInstance(actorSystem, DefaultHttpProxyConfig.ofProxy(DefaultScopedConfig.empty("/"))); - authorizationSubjectsProvider = JwtAuthorizationSubjectsProvider.get(actorSystem, ConfigFactory.empty()); + authorizationSubjectsProvider = JwtAuthorizationSubjectsProvider.get(actorSystem, + ScopedConfig.dittoExtension(testConfig)); jwtAuthenticationFactory = JwtAuthenticationFactory.newInstance(authConfig.getOAuthConfig(), cacheConfig, httpClientFacade, diff --git a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/RootRouteTest.java b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/RootRouteTest.java index 0ad0544dd6..63f09133ef 100755 --- a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/RootRouteTest.java +++ b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/RootRouteTest.java @@ -24,6 +24,14 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import org.apache.pekko.actor.ActorSystem; +import org.apache.pekko.http.javadsl.model.HttpRequest; +import org.apache.pekko.http.javadsl.model.StatusCodes; +import org.apache.pekko.http.javadsl.model.headers.Location; +import org.apache.pekko.http.javadsl.model.headers.RawHeader; +import org.apache.pekko.http.javadsl.testkit.TestRoute; +import org.apache.pekko.http.javadsl.testkit.TestRouteResult; +import org.apache.pekko.stream.SystemMaterializer; import org.eclipse.ditto.base.model.headers.DittoHeaderDefinition; import org.eclipse.ditto.base.model.headers.DittoHeaders; import org.eclipse.ditto.base.model.json.JsonSchemaVersion; @@ -70,15 +78,6 @@ import com.typesafe.config.ConfigFactory; -import org.apache.pekko.actor.ActorSystem; -import org.apache.pekko.http.javadsl.model.HttpRequest; -import org.apache.pekko.http.javadsl.model.StatusCodes; -import org.apache.pekko.http.javadsl.model.headers.Location; -import org.apache.pekko.http.javadsl.model.headers.RawHeader; -import org.apache.pekko.http.javadsl.testkit.TestRoute; -import org.apache.pekko.http.javadsl.testkit.TestRouteResult; -import org.apache.pekko.stream.SystemMaterializer; - /** * Tests {@link RootRoute}. */ @@ -137,12 +136,12 @@ public void setUp() { final var statusAndHealthProvider = DittoStatusAndHealthProviderFactory.of(routeBaseProperties.getActorSystem(), clusterStatusSupplier, healthCheckConfig); + final var dittoExtensionConfig = + ScopedConfig.dittoExtension(routeBaseProperties.getActorSystem().settings().config()); final var devopsAuthenticationDirectiveFactory = DevopsAuthenticationDirectiveFactory.newInstance(jwtAuthenticationFactory, - authConfig.getDevOpsConfig()); + authConfig.getDevOpsConfig(), dittoExtensionConfig); final var devOpsAuthenticationDirective = devopsAuthenticationDirectiveFactory.devops(); - final var dittoExtensionConfig = - ScopedConfig.dittoExtension(routeBaseProperties.getActorSystem().settings().config()); final var rootRoute = RootRoute.getBuilder(httpConfig) .statsRoute(new StatsRoute(routeBaseProperties, devOpsAuthenticationDirective)) .statusRoute(new StatusRoute(clusterStatusSupplier, diff --git a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/connections/ConnectionsRouteTest.java b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/connections/ConnectionsRouteTest.java index f979180958..b7f5621c74 100644 --- a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/connections/ConnectionsRouteTest.java +++ b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/connections/ConnectionsRouteTest.java @@ -20,6 +20,14 @@ import java.util.Optional; import java.util.function.Function; +import org.apache.pekko.http.javadsl.model.ContentTypes; +import org.apache.pekko.http.javadsl.model.HttpRequest; +import org.apache.pekko.http.javadsl.model.StatusCodes; +import org.apache.pekko.http.javadsl.server.Directives; +import org.apache.pekko.http.javadsl.server.ExceptionHandler; +import org.apache.pekko.http.javadsl.server.RejectionHandler; +import org.apache.pekko.http.javadsl.server.Route; +import org.apache.pekko.http.javadsl.testkit.TestRoute; import org.eclipse.ditto.base.model.auth.AuthorizationContext; import org.eclipse.ditto.base.model.auth.AuthorizationSubject; import org.eclipse.ditto.base.model.auth.DittoAuthorizationContextType; @@ -41,15 +49,6 @@ import org.junit.Test; import org.mockito.Mockito; -import org.apache.pekko.http.javadsl.model.ContentTypes; -import org.apache.pekko.http.javadsl.model.HttpRequest; -import org.apache.pekko.http.javadsl.model.StatusCodes; -import org.apache.pekko.http.javadsl.server.Directives; -import org.apache.pekko.http.javadsl.server.ExceptionHandler; -import org.apache.pekko.http.javadsl.server.RejectionHandler; -import org.apache.pekko.http.javadsl.server.Route; -import org.apache.pekko.http.javadsl.testkit.TestRoute; - public final class ConnectionsRouteTest extends EndpointTestBase { private static final JsonValue DEFAULT_DUMMY_ENTITY_JSON = JsonValue.of("dummy"); @@ -96,8 +95,8 @@ public final class ConnectionsRouteTest extends EndpointTestBase { public void setUp() { final DevopsAuthenticationDirective devopsAuthenticationDirective = Mockito.mock( DevopsAuthenticationDirective.class); - Mockito.when(devopsAuthenticationDirective.authenticateDevOps(Mockito.any(), Mockito.any())) - .thenAnswer(a -> a.getArguments()[1]); + Mockito.when(devopsAuthenticationDirective.authenticateDevOps(Mockito.any(), Mockito.any(), Mockito.any())) + .thenAnswer(a -> a.getArguments()[2]); final var connectionsRoute = new ConnectionsRoute(routeBaseProperties, devopsAuthenticationDirective); final Route route = extractRequestContext(ctx -> connectionsRoute.buildConnectionsRoute(ctx, dittoHeaders)); diff --git a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/devops/DevOpsRouteTest.java b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/devops/DevOpsRouteTest.java index 0f3df31162..a70e43484a 100644 --- a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/devops/DevOpsRouteTest.java +++ b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/devops/DevOpsRouteTest.java @@ -14,13 +14,22 @@ package org.eclipse.ditto.gateway.service.endpoints.routes.devops; import java.util.Collections; +import java.util.UUID; +import org.apache.pekko.http.javadsl.model.ContentTypes; +import org.apache.pekko.http.javadsl.model.HttpEntities; +import org.apache.pekko.http.javadsl.model.HttpRequest; +import org.apache.pekko.http.javadsl.model.RequestEntity; +import org.apache.pekko.http.javadsl.model.StatusCodes; +import org.apache.pekko.http.javadsl.server.Route; +import org.apache.pekko.http.javadsl.testkit.TestRoute; import org.eclipse.ditto.base.api.devops.signals.commands.ExecutePiggybackCommand; import org.eclipse.ditto.base.model.headers.DittoHeaders; import org.eclipse.ditto.gateway.service.endpoints.EndpointTestBase; import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevopsAuthenticationDirectiveFactory; import org.eclipse.ditto.gateway.service.util.config.security.DefaultDevOpsConfig; import org.eclipse.ditto.gateway.service.util.config.security.DevOpsConfig; +import org.eclipse.ditto.internal.utils.config.ScopedConfig; import org.eclipse.ditto.things.model.ThingId; import org.eclipse.ditto.things.model.signals.commands.query.RetrieveThing; import org.junit.Before; @@ -28,14 +37,6 @@ import com.typesafe.config.ConfigFactory; -import org.apache.pekko.http.javadsl.model.ContentTypes; -import org.apache.pekko.http.javadsl.model.HttpEntities; -import org.apache.pekko.http.javadsl.model.HttpRequest; -import org.apache.pekko.http.javadsl.model.RequestEntity; -import org.apache.pekko.http.javadsl.model.StatusCodes; -import org.apache.pekko.http.javadsl.server.Route; -import org.apache.pekko.http.javadsl.testkit.TestRoute; - /** * Unit test for {@link DevOpsRoute}. */ @@ -47,11 +48,14 @@ public final class DevOpsRouteTest extends EndpointTestBase { @Before public void setUp() { + final var dittoExtensionConfig = + ScopedConfig.dittoExtension(routeBaseProperties.getActorSystem().settings().config()); final var devopsAuthenticationDirectiveFactory = - DevopsAuthenticationDirectiveFactory.newInstance(jwtAuthenticationFactory, getInsecureDevopsConfig()); + DevopsAuthenticationDirectiveFactory.newInstance(jwtAuthenticationFactory, getInsecureDevopsConfig(), + dittoExtensionConfig); final var authenticationDirective = devopsAuthenticationDirectiveFactory.devops(); devOpsRoute = new DevOpsRoute(routeBaseProperties, authenticationDirective); - final Route route = extractRequestContext(ctx -> devOpsRoute.buildDevOpsRoute(ctx, Collections.emptyMap())); + final Route route = extractRequestContext(ctx -> devOpsRoute.buildDevOpsRoute(ctx, UUID.randomUUID().toString(), Collections.emptyMap())); underTest = testRoute(route); } diff --git a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/stats/StatsRouteTest.java b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/stats/StatsRouteTest.java index a95a7ac762..aa97e7b7d1 100755 --- a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/stats/StatsRouteTest.java +++ b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/stats/StatsRouteTest.java @@ -18,6 +18,11 @@ import java.util.Optional; import java.util.UUID; +import org.apache.pekko.actor.ActorRef; +import org.apache.pekko.actor.ActorSystem; +import org.apache.pekko.http.javadsl.model.HttpRequest; +import org.apache.pekko.http.javadsl.model.StatusCodes; +import org.apache.pekko.http.javadsl.testkit.TestRoute; import org.eclipse.ditto.base.model.headers.DittoHeaders; import org.eclipse.ditto.gateway.service.endpoints.EndpointTestBase; import org.eclipse.ditto.gateway.service.endpoints.EndpointTestConstants; @@ -33,12 +38,6 @@ import com.typesafe.config.ConfigFactory; -import org.apache.pekko.actor.ActorRef; -import org.apache.pekko.actor.ActorSystem; -import org.apache.pekko.http.javadsl.model.HttpRequest; -import org.apache.pekko.http.javadsl.model.StatusCodes; -import org.apache.pekko.http.javadsl.testkit.TestRoute; - /** * Tests {@link StatsRoute}. */ @@ -62,8 +61,10 @@ private void setUp(final ActorRef proxyActor) { final var devopsJwtAuthenticationFactory = JwtAuthenticationFactory.newInstance(devOpsConfig.getOAuthConfig(), cacheConfig, httpClientFacade, actorSystem); + final var dittoExtensionConfig = + ScopedConfig.dittoExtension(actorSystem.settings().config()); final var jwtAuthenticationProvider = JwtAuthenticationProvider.newInstance( - devopsJwtAuthenticationFactory.newJwtAuthenticationResultProvider(ScopedConfig.DITTO_EXTENSIONS_SCOPE), + devopsJwtAuthenticationFactory.newJwtAuthenticationResultProvider(dittoExtensionConfig, null), devopsJwtAuthenticationFactory.getJwtValidator()); final var routeBaseProperties = RouteBaseProperties.newBuilder(this.routeBaseProperties) .proxyActor(proxyActor) diff --git a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/status/OverallStatusRouteTest.java b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/status/OverallStatusRouteTest.java index 7e9997eff8..89ff348af2 100755 --- a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/status/OverallStatusRouteTest.java +++ b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/endpoints/routes/status/OverallStatusRouteTest.java @@ -17,22 +17,22 @@ import java.util.function.Supplier; -import org.eclipse.ditto.gateway.service.health.DittoStatusAndHealthProviderFactory; -import org.eclipse.ditto.gateway.service.health.StatusAndHealthProvider; -import org.eclipse.ditto.gateway.service.util.config.security.DevOpsConfig; +import org.apache.pekko.http.javadsl.model.HttpRequest; +import org.apache.pekko.http.javadsl.model.StatusCodes; +import org.apache.pekko.http.javadsl.testkit.TestRoute; +import org.apache.pekko.http.javadsl.testkit.TestRouteResult; import org.eclipse.ditto.gateway.service.endpoints.EndpointTestBase; import org.eclipse.ditto.gateway.service.endpoints.EndpointTestConstants; import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevopsAuthenticationDirective; import org.eclipse.ditto.gateway.service.endpoints.directives.auth.DevopsAuthenticationDirectiveFactory; +import org.eclipse.ditto.gateway.service.health.DittoStatusAndHealthProviderFactory; +import org.eclipse.ditto.gateway.service.health.StatusAndHealthProvider; +import org.eclipse.ditto.gateway.service.util.config.security.DevOpsConfig; +import org.eclipse.ditto.internal.utils.config.ScopedConfig; import org.eclipse.ditto.internal.utils.health.cluster.ClusterStatus; import org.junit.Before; import org.junit.Test; -import org.apache.pekko.http.javadsl.model.HttpRequest; -import org.apache.pekko.http.javadsl.model.StatusCodes; -import org.apache.pekko.http.javadsl.testkit.TestRoute; -import org.apache.pekko.http.javadsl.testkit.TestRouteResult; - /** * Tests {@link OverallStatusRoute}. */ @@ -50,16 +50,19 @@ public final class OverallStatusRouteTest extends EndpointTestBase { @Before public void setUp() { + final var dittoExtensionConfig = + ScopedConfig.dittoExtension(routeBaseProperties.getActorSystem().settings().config()); final Supplier clusterStateSupplier = createClusterStatusSupplierMock(); final StatusAndHealthProvider statusHealthProvider = DittoStatusAndHealthProviderFactory.of(system(), clusterStateSupplier, healthCheckConfig); final DevOpsConfig devOpsConfig = authConfig.getDevOpsConfig(); final DevopsAuthenticationDirectiveFactory devopsAuthenticationDirectiveFactory = - DevopsAuthenticationDirectiveFactory.newInstance(jwtAuthenticationFactory, devOpsConfig); + DevopsAuthenticationDirectiveFactory.newInstance(jwtAuthenticationFactory, devOpsConfig, + dittoExtensionConfig); final DevopsAuthenticationDirective authenticationDirective = devopsAuthenticationDirectiveFactory.status(); final OverallStatusRoute statusRoute = new OverallStatusRoute(clusterStateSupplier, statusHealthProvider, authenticationDirective); - statusTestRoute = testRoute(statusRoute.buildOverallStatusRoute()); + statusTestRoute = testRoute(statusRoute.buildOverallStatusRoute("correlationId")); } @Test diff --git a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/DefaultJwtAuthenticationResultProviderTest.java b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/DefaultJwtAuthenticationResultProviderTest.java index 19e3df3d37..4220caf1d6 100644 --- a/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/DefaultJwtAuthenticationResultProviderTest.java +++ b/gateway/service/src/test/java/org/eclipse/ditto/gateway/service/security/authentication/jwt/DefaultJwtAuthenticationResultProviderTest.java @@ -19,20 +19,19 @@ import java.util.UUID; +import org.apache.pekko.actor.ActorSystem; import org.eclipse.ditto.base.model.auth.AuthorizationSubject; import org.eclipse.ditto.base.model.headers.DittoHeaders; import org.eclipse.ditto.gateway.service.security.authentication.AuthenticationResult; +import org.eclipse.ditto.internal.utils.config.ScopedConfig; import org.eclipse.ditto.jwt.model.ImmutableJsonWebToken; import org.eclipse.ditto.jwt.model.JsonWebToken; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; -import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; -import org.apache.pekko.actor.ActorSystem; - /** * Unit test for {@link DefaultJwtAuthenticationResultProvider}. */ @@ -51,8 +50,10 @@ public void assertImmutability() { @Test public void getAuthorizationContext() { + final var dittoExtensionConfig = + ScopedConfig.dittoExtension(ACTOR_SYSTEM.settings().config()); final JwtAuthenticationResultProvider underTest = - JwtAuthenticationResultProvider.get(ACTOR_SYSTEM, ConfigFactory.empty()); + JwtAuthenticationResultProvider.get(ACTOR_SYSTEM, dittoExtensionConfig, null); final JsonWebToken jsonWebToken = ImmutableJsonWebToken.fromToken(JwtTestConstants.VALID_JWT_TOKEN); final AuthorizationSubject myTestSubj = AuthorizationSubject.newInstance("example:myTestSubj"); diff --git a/gateway/service/src/test/resources/test.conf b/gateway/service/src/test/resources/test.conf index 0cca17deb0..e659d1ae95 100755 --- a/gateway/service/src/test/resources/test.conf +++ b/gateway/service/src/test/resources/test.conf @@ -133,14 +133,34 @@ ditto { extensions { jwt-authorization-subjects-provider = { extension-class = org.eclipse.ditto.gateway.service.security.authentication.jwt.DittoJwtAuthorizationSubjectsProvider + extension-config = { + role = regular + } } # The provider for JSON Web Token authentication results jwt-authentication-result-provider = { extension-class = org.eclipse.ditto.gateway.service.security.authentication.jwt.DefaultJwtAuthenticationResultProvider # The provider for JSON Web Token authorization subjects extension-config = { + role = regular + jwt-authorization-subjects-provider = { + extension-class = org.eclipse.ditto.gateway.service.security.authentication.jwt.DittoJwtAuthorizationSubjectsProvider + extension-config = { + role = regular + } + } + } + } + jwt-authentication-result-provider-devops = { + extension-class = org.eclipse.ditto.gateway.service.security.authentication.jwt.DefaultJwtAuthenticationResultProvider + # The provider for JSON Web Token authorization subjects + extension-config = { + role = devops jwt-authorization-subjects-provider = { extension-class = org.eclipse.ditto.gateway.service.security.authentication.jwt.DittoJwtAuthorizationSubjectsProvider + extension-config = { + role = devops + } } } }