diff options
author | Bjørn Christian Seime <bjorncs@oath.com> | 2017-11-20 13:49:00 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@oath.com> | 2017-11-20 15:49:05 +0100 |
commit | f300edc1b8f1a6d123d9051bf258e76efb9bbebe (patch) | |
tree | 9e41e368e9402d64b0de31e7ce1a8d1b670096be /controller-server | |
parent | 67383d77a96f0d6ff1c653bf49f9d0dfa2c6fbee (diff) |
Send error response as application/json instead of html
Diffstat (limited to 'controller-server')
3 files changed, 44 insertions, 24 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/AthenzPrincipalFilter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/AthenzPrincipalFilter.java index da5136817df..f5e2020d3e3 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/AthenzPrincipalFilter.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/AthenzPrincipalFilter.java @@ -2,22 +2,19 @@ package com.yahoo.vespa.hosted.controller.athenz.filter; import com.google.inject.Inject; -import com.yahoo.jdisc.Response; -import com.yahoo.jdisc.handler.FastContentWriter; -import com.yahoo.jdisc.handler.ResponseDispatch; import com.yahoo.jdisc.handler.ResponseHandler; import com.yahoo.jdisc.http.filter.DiscFilterRequest; import com.yahoo.jdisc.http.filter.SecurityRequestFilter; -import com.yahoo.jdisc.http.server.jetty.ErrorResponseContentCreator; import com.yahoo.vespa.hosted.controller.athenz.AthenzPrincipal; import com.yahoo.vespa.hosted.controller.athenz.InvalidTokenException; import com.yahoo.vespa.hosted.controller.athenz.NToken; import com.yahoo.vespa.hosted.controller.athenz.ZmsKeystore; import com.yahoo.vespa.hosted.controller.athenz.config.AthenzConfig; -import java.util.Optional; import java.util.concurrent.Executor; +import static com.yahoo.vespa.hosted.controller.athenz.filter.SecurityFilterUtils.sendUnauthorized; + /** * Performs authentication by validating the principal token (NToken) header. * @@ -26,7 +23,6 @@ import java.util.concurrent.Executor; // TODO bjorncs: Move this class into separate container-security bundle public class AthenzPrincipalFilter implements SecurityRequestFilter { - private final ErrorResponseContentCreator responseCreator = new ErrorResponseContentCreator(); private final NTokenValidator validator; private final String principalTokenHeader; @@ -48,7 +44,7 @@ public class AthenzPrincipalFilter implements SecurityRequestFilter { public void filter(DiscFilterRequest request, ResponseHandler responseHandler) { String rawToken = request.getHeader(principalTokenHeader); if (rawToken == null || rawToken.isEmpty()) { - sendUnauthorized(request, responseHandler, "NToken is missing"); + sendUnauthorized(responseHandler, "NToken is missing"); return; } try { @@ -56,16 +52,7 @@ public class AthenzPrincipalFilter implements SecurityRequestFilter { request.setUserPrincipal(principal); request.setRemoteUser(principal.getName()); } catch (InvalidTokenException e) { - sendUnauthorized(request, responseHandler, e.getMessage()); - } - } - - protected void sendUnauthorized(DiscFilterRequest request, ResponseHandler responseHandler, String message) { - try (FastContentWriter writer = ResponseDispatch.newInstance(Response.Status.UNAUTHORIZED) - .connectFastWriter(responseHandler)) { - writer.write( - responseCreator.createErrorContent( - request.getRequestURI(), Response.Status.UNAUTHORIZED, Optional.of(message))); + sendUnauthorized(responseHandler, e.getMessage()); } } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/SecurityFilterUtils.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/SecurityFilterUtils.java new file mode 100644 index 00000000000..075e5e76acd --- /dev/null +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/SecurityFilterUtils.java @@ -0,0 +1,32 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.athenz.filter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.yahoo.jdisc.Response; +import com.yahoo.jdisc.handler.FastContentWriter; +import com.yahoo.jdisc.handler.ResponseDispatch; +import com.yahoo.jdisc.handler.ResponseHandler; + +/** + * @author bjorncs + */ +class SecurityFilterUtils { + private static final ObjectMapper mapper = new ObjectMapper(); + + private SecurityFilterUtils() {} + + static void sendUnauthorized(ResponseHandler responseHandler, String message) { + Response response = new Response(Response.Status.UNAUTHORIZED); + response.headers().put("Content-Type", "application/json"); + ObjectNode errorMessage = mapper.createObjectNode(); + errorMessage.put("message", message); + try (FastContentWriter writer = ResponseDispatch.newInstance(response).connectFastWriter(responseHandler)) { + writer.write(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorMessage)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/UserAuthWithAthenzPrincipalFilter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/UserAuthWithAthenzPrincipalFilter.java index f20490db910..d125f279b63 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/UserAuthWithAthenzPrincipalFilter.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/athenz/filter/UserAuthWithAthenzPrincipalFilter.java @@ -9,6 +9,9 @@ import com.yahoo.vespa.hosted.controller.athenz.config.AthenzConfig; import com.yahoo.yolean.chain.Provides; import java.util.concurrent.Executor; +import java.util.stream.Stream; + +import static com.yahoo.vespa.hosted.controller.athenz.filter.SecurityFilterUtils.sendUnauthorized; /** * A variant of the {@link AthenzPrincipalFilter} to be used in combination with a cookie-based @@ -41,7 +44,7 @@ public class UserAuthWithAthenzPrincipalFilter extends AthenzPrincipalFilter { case USER_COOKIE_OK: return; // Authenticated using user cookie case USER_COOKIE_INVALID: - sendUnauthorized(request, responseHandler, "Your user cookie is invalid (either expired or tampered)"); + sendUnauthorized(responseHandler, "Your user cookie is invalid (either expired or tampered)"); break; } } @@ -51,12 +54,10 @@ public class UserAuthWithAthenzPrincipalFilter extends AthenzPrincipalFilter { throw new IllegalStateException("User authentication filter passthru attribute missing"); } Integer statusCode = (Integer) request.getAttribute(userAuthenticationPassThruAttribute); - for (UserAuthenticationResult result : UserAuthenticationResult.values()) { - if (result.statusCode == statusCode) { - return result; - } - } - throw new IllegalStateException("Invalid status code: " + statusCode); + return Stream.of(UserAuthenticationResult.values()) + .filter(uar -> uar.statusCode == statusCode) + .findAny() + .orElseThrow(() -> new IllegalStateException("Invalid status code: " + statusCode)); } private enum UserAuthenticationResult { |