diff --git a/model/jwt/src/main/java/org/eclipse/ditto/model/jwt/Audience.java b/model/jwt/src/main/java/org/eclipse/ditto/model/jwt/Audience.java index 4f111e7ef1..0961c9b3ea 100644 --- a/model/jwt/src/main/java/org/eclipse/ditto/model/jwt/Audience.java +++ b/model/jwt/src/main/java/org/eclipse/ditto/model/jwt/Audience.java @@ -69,7 +69,7 @@ static Audience fromJson(final JsonValue audValue) { * * @return the empty audience. */ - static Audience empty() { + public static Audience empty() { return new Audience(Collections.emptyList()); } diff --git a/model/placeholders/src/main/java/org/eclipse/ditto/model/placeholders/ExpressionResolver.java b/model/placeholders/src/main/java/org/eclipse/ditto/model/placeholders/ExpressionResolver.java index 34e4f23b8c..9acf9eb8bc 100644 --- a/model/placeholders/src/main/java/org/eclipse/ditto/model/placeholders/ExpressionResolver.java +++ b/model/placeholders/src/main/java/org/eclipse/ditto/model/placeholders/ExpressionResolver.java @@ -70,7 +70,7 @@ default PipelineElement resolve(final String expressionTemplate) { * @throws PlaceholderFunctionTooComplexException thrown if the {@code expressionTemplate} contains a placeholder * function chain which is too complex (e.g. too much chained function calls) */ - default PipelineElement resolvePartially(final String expressionTemplate) { + default String resolvePartially(final String expressionTemplate) { return ExpressionResolver.substitute(expressionTemplate, expression -> { try { return resolveAsPipelineElement(expression).onUnresolved(() -> PipelineElement.resolved(expression)); @@ -78,7 +78,7 @@ default PipelineElement resolvePartially(final String expressionTemplate) { // placeholder is not supported; return the expression without resolution. return PipelineElement.resolved("{{" + expression + "}}"); } - }); + }).toOptional().orElseThrow(() -> new IllegalStateException("Impossible")); } /** diff --git a/model/placeholders/src/test/java/org/eclipse/ditto/model/placeholders/ExpressionResolverTest.java b/model/placeholders/src/test/java/org/eclipse/ditto/model/placeholders/ExpressionResolverTest.java index 02dc9aba8a..85a28d2313 100644 --- a/model/placeholders/src/test/java/org/eclipse/ditto/model/placeholders/ExpressionResolverTest.java +++ b/model/placeholders/src/test/java/org/eclipse/ditto/model/placeholders/ExpressionResolverTest.java @@ -125,7 +125,7 @@ public void testDeleteIfUnresolved() { @Test public void testPartialResolution() { assertThat(expressionResolver.resolvePartially("{{header:header-name}}-{{unknown:placeholder|fn:unknown}}")) - .containsExactly("header-val-{{unknown:placeholder|fn:unknown}}"); + .isEqualTo("header-val-{{unknown:placeholder|fn:unknown}}"); } } diff --git a/model/policies/src/main/java/org/eclipse/ditto/model/policies/PolicyActionFailedException.java b/model/policies/src/main/java/org/eclipse/ditto/model/policies/PolicyActionFailedException.java index 21c2611d35..2f68d336a3 100755 --- a/model/policies/src/main/java/org/eclipse/ditto/model/policies/PolicyActionFailedException.java +++ b/model/policies/src/main/java/org/eclipse/ditto/model/policies/PolicyActionFailedException.java @@ -39,11 +39,17 @@ public final class PolicyActionFailedException extends DittoRuntimeException imp */ public static final String ERROR_CODE = ERROR_CODE_PREFIX + "action.failed"; - private static final HttpStatusCode DEFAULT_STATUS = HttpStatusCode.INTERNAL_SERVER_ERROR; + /** + * The action {@code activateTokenIntegration}. + */ + public static final String ACTIVATE_TOKEN_INTEGRATION = "activateTokenIntegration"; - private static final String ACTIVATE_TOKEN_INTEGRATION = "activateTokenIntegration"; + /** + * The action {@code deactivateTokenIntegration}. + */ + public static final String DEACTIVATE_TOKEN_INTEGRATION = "deactivateTokenIntegration"; - private static final String DEACTIVATE_TOKEN_INTEGRATION = "deactivateTokenIntegration"; + private static final HttpStatusCode DEFAULT_STATUS = HttpStatusCode.INTERNAL_SERVER_ERROR; private static final String MESSAGE_TEMPLATE = "Failed to execute action ''{0}''."; @@ -76,6 +82,19 @@ public static DittoRuntimeExceptionBuilder newBuild return new Builder().action(DEACTIVATE_TOKEN_INTEGRATION); } + /** + * A mutable builder for a {@code PolicyActionFailedException} due to inappropriate authentication method. + * + * @param action the failed action. + * @return the exception builder. + */ + public static DittoRuntimeExceptionBuilder + newBuilderForInappropriateAuthenticationMethod(final String action) { + return new Builder().action(action) + .status(HttpStatusCode.BAD_REQUEST) + .description("Policy action is only possible with JWT authentication."); + } + /** * A mutable builder for when a deactivation failed due to matching permanent subjects. * diff --git a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/directives/auth/GatewayAuthenticationDirective.java b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/directives/auth/GatewayAuthenticationDirective.java index ee4e1a282c..ee4e4ae631 100755 --- a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/directives/auth/GatewayAuthenticationDirective.java +++ b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/directives/auth/GatewayAuthenticationDirective.java @@ -74,10 +74,10 @@ public GatewayAuthenticationDirective(final AuthenticationChain authenticationCh * Depending on the request headers, one of the supported authentication mechanisms is applied. * * @param dittoHeaders the DittoHeaders containing already gathered context information. - * @param inner the inner route which will be wrapped with the {@link DittoHeaders}. + * @param inner the inner route which will be wrapped with the {@link org.eclipse.ditto.model.base.headers.DittoHeaders}. * @return the inner route. */ - public Route authenticate(final DittoHeaders dittoHeaders, final Function, Route> inner) { + public Route authenticate(final DittoHeaders dittoHeaders, final Function inner) { return extractRequestContext(requestContext -> { final Uri requestUri = requestContext.getRequest().getUri(); @@ -95,12 +95,12 @@ public Route authenticate(final DittoHeaders dittoHeaders, final Function authenticationResultTry, final Uri requestUri, final DittoHeaders dittoHeaders, - final Function, Route> inner) { + final Function inner) { if (authenticationResultTry.isSuccess()) { final AuthenticationResult authenticationResult = authenticationResultTry.get(); if (authenticationResult.isSuccess()) { - return inner.apply(authenticationResult.getDittoHeaders().toBuilder()); + return inner.apply(authenticationResult); } return handleFailedAuthentication(authenticationResult.getReasonOfFailure(), requestUri, dittoHeaders); } diff --git a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/RootRoute.java b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/RootRoute.java index 39c188c9f2..662592d2df 100755 --- a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/RootRoute.java +++ b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/RootRoute.java @@ -27,7 +27,6 @@ import org.eclipse.ditto.model.base.exceptions.DittoRuntimeException; import org.eclipse.ditto.model.base.headers.DittoHeaders; -import org.eclipse.ditto.model.base.headers.DittoHeadersBuilder; import org.eclipse.ditto.model.base.headers.DittoHeadersSizeChecker; import org.eclipse.ditto.model.base.json.JsonSchemaVersion; import org.eclipse.ditto.protocoladapter.HeaderTranslator; @@ -50,6 +49,7 @@ import org.eclipse.ditto.services.gateway.endpoints.routes.websocket.WebSocketRouteBuilder; import org.eclipse.ditto.services.gateway.endpoints.routes.whoami.WhoamiRoute; import org.eclipse.ditto.services.gateway.endpoints.utils.DittoRejectionHandlerFactory; +import org.eclipse.ditto.services.gateway.security.authentication.AuthenticationResult; import org.eclipse.ditto.services.gateway.util.config.endpoints.HttpConfig; import org.eclipse.ditto.services.utils.health.routes.StatusRoute; import org.eclipse.ditto.services.utils.protocol.ProtocolAdapterProvider; @@ -219,16 +219,17 @@ private Route api(final RequestContext ctx, final CharSequence correlationId, return rawPathPrefix(PathMatchers.slash().concat(HTTP_PATH_API_PREFIX), () -> // /api ensureSchemaVersion(apiVersion -> // /api/ customApiRoutesProvider.unauthorized(apiVersion, correlationId).orElse( - apiAuthentication(apiVersion, correlationId, initialHeadersBuilder -> { + apiAuthentication(apiVersion, correlationId, auth -> { final CompletionStage dittoHeadersPromise = rootRouteHeadersStepBuilder - .withInitialDittoHeadersBuilder(initialHeadersBuilder) + .withInitialDittoHeadersBuilder( + auth.getDittoHeaders().toBuilder()) .withRequestContext(ctx) .withQueryParameters(queryParameters) .build(CustomHeadersHandler.RequestType.API); return withDittoHeaders(dittoHeadersPromise, - dittoHeaders -> buildApiSubRoutes(ctx, dittoHeaders)); + dittoHeaders -> buildApiSubRoutes(ctx, dittoHeaders, auth)); } ) ) @@ -255,7 +256,7 @@ private Route ensureSchemaVersion(final Function inner } private Route apiAuthentication(final JsonSchemaVersion schemaVersion, final CharSequence correlationId, - final Function, Route> inner) { + final Function inner) { final DittoHeaders dittoHeaders = DittoHeaders.newBuilder() .schemaVersion(schemaVersion) @@ -264,13 +265,14 @@ private Route apiAuthentication(final JsonSchemaVersion schemaVersion, final Cha return apiAuthenticationDirective.authenticate(dittoHeaders, inner); } - private Route buildApiSubRoutes(final RequestContext ctx, final DittoHeaders dittoHeaders) { + private Route buildApiSubRoutes(final RequestContext ctx, final DittoHeaders dittoHeaders, + final AuthenticationResult authenticationResult) { final Route customApiSubRoutes = customApiRoutesProvider.authorized(dittoHeaders); return concat( // /api/{apiVersion}/policies - policiesRoute.buildPoliciesRoute(ctx, dittoHeaders), + policiesRoute.buildPoliciesRoute(ctx, dittoHeaders, authenticationResult), // /api/{apiVersion}/things SSE support buildSseThingsRoute(ctx, dittoHeaders), // /api/{apiVersion}/things @@ -309,10 +311,10 @@ private Route ws(final RequestContext ctx, final CharSequence correlationId, final Map queryParameters) { return rawPathPrefix(PathMatchers.slash().concat(WS_PATH_PREFIX), () -> // /ws ensureSchemaVersion(wsVersion -> // /ws/ - wsAuthentication(wsVersion, correlationId, initialHeadersBuilder -> { + wsAuthentication(wsVersion, correlationId, auth -> { final CompletionStage dittoHeadersPromise = rootRouteHeadersStepBuilder - .withInitialDittoHeadersBuilder(initialHeadersBuilder) + .withInitialDittoHeadersBuilder(auth.getDittoHeaders().toBuilder()) .withRequestContext(ctx) .withQueryParameters(queryParameters) .build(CustomHeadersHandler.RequestType.WS); @@ -331,7 +333,7 @@ private Route ws(final RequestContext ctx, final CharSequence correlationId, } private Route wsAuthentication(final JsonSchemaVersion schemaVersion, final CharSequence correlationId, - final Function, Route> inner) { + final Function inner) { final DittoHeaders dittoHeaders = DittoHeaders.newBuilder() .schemaVersion(schemaVersion) diff --git a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/RootRouteExceptionHandler.java b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/RootRouteExceptionHandler.java index e8eb21dd41..f57d5796ab 100644 --- a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/RootRouteExceptionHandler.java +++ b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/RootRouteExceptionHandler.java @@ -40,7 +40,7 @@ * This class provides an {@link ExceptionHandler} for the root route. */ @Immutable -final class RootRouteExceptionHandler { +public final class RootRouteExceptionHandler { private static final ThreadSafeDittoLogger LOGGER = DittoLoggerFactory .getThreadSafeLogger(RootRouteExceptionHandler.class); diff --git a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/OAuthTokenIntegrationSubjectIdFactory.java b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/OAuthTokenIntegrationSubjectIdFactory.java new file mode 100755 index 0000000000..bcdd025176 --- /dev/null +++ b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/OAuthTokenIntegrationSubjectIdFactory.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.ditto.services.gateway.endpoints.routes.policies; + +import org.eclipse.ditto.model.base.headers.DittoHeaders; +import org.eclipse.ditto.model.jwt.JsonWebToken; +import org.eclipse.ditto.model.placeholders.ExpressionResolver; +import org.eclipse.ditto.model.placeholders.PlaceholderFactory; +import org.eclipse.ditto.model.policies.SubjectId; +import org.eclipse.ditto.services.gateway.security.authentication.jwt.JwtPlaceholder; +import org.eclipse.ditto.services.gateway.util.config.security.OAuthConfig; + +/** + * Creator of token integration subjects for the configured OAuth subject pattern. + */ +public final class OAuthTokenIntegrationSubjectIdFactory implements TokenIntegrationSubjectIdFactory { + + private final String subjectTemplate; + + private OAuthTokenIntegrationSubjectIdFactory(final String subjectTemplate) { + this.subjectTemplate = subjectTemplate; + } + + /** + * Create an OAuth token integration subject ID factory from OAuth config. + * + * @param oAuthConfig the config. + * @return the factory. + */ + public static OAuthTokenIntegrationSubjectIdFactory of(final OAuthConfig oAuthConfig) { + return new OAuthTokenIntegrationSubjectIdFactory(oAuthConfig.getTokenIntegrationSubject()); + } + + @Override + public SubjectId getSubjectId(final DittoHeaders dittoHeaders, final JsonWebToken jwt) { + final ExpressionResolver expressionResolver = PlaceholderFactory.newExpressionResolver( + PlaceholderFactory.newPlaceholderResolver(PlaceholderFactory.newHeadersPlaceholder(), dittoHeaders), + PlaceholderFactory.newPlaceholderResolver(JwtPlaceholder.getInstance(), jwt) + ); + return SubjectId.newInstance(expressionResolver.resolvePartially(subjectTemplate)); + } +} diff --git a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/PoliciesRoute.java b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/PoliciesRoute.java index cf6e4c5972..21dc54fa3f 100755 --- a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/PoliciesRoute.java +++ b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/PoliciesRoute.java @@ -14,18 +14,30 @@ import static org.eclipse.ditto.model.base.exceptions.DittoJsonException.wrapJsonRuntimeException; +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + import org.eclipse.ditto.json.JsonFactory; import org.eclipse.ditto.json.JsonObject; import org.eclipse.ditto.json.JsonValue; import org.eclipse.ditto.model.base.headers.DittoHeaders; +import org.eclipse.ditto.model.jwt.JsonWebToken; import org.eclipse.ditto.model.policies.PoliciesModelFactory; import org.eclipse.ditto.model.policies.Policy; +import org.eclipse.ditto.model.policies.PolicyActionFailedException; import org.eclipse.ditto.model.policies.PolicyId; +import org.eclipse.ditto.model.policies.SubjectId; import org.eclipse.ditto.protocoladapter.HeaderTranslator; import org.eclipse.ditto.services.gateway.endpoints.routes.AbstractRoute; +import org.eclipse.ditto.services.gateway.security.authentication.AuthenticationResult; +import org.eclipse.ditto.services.gateway.security.authentication.jwt.JwtAuthenticationResult; import org.eclipse.ditto.services.gateway.util.config.endpoints.CommandConfig; import org.eclipse.ditto.services.gateway.util.config.endpoints.HttpConfig; import org.eclipse.ditto.signals.commands.policies.exceptions.PolicyIdNotExplicitlySettableException; +import org.eclipse.ditto.signals.commands.policies.modify.ActivateSubjects; +import org.eclipse.ditto.signals.commands.policies.modify.DeactivateSubjects; import org.eclipse.ditto.signals.commands.policies.modify.DeletePolicy; import org.eclipse.ditto.signals.commands.policies.modify.ModifyPolicy; import org.eclipse.ditto.signals.commands.policies.query.RetrievePolicy; @@ -41,10 +53,15 @@ */ public final class PoliciesRoute extends AbstractRoute { + static final String PATH_ACTIONS = "actions"; + static final String ACTIVATE_TOKEN_INTEGRATION = PolicyActionFailedException.ACTIVATE_TOKEN_INTEGRATION; + static final String DEACTIVATE_TOKEN_INTEGRATION = PolicyActionFailedException.DEACTIVATE_TOKEN_INTEGRATION; + private static final String PATH_POLICIES = "policies"; private static final String PATH_ENTRIES = "entries"; private final PolicyEntriesRoute policyEntriesRoute; + private final TokenIntegrationSubjectIdFactory tokenIntegrationSubjectIdFactory; /** * Constructs the {@code /policies} route builder. @@ -54,18 +71,22 @@ public final class PoliciesRoute extends AbstractRoute { * @param httpConfig the configuration settings of the Gateway service's HTTP endpoint. * @param commandConfig the configuration settings of the Gateway service's incoming command processing. * @param headerTranslator translates headers from external sources or to external sources. + * @param tokenIntegrationSubjectIdFactory factory of resolvers for placeholders. * @throws NullPointerException if any argument is {@code null}. */ public PoliciesRoute(final ActorRef proxyActor, final ActorSystem actorSystem, final HttpConfig httpConfig, final CommandConfig commandConfig, - final HeaderTranslator headerTranslator) { + final HeaderTranslator headerTranslator, + final TokenIntegrationSubjectIdFactory tokenIntegrationSubjectIdFactory) { super(proxyActor, actorSystem, httpConfig, commandConfig, headerTranslator); + this.tokenIntegrationSubjectIdFactory = tokenIntegrationSubjectIdFactory; policyEntriesRoute = - new PolicyEntriesRoute(proxyActor, actorSystem, httpConfig, commandConfig, headerTranslator); + new PolicyEntriesRoute(proxyActor, actorSystem, httpConfig, commandConfig, headerTranslator, + tokenIntegrationSubjectIdFactory); } /** @@ -73,19 +94,22 @@ public PoliciesRoute(final ActorRef proxyActor, * * @return the {@code /policies} route. */ - public Route buildPoliciesRoute(final RequestContext ctx, final DittoHeaders dittoHeaders) { + public Route buildPoliciesRoute(final RequestContext ctx, final DittoHeaders dittoHeaders, + final AuthenticationResult authenticationResult) { return rawPathPrefix(PathMatchers.slash().concat(PATH_POLICIES), () -> rawPathPrefix(PathMatchers.slash().concat(PathMatchers.segment()), policyId -> // /policies/ - policyRoute(ctx, dittoHeaders, PolicyId.of(policyId)) + policyRoute(ctx, dittoHeaders, PolicyId.of(policyId), authenticationResult) ) ); } - private Route policyRoute(final RequestContext ctx, final DittoHeaders dittoHeaders, final PolicyId policyId) { + private Route policyRoute(final RequestContext ctx, final DittoHeaders dittoHeaders, final PolicyId policyId, + final AuthenticationResult authenticationResult) { return concat( policyEntry(ctx, dittoHeaders, policyId), - policyEntryEntries(ctx, dittoHeaders, policyId) + policyEntryEntries(ctx, dittoHeaders, policyId, authenticationResult), + policyActions(ctx, dittoHeaders, policyId, authenticationResult) ); } @@ -134,11 +158,62 @@ private static JsonObject createPolicyJsonObjectForPut(final String jsonString, * * @return {@code /policies//entries} route. */ - private Route policyEntryEntries(final RequestContext ctx, final DittoHeaders dittoHeaders, - final PolicyId policyId) { + private Route policyEntryEntries(final RequestContext ctx, final DittoHeaders dittoHeaders, final PolicyId policyId, + final AuthenticationResult authResult) { return rawPathPrefix(PathMatchers.slash().concat(PATH_ENTRIES), () -> // /policies//entries - policyEntriesRoute.buildPolicyEntriesRoute(ctx, dittoHeaders, policyId) + policyEntriesRoute.buildPolicyEntriesRoute(ctx, dittoHeaders, policyId, authResult) ); } + /* + * Describes{@code /policies//actions} route. + */ + private Route policyActions(final RequestContext ctx, final DittoHeaders dittoHeaders, final PolicyId policyId, + final AuthenticationResult authenticationResult) { + + return rawPathPrefix(PathMatchers.slash().concat(PATH_ACTIONS), () -> concat(// /policies//actions + rawPathPrefix(PathMatchers.slash().concat(ACTIVATE_TOKEN_INTEGRATION), () -> + pathEndOrSingleSlash(() -> + extractJwt(dittoHeaders, authenticationResult, ACTIVATE_TOKEN_INTEGRATION, jwt -> + post(() -> handlePerRequest(ctx, + activateSubjects(dittoHeaders, policyId, jwt)))))), + rawPathPrefix(PathMatchers.slash().concat(DEACTIVATE_TOKEN_INTEGRATION), () -> + pathEndOrSingleSlash(() -> + extractJwt(dittoHeaders, authenticationResult, DEACTIVATE_TOKEN_INTEGRATION, jwt -> + post(() -> handlePerRequest(ctx, + deactivateSubjects(dittoHeaders, policyId, jwt)))))) + )); + } + + private ActivateSubjects activateSubjects(final DittoHeaders dittoHeaders, final PolicyId policyId, + final JsonWebToken jwt) { + + final SubjectId subjectId = tokenIntegrationSubjectIdFactory.getSubjectId(dittoHeaders, jwt); + final Instant expiry = jwt.getExpirationTime(); + return ActivateSubjects.of(policyId, subjectId, expiry, List.of(), dittoHeaders); + } + + private DeactivateSubjects deactivateSubjects(final DittoHeaders dittoHeaders, final PolicyId policyId, + final JsonWebToken jwt) { + + final SubjectId subjectId = tokenIntegrationSubjectIdFactory.getSubjectId(dittoHeaders, jwt); + return DeactivateSubjects.of(policyId, subjectId, List.of(), dittoHeaders); + } + + static Route extractJwt(final DittoHeaders dittoHeaders, + final AuthenticationResult authResult, + final String action, + final Function inner) { + + if (authResult instanceof JwtAuthenticationResult) { + final Optional jwtOptional = ((JwtAuthenticationResult) authResult).getJwt(); + if (jwtOptional.isPresent()) { + return inner.apply(jwtOptional.get()); + } + } + throw PolicyActionFailedException.newBuilderForInappropriateAuthenticationMethod(action) + .dittoHeaders(dittoHeaders) + .build(); + } + } diff --git a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/PolicyEntriesRoute.java b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/PolicyEntriesRoute.java index fe4860276c..87214b74ec 100755 --- a/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/PolicyEntriesRoute.java +++ b/services/gateway/endpoints/src/main/java/org/eclipse/ditto/services/gateway/endpoints/routes/policies/PolicyEntriesRoute.java @@ -13,10 +13,14 @@ package org.eclipse.ditto.services.gateway.endpoints.routes.policies; import static org.eclipse.ditto.model.base.exceptions.DittoJsonException.wrapJsonRuntimeException; +import static org.eclipse.ditto.services.gateway.endpoints.routes.policies.PoliciesRoute.ACTIVATE_TOKEN_INTEGRATION; +import static org.eclipse.ditto.services.gateway.endpoints.routes.policies.PoliciesRoute.DEACTIVATE_TOKEN_INTEGRATION; +import static org.eclipse.ditto.services.gateway.endpoints.routes.policies.PoliciesRoute.PATH_ACTIONS; import org.eclipse.ditto.json.JsonFactory; import org.eclipse.ditto.json.JsonObject; import org.eclipse.ditto.model.base.headers.DittoHeaders; +import org.eclipse.ditto.model.jwt.JsonWebToken; import org.eclipse.ditto.model.policies.Label; import org.eclipse.ditto.model.policies.PoliciesModelFactory; import org.eclipse.ditto.model.policies.PolicyEntry; @@ -29,8 +33,11 @@ import org.eclipse.ditto.model.policies.Subjects; import org.eclipse.ditto.protocoladapter.HeaderTranslator; import org.eclipse.ditto.services.gateway.endpoints.routes.AbstractRoute; +import org.eclipse.ditto.services.gateway.security.authentication.AuthenticationResult; import org.eclipse.ditto.services.gateway.util.config.endpoints.CommandConfig; import org.eclipse.ditto.services.gateway.util.config.endpoints.HttpConfig; +import org.eclipse.ditto.signals.commands.policies.modify.ActivateSubject; +import org.eclipse.ditto.signals.commands.policies.modify.DeactivateSubject; import org.eclipse.ditto.signals.commands.policies.modify.DeletePolicyEntry; import org.eclipse.ditto.signals.commands.policies.modify.DeleteResource; import org.eclipse.ditto.signals.commands.policies.modify.DeleteSubject; @@ -61,6 +68,8 @@ final class PolicyEntriesRoute extends AbstractRoute { private static final String PATH_SUFFIX_SUBJECTS = "subjects"; private static final String PATH_SUFFIX_RESOURCES = "resources"; + private final TokenIntegrationSubjectIdFactory tokenIntegrationSubjectIdFactory; + /** * Constructs the {@code /entries} route builder. * @@ -69,15 +78,18 @@ final class PolicyEntriesRoute extends AbstractRoute { * @param httpConfig the configuration settings of the Gateway service's HTTP endpoint. * @param commandConfig the configuration settings of the Gateway service's incoming command processing. * @param headerTranslator translates headers from external sources or to external sources. + * @param tokenIntegrationSubjectIdFactory factory of token integration subject IDs. * @throws NullPointerException if any argument is {@code null}. */ PolicyEntriesRoute(final ActorRef proxyActor, final ActorSystem actorSystem, final HttpConfig httpConfig, final CommandConfig commandConfig, - final HeaderTranslator headerTranslator) { + final HeaderTranslator headerTranslator, + final TokenIntegrationSubjectIdFactory tokenIntegrationSubjectIdFactory) { super(proxyActor, actorSystem, httpConfig, commandConfig, headerTranslator); + this.tokenIntegrationSubjectIdFactory = tokenIntegrationSubjectIdFactory; } /** @@ -85,14 +97,16 @@ final class PolicyEntriesRoute extends AbstractRoute { * * @return the {@code /entries} route. */ - Route buildPolicyEntriesRoute(final RequestContext ctx, final DittoHeaders dittoHeaders, final PolicyId policyId) { + Route buildPolicyEntriesRoute(final RequestContext ctx, final DittoHeaders dittoHeaders, final PolicyId policyId, + final AuthenticationResult authResult) { return concat( thingsEntryPolicyEntries(ctx, dittoHeaders, policyId), thingsEntryPolicyEntry(ctx, dittoHeaders, policyId), thingsEntryPolicyEntrySubjects(ctx, dittoHeaders, policyId), thingsEntryPolicyEntrySubjectsEntry(ctx, dittoHeaders, policyId), thingsEntryPolicyEntryResources(ctx, dittoHeaders, policyId), - thingsEntryPolicyEntryResourcesEntry(ctx, dittoHeaders, policyId) + thingsEntryPolicyEntryResourcesEntry(ctx, dittoHeaders, policyId), + policyEntryActions(ctx, dittoHeaders, policyId, authResult) ); } @@ -338,6 +352,40 @@ private Route thingsEntryPolicyEntryResourcesEntry(final RequestContext ctx, fin ); } + /* + * Describes {@code /entries/