From 78d88b46ef36da1b587882a2e1ff296babbc3095 Mon Sep 17 00:00:00 2001 From: Andy LoPresto Date: Mon, 20 Jul 2020 17:05:03 -0700 Subject: [PATCH] NIFI-7657 Introduced AccessTokenUnnecessaryException for authentication calls to HTTP NiFi server. Added exception mapper. NIFI-7657 Renamed exception & exception mapper to reflect scope of authentication not supported. Registered exception mapper. Signed-off-by: Pierre Villard This closes #4418. --- .../AuthenticationNotSupportedException.java | 32 ++++++++++++ .../nifi/web/NiFiWebApiResourceConfig.java | 9 ++-- .../apache/nifi/web/api/AccessResource.java | 16 +++--- ...enticationNotSupportedExceptionMapper.java | 49 +++++++++++++++++++ 4 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 nifi-framework-api/src/main/java/org/apache/nifi/authentication/exception/AuthenticationNotSupportedException.java create mode 100644 nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/AuthenticationNotSupportedExceptionMapper.java diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/authentication/exception/AuthenticationNotSupportedException.java b/nifi-framework-api/src/main/java/org/apache/nifi/authentication/exception/AuthenticationNotSupportedException.java new file mode 100644 index 0000000000..8326d9286b --- /dev/null +++ b/nifi-framework-api/src/main/java/org/apache/nifi/authentication/exception/AuthenticationNotSupportedException.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.authentication.exception; + +/** + * Represents the case when the application is not secured so any authentication requests are rejected as unnecessary. + */ +public class AuthenticationNotSupportedException extends RuntimeException { + + public AuthenticationNotSupportedException(String message, Throwable cause) { + super(message, cause); + } + + public AuthenticationNotSupportedException(String message) { + super(message); + } + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiResourceConfig.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiResourceConfig.java index 7569b37ac3..0ff68bb1e5 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiResourceConfig.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiResourceConfig.java @@ -16,9 +16,12 @@ */ package org.apache.nifi.web; +import javax.servlet.ServletContext; +import javax.ws.rs.core.Context; import org.apache.nifi.web.api.config.AccessDeniedExceptionMapper; import org.apache.nifi.web.api.config.AdministrationExceptionMapper; import org.apache.nifi.web.api.config.AuthenticationCredentialsNotFoundExceptionMapper; +import org.apache.nifi.web.api.config.AuthenticationNotSupportedExceptionMapper; import org.apache.nifi.web.api.config.AuthorizationAccessExceptionMapper; import org.apache.nifi.web.api.config.ClusterExceptionMapper; import org.apache.nifi.web.api.config.IllegalArgumentExceptionMapper; @@ -30,9 +33,9 @@ import org.apache.nifi.web.api.config.IllegalNodeReconnectionExceptionMapper; import org.apache.nifi.web.api.config.IllegalStateExceptionMapper; import org.apache.nifi.web.api.config.InvalidAuthenticationExceptionMapper; import org.apache.nifi.web.api.config.InvalidRevisionExceptionMapper; +import org.apache.nifi.web.api.config.JsonContentConversionExceptionMapper; import org.apache.nifi.web.api.config.JsonMappingExceptionMapper; import org.apache.nifi.web.api.config.JsonParseExceptionMapper; -import org.apache.nifi.web.api.config.JsonContentConversionExceptionMapper; import org.apache.nifi.web.api.config.MutableRequestExceptionMapper; import org.apache.nifi.web.api.config.NiFiCoreExceptionMapper; import org.apache.nifi.web.api.config.NoClusterCoordinatorExceptionMapper; @@ -56,9 +59,6 @@ import org.glassfish.jersey.server.filter.EncodingFilter; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; -import javax.servlet.ServletContext; -import javax.ws.rs.core.Context; - public class NiFiWebApiResourceConfig extends ResourceConfig { public NiFiWebApiResourceConfig(@Context ServletContext servletContext) { @@ -105,6 +105,7 @@ public class NiFiWebApiResourceConfig extends ResourceConfig { // exception mappers register(AccessDeniedExceptionMapper.class); register(AuthorizationAccessExceptionMapper.class); + register(AuthenticationNotSupportedExceptionMapper.class); register(InvalidAuthenticationExceptionMapper.class); register(AuthenticationCredentialsNotFoundExceptionMapper.class); register(AdministrationExceptionMapper.class); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java index 8b632f8052..0e3e70f12e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java @@ -53,6 +53,7 @@ import org.apache.nifi.admin.service.AdministrationException; import org.apache.nifi.authentication.AuthenticationResponse; import org.apache.nifi.authentication.LoginCredentials; import org.apache.nifi.authentication.LoginIdentityProvider; +import org.apache.nifi.authentication.exception.AuthenticationNotSupportedException; import org.apache.nifi.authentication.exception.IdentityAccessException; import org.apache.nifi.authentication.exception.InvalidLoginCredentialsException; import org.apache.nifi.authorization.AccessDeniedException; @@ -103,6 +104,7 @@ public class AccessResource extends ApplicationResource { private static final String OIDC_REQUEST_IDENTIFIER = "oidc-request-identifier"; private static final String OIDC_ERROR_TITLE = "Unable to continue login sequence"; + private static final String AUTHENTICATION_NOT_ENABLED_MSG = "User authentication/authorization is only supported when running over HTTPS."; private X509CertificateExtractor certificateExtractor; private X509AuthenticationProvider x509AuthenticationProvider; @@ -157,7 +159,7 @@ public class AccessResource extends ApplicationResource { public void oidcRequest(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) throws Exception { // only consider user specific access over https if (!httpServletRequest.isSecure()) { - forwardToMessagePage(httpServletRequest, httpServletResponse, "User authentication/authorization is only supported when running over HTTPS."); + forwardToMessagePage(httpServletRequest, httpServletResponse, AUTHENTICATION_NOT_ENABLED_MSG); return; } @@ -290,7 +292,7 @@ public class AccessResource extends ApplicationResource { public Response oidcExchange(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) throws Exception { // only consider user specific access over https if (!httpServletRequest.isSecure()) { - throw new IllegalStateException("User authentication/authorization is only supported when running over HTTPS."); + throw new AuthenticationNotSupportedException(AUTHENTICATION_NOT_ENABLED_MSG); } // ensure oidc is enabled @@ -358,7 +360,7 @@ public class AccessResource extends ApplicationResource { public void knoxRequest(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) throws Exception { // only consider user specific access over https if (!httpServletRequest.isSecure()) { - forwardToMessagePage(httpServletRequest, httpServletResponse, "User authentication/authorization is only supported when running over HTTPS."); + forwardToMessagePage(httpServletRequest, httpServletResponse, AUTHENTICATION_NOT_ENABLED_MSG); return; } @@ -445,7 +447,7 @@ public class AccessResource extends ApplicationResource { // only consider user specific access over https if (!httpServletRequest.isSecure()) { - throw new IllegalStateException("User authentication/authorization is only supported when running over HTTPS."); + throw new AuthenticationNotSupportedException(AUTHENTICATION_NOT_ENABLED_MSG); } final AccessStatusDTO accessStatus = new AccessStatusDTO(); @@ -584,7 +586,7 @@ public class AccessResource extends ApplicationResource { public Response createUiExtensionToken(@Context HttpServletRequest httpServletRequest) { // only support access tokens when communicating over HTTPS if (!httpServletRequest.isSecure()) { - throw new IllegalStateException("UI extension access tokens are only issued over HTTPS."); + throw new AuthenticationNotSupportedException("UI extension access tokens are only issued over HTTPS."); } final NiFiUser user = NiFiUserUtils.getNiFiUser(); @@ -633,7 +635,7 @@ public class AccessResource extends ApplicationResource { // only support access tokens when communicating over HTTPS if (!httpServletRequest.isSecure()) { - throw new IllegalStateException("Access tokens are only issued over HTTPS."); + throw new AuthenticationNotSupportedException("Access tokens are only issued over HTTPS."); } // If Kerberos Service Principal and keytab location not configured, throws exception @@ -709,7 +711,7 @@ public class AccessResource extends ApplicationResource { // only support access tokens when communicating over HTTPS if (!httpServletRequest.isSecure()) { - throw new IllegalStateException("Access tokens are only issued over HTTPS."); + throw new AuthenticationNotSupportedException("Access tokens are only issued over HTTPS."); } // if not configuration for login, don't consider credentials diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/AuthenticationNotSupportedExceptionMapper.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/AuthenticationNotSupportedExceptionMapper.java new file mode 100644 index 0000000000..22b3fc6cbb --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/AuthenticationNotSupportedExceptionMapper.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.web.api.config; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import org.apache.nifi.authentication.exception.AuthenticationNotSupportedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Maps web application exceptions into client responses. + */ +@Provider +public class AuthenticationNotSupportedExceptionMapper implements ExceptionMapper { + + private static final Logger logger = LoggerFactory.getLogger(AuthenticationNotSupportedExceptionMapper.class); + + /** + * Returns a {@link Response} to the client which translates the provided + * exception. Ideally, these requests would not be made when HTTPS is off, but + * these expected messages confuse users reading the logs. + * + * @param exception the exception indicating HTTPS is disabled + * @return the response to the client + */ + @Override + public Response toResponse(AuthenticationNotSupportedException exception) { + // Use DEBUG level to avoid polluting the logs + logger.debug("{}. Returning {} response.", exception, Response.Status.CONFLICT, exception); + return Response.status(Response.Status.CONFLICT).entity(exception.getMessage()).type("text/plain").build(); + } + +}