diff --git a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java index 4b4bb77d8d..54866a4e39 100644 --- a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java +++ b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java @@ -39,7 +39,6 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * The NiFiProperties class holds all properties which are needed for various @@ -181,12 +180,6 @@ public class NiFiProperties extends ApplicationProperties { public static final String SECURITY_USER_OIDC_FALLBACK_CLAIMS_IDENTIFYING_USER = "nifi.security.user.oidc.fallback.claims.identifying.user"; public static final String SECURITY_USER_OIDC_TOKEN_REFRESH_WINDOW = "nifi.security.user.oidc.token.refresh.window"; - // apache knox - public static final String SECURITY_USER_KNOX_URL = "nifi.security.user.knox.url"; - public static final String SECURITY_USER_KNOX_PUBLIC_KEY = "nifi.security.user.knox.publicKey"; - public static final String SECURITY_USER_KNOX_COOKIE_NAME = "nifi.security.user.knox.cookieName"; - public static final String SECURITY_USER_KNOX_AUDIENCES = "nifi.security.user.knox.audiences"; - // saml public static final String SECURITY_USER_SAML_IDP_METADATA_URL = "nifi.security.user.saml.idp.metadata.url"; public static final String SECURITY_USER_SAML_SP_ENTITY_ID = "nifi.security.user.saml.sp.entity.id"; @@ -1149,57 +1142,6 @@ public class NiFiProperties extends ApplicationProperties { return getProperty(DIAGNOSTICS_ON_SHUTDOWN_MAX_DIRECTORY_SIZE, DEFAULT_DIAGNOSTICS_ON_SHUTDOWN_MAX_DIRECTORY_SIZE); } - /** - * Returns whether Knox SSO is enabled. - * - * @return whether Knox SSO is enabled - */ - public boolean isKnoxSsoEnabled() { - return !StringUtils.isBlank(getKnoxUrl()); - } - - /** - * Returns the Knox URL. - * - * @return Knox URL - */ - public String getKnoxUrl() { - return getProperty(SECURITY_USER_KNOX_URL); - } - - /** - * Gets the configured Knox Audiences. - * - * @return Knox audiences - */ - public Set getKnoxAudiences() { - final String rawAudiences = getProperty(SECURITY_USER_KNOX_AUDIENCES); - if (StringUtils.isBlank(rawAudiences)) { - return null; - } else { - final String[] audienceTokens = rawAudiences.split(","); - return Stream.of(audienceTokens).map(String::trim).filter(aud -> !StringUtils.isEmpty(aud)).collect(Collectors.toSet()); - } - } - - /** - * Returns the path to the Knox public key. - * - * @return path to the Knox public key - */ - public Path getKnoxPublicKeyPath() { - return Paths.get(getProperty(SECURITY_USER_KNOX_PUBLIC_KEY)); - } - - /** - * Returns the name of the Knox cookie. - * - * @return name of the Knox cookie - */ - public String getKnoxCookieName() { - return getProperty(SECURITY_USER_KNOX_COOKIE_NAME); - } - /** * Returns whether SAML is enabled. * @@ -1354,7 +1296,6 @@ public class NiFiProperties extends ApplicationProperties { * - login identity provider is not populated * - Kerberos service support is not enabled * - openid connect is not enabled - * - knox sso is not enabled * - anonymous authentication is not enabled *

* @@ -1363,7 +1304,6 @@ public class NiFiProperties extends ApplicationProperties { public boolean isClientAuthRequiredForRestApi() { return !isLoginIdentityProviderEnabled() && !isOidcEnabled() - && !isKnoxSsoEnabled() && !isSamlEnabled() && !isAnonymousAuthenticationAllowed(); } diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc b/nifi-docs/src/main/asciidoc/administration-guide.adoc index fe111c9732..5bd5749576 100644 --- a/nifi-docs/src/main/asciidoc/administration-guide.adoc +++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc @@ -347,9 +347,6 @@ used. The default value of this property is `single-user-provider` supporting au For Single sign-on authentication, NiFi will redirect users to the Identity Provider before returning to NiFi. NiFi will then process responses and convert attributes to application token information. -During Apache Knox authentication, NiFi will redirect users to login with Apache Knox before returning to NiFi. NiFi will verify the Apache Knox -token during authentication. - NOTE: NiFi cannot be configured for multiple authentication strategies simultaneously. NiFi will require client certificates for authenticating users over HTTPS if no other strategies have been configured. @@ -638,21 +635,6 @@ SAML authentication enables the following REST API resources for integration wit | /nifi-api/access/saml/single-logout/request | Complete SAML 2.0 Single Logout processing initiating a request to the Asserting Party. Requires Single Logout to be enabled. |====================================== -[[apache_knox]] -=== Apache Knox - -To enable authentication via Apache Knox the following properties must be configured in _nifi.properties_. - -[options="header"] -|================================================================================================================================================== -| Property Name | Description -|`nifi.security.user.knox.url` | The URL for the Apache Knox login page. -|`nifi.security.user.knox.publicKey` | The path to the Apache Knox public key that will be used to verify the signatures of the authentication tokens in the HTTP Cookie. -|`nifi.security.user.knox.cookieName` | The name of the HTTP Cookie that Apache Knox will generate after successful login. The default value is `hadoop-jwt`. -|`nifi.security.user.knox.audiences` | Optional. A comma separate listed of allowed audiences. If set, the audience in the token must be present in -this listing. The audience that is populated in the token can be configured in Knox. -|================================================================================================================================================== - [[json_web_token]] === JSON Web Tokens diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/replication/ThreadPoolRequestReplicator.java b/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/replication/ThreadPoolRequestReplicator.java index 6d9ec3a596..35c26e3ae5 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/replication/ThreadPoolRequestReplicator.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/replication/ThreadPoolRequestReplicator.java @@ -250,11 +250,6 @@ public class ThreadPoolRequestReplicator implements RequestReplicator { // remove the access token if present, since the user is already authenticated... authorization // will happen when the request is replicated using the proxy chain above removeHeader(headers, SecurityHeader.AUTHORIZATION.getHeader()); - - // if knox sso cookie name is set, remove any authentication cookie since this user is already authenticated - // and will be included in the proxied entities chain above... authorization will happen when the - // request is replicated - removeCookie(headers, nifiProperties.getKnoxCookieName()); removeCookie(headers, SecurityCookieName.AUTHORIZATION_BEARER.getName()); removeCookie(headers, SecurityCookieName.REQUEST_TOKEN.getName()); diff --git a/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml b/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml index 0bbe502d04..f73c640f8d 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml +++ b/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml @@ -174,12 +174,6 @@ JDK 60 secs - - - - hadoop-jwt - - diff --git a/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties b/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties index 9c54843e41..3d9744fca5 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties +++ b/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties @@ -219,12 +219,6 @@ nifi.security.user.oidc.claim.groups=${nifi.security.user.oidc.claim.groups} nifi.security.user.oidc.truststore.strategy=${nifi.security.user.oidc.truststore.strategy} nifi.security.user.oidc.token.refresh.window=${nifi.security.user.oidc.token.refresh.window} -# Apache Knox SSO Properties # -nifi.security.user.knox.url=${nifi.security.user.knox.url} -nifi.security.user.knox.publicKey=${nifi.security.user.knox.publicKey} -nifi.security.user.knox.cookieName=${nifi.security.user.knox.cookieName} -nifi.security.user.knox.audiences=${nifi.security.user.knox.audiences} - # SAML Properties # nifi.security.user.saml.idp.metadata.url=${nifi.security.user.saml.idp.metadata.url} nifi.security.user.saml.sp.entity.id=${nifi.security.user.saml.sp.entity.id} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java index b0a1ea77a5..3762574e78 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java @@ -284,7 +284,6 @@ public class JettyServer implements NiFiServer, ExtensionUiLoader { // load the web ui app final WebAppContext webUiContext = loadWar(webUiWar, CONTEXT_PATH_NIFI, frameworkClassLoader); webUiContext.getInitParams().put("oidc-supported", String.valueOf(props.isOidcEnabled())); - webUiContext.getInitParams().put("knox-supported", String.valueOf(props.isKnoxSsoEnabled())); webUiContext.getInitParams().put("saml-supported", String.valueOf(props.isSamlEnabled())); webUiContext.getInitParams().put("saml-single-logout-supported", String.valueOf(props.isSamlSingleLogoutEnabled())); webAppContextHandlers.addHandler(webUiContext); @@ -311,7 +310,6 @@ public class JettyServer implements NiFiServer, ExtensionUiLoader { if (webNewUiWar != null) { final WebAppContext newUiContext = loadWar(webNewUiWar, CONTEXT_PATH_NF, frameworkClassLoader); newUiContext.getInitParams().put("oidc-supported", String.valueOf(props.isOidcEnabled())); - newUiContext.getInitParams().put("knox-supported", String.valueOf(props.isKnoxSsoEnabled())); newUiContext.getInitParams().put("saml-supported", String.valueOf(props.isSamlEnabled())); newUiContext.getInitParams().put("saml-single-logout-supported", String.valueOf(props.isSamlSingleLogoutEnabled())); webAppContextHandlers.addHandler(newUiContext); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java index c27ca5e0b3..a97fbdca84 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java @@ -16,7 +16,6 @@ */ package org.apache.nifi.web.api; -import java.net.HttpURLConnection; import java.net.URI; import java.security.cert.X509Certificate; import java.time.Instant; @@ -42,7 +41,6 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.UriBuilder; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.admin.service.AdministrationException; import org.apache.nifi.authentication.AuthenticationResponse; @@ -69,7 +67,6 @@ import org.apache.nifi.web.security.UntrustedProxyException; import org.apache.nifi.web.security.cookie.ApplicationCookieName; import org.apache.nifi.web.security.jwt.provider.BearerTokenProvider; import org.apache.nifi.web.security.jwt.revocation.JwtLogoutListener; -import org.apache.nifi.web.security.knox.KnoxService; import org.apache.nifi.web.security.logout.LogoutRequest; import org.apache.nifi.web.security.logout.LogoutRequestManager; import org.apache.nifi.web.security.token.LoginAuthenticationToken; @@ -108,7 +105,6 @@ public class AccessResource extends ApplicationResource { private JwtDecoder jwtDecoder; private BearerTokenProvider bearerTokenProvider; private BearerTokenResolver bearerTokenResolver; - private KnoxService knoxService; private LogoutRequestManager logoutRequestManager; /** @@ -140,74 +136,6 @@ public class AccessResource extends ApplicationResource { return generateOkResponse(entity).build(); } - @GET - @Consumes(MediaType.WILDCARD) - @Produces(MediaType.WILDCARD) - @Path("knox/request") - @Operation( - summary = "Initiates a request to authenticate through Apache Knox." - ) - public void knoxRequest(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) throws Exception { - // only consider user specific access over https - if (!httpServletRequest.isSecure()) { - httpServletResponse.sendError(HttpURLConnection.HTTP_NOT_ACCEPTABLE, AUTHENTICATION_NOT_ENABLED_MSG); - return; - } - - // ensure knox is enabled - if (!knoxService.isKnoxEnabled()) { - httpServletResponse.sendError(HttpURLConnection.HTTP_NOT_ACCEPTABLE, "Apache Knox SSO support is not configured."); - return; - } - - // build the originalUri, and direct back to the ui - final String originalUri = generateResourceUri("access", "knox", "callback"); - - // build the authorization uri - final URI authorizationUri = UriBuilder.fromUri(knoxService.getKnoxUrl()) - .queryParam("originalUrl", originalUri) - .build(); - - // generate the response - httpServletResponse.sendRedirect(authorizationUri.toString()); - } - - @GET - @Consumes(MediaType.WILDCARD) - @Produces(MediaType.WILDCARD) - @Path("knox/callback") - @Operation( - summary = "Redirect/callback URI for processing the result of the Apache Knox login sequence." - ) - public void knoxCallback(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) throws Exception { - // only consider user specific access over https - if (!httpServletRequest.isSecure()) { - httpServletResponse.sendError(HttpURLConnection.HTTP_NOT_ACCEPTABLE, AUTHENTICATION_NOT_ENABLED_MSG); - return; - } - - // ensure knox is enabled - if (!knoxService.isKnoxEnabled()) { - httpServletResponse.sendError(HttpURLConnection.HTTP_NOT_ACCEPTABLE, "Apache Knox SSO support is not configured."); - return; - } - - httpServletResponse.sendRedirect(getNiFiUri()); - } - - @GET - @Consumes(MediaType.WILDCARD) - @Produces(MediaType.WILDCARD) - @Path("knox/logout") - @Operation( - summary = "Performs a logout in the Apache Knox.", - description = NON_GUARANTEED_ENDPOINT - ) - public void knoxLogout(@Context HttpServletResponse httpServletResponse) throws Exception { - String redirectPath = generateResourceUri("..", "nifi", "login"); - httpServletResponse.sendRedirect(redirectPath); - } - /** * Gets the status the client's access. * @@ -542,10 +470,6 @@ public class AccessResource extends ApplicationResource { this.certificateExtractor = certificateExtractor; } - public void setKnoxService(KnoxService knoxService) { - this.knoxService = knoxService; - } - public void setLogoutRequestManager(LogoutRequestManager logoutRequestManager) { this.logoutRequestManager = logoutRequestManager; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml index 6c74a66397..d14200d0b7 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml @@ -607,7 +607,6 @@ - diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/AuthenticationSecurityConfiguration.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/AuthenticationSecurityConfiguration.java index a0f5fccb9a..d100298ee7 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/AuthenticationSecurityConfiguration.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/AuthenticationSecurityConfiguration.java @@ -37,7 +37,6 @@ import org.springframework.security.authentication.AuthenticationManager; ClientRegistrationConfiguration.class, JwtAuthenticationSecurityConfiguration.class, JwtDecoderConfiguration.class, - KnoxAuthenticationSecurityConfiguration.class, OidcSecurityConfiguration.class, SamlAuthenticationSecurityConfiguration.class, X509AuthenticationSecurityConfiguration.class diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/KnoxAuthenticationSecurityConfiguration.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/KnoxAuthenticationSecurityConfiguration.java deleted file mode 100644 index da01fecfab..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/KnoxAuthenticationSecurityConfiguration.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.security.configuration; - -import org.apache.nifi.authorization.Authorizer; -import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.security.knox.KnoxAuthenticationFilter; -import org.apache.nifi.web.security.knox.KnoxAuthenticationProvider; -import org.apache.nifi.web.security.knox.KnoxService; -import org.apache.nifi.web.security.knox.KnoxServiceFactoryBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; - -/** - * Knox Configuration for Authentication Security - */ -@Configuration -public class KnoxAuthenticationSecurityConfiguration { - private final NiFiProperties niFiProperties; - - private final Authorizer authorizer; - - @Autowired - public KnoxAuthenticationSecurityConfiguration( - final NiFiProperties niFiProperties, - final Authorizer authorizer - ) { - this.niFiProperties = niFiProperties; - this.authorizer = authorizer; - } - - @Bean - public KnoxAuthenticationFilter knoxAuthenticationFilter(final AuthenticationManager authenticationManager) { - final KnoxAuthenticationFilter knoxAuthenticationFilter = new KnoxAuthenticationFilter(); - knoxAuthenticationFilter.setAuthenticationManager(authenticationManager); - knoxAuthenticationFilter.setProperties(niFiProperties); - return knoxAuthenticationFilter; - } - - @Bean - public KnoxAuthenticationProvider knoxAuthenticationProvider() { - return new KnoxAuthenticationProvider(knoxService(), niFiProperties, authorizer); - } - - @Bean - public KnoxService knoxService() { - final KnoxServiceFactoryBean knoxServiceFactoryBean = new KnoxServiceFactoryBean(); - knoxServiceFactoryBean.setProperties(niFiProperties); - return knoxServiceFactoryBean.getObject(); - } -} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/WebSecurityConfiguration.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/WebSecurityConfiguration.java index 9fe3c55709..6f5dec1f00 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/WebSecurityConfiguration.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/configuration/WebSecurityConfiguration.java @@ -24,7 +24,6 @@ import org.apache.nifi.web.security.csrf.CsrfCookieRequestMatcher; import org.apache.nifi.web.security.csrf.SkipReplicatedCsrfFilter; import org.apache.nifi.web.security.csrf.StandardCookieCsrfTokenRepository; import org.apache.nifi.web.security.csrf.StandardCsrfTokenRequestAttributeHandler; -import org.apache.nifi.web.security.knox.KnoxAuthenticationFilter; import org.apache.nifi.web.security.log.AuthenticationUserFilter; import org.apache.nifi.web.security.oidc.client.web.OidcBearerTokenRefreshFilter; import org.apache.nifi.web.security.oidc.logout.OidcLogoutFilter; @@ -87,7 +86,6 @@ public class WebSecurityConfiguration { final StandardAuthenticationEntryPoint authenticationEntryPoint, final X509AuthenticationFilter x509AuthenticationFilter, final BearerTokenAuthenticationFilter bearerTokenAuthenticationFilter, - final KnoxAuthenticationFilter knoxAuthenticationFilter, final NiFiAnonymousAuthenticationFilter anonymousAuthenticationFilter, final OAuth2LoginAuthenticationFilter oAuth2LoginAuthenticationFilter, final OAuth2AuthorizationCodeGrantFilter oAuth2AuthorizationCodeGrantFilter, @@ -115,8 +113,6 @@ public class WebSecurityConfiguration { "/access", "/access/config", "/access/token", - "/access/knox/callback", - "/access/knox/request", "/access/logout/complete", "/authentication/configuration" ).permitAll() @@ -140,10 +136,6 @@ public class WebSecurityConfiguration { .addFilterBefore(bearerTokenAuthenticationFilter, AnonymousAuthenticationFilter.class) .addFilterBefore(new AuthenticationUserFilter(), ExceptionTranslationFilter.class); - if (properties.isKnoxSsoEnabled()) { - http.addFilterBefore(knoxAuthenticationFilter, AnonymousAuthenticationFilter.class); - } - if (properties.isAnonymousAuthenticationAllowed() || properties.isHttpEnabled()) { http.addFilterAfter(anonymousAuthenticationFilter, AnonymousAuthenticationFilter.class); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxAuthenticationFilter.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxAuthenticationFilter.java deleted file mode 100644 index 59f4e20d99..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxAuthenticationFilter.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.security.knox; - -import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.security.NiFiAuthenticationFilter; -import org.springframework.security.core.Authentication; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; - -/** - */ -public class KnoxAuthenticationFilter extends NiFiAuthenticationFilter { - - @Override - public Authentication attemptAuthentication(final HttpServletRequest request) { - // only support knox login when running securely - if (!request.isSecure()) { - return null; - } - - // ensure knox sso support is enabled - final NiFiProperties properties = getProperties(); - if (!properties.isKnoxSsoEnabled()) { - return null; - } - - // get the principal out of the user token - final String knoxJwt = getJwtFromCookie(request, properties.getKnoxCookieName()); - - // if there is no cookie, return null to attempt another authentication - if (knoxJwt == null) { - return null; - } else { - // otherwise create the authentication request token - return new KnoxAuthenticationRequestToken(knoxJwt, request.getRemoteAddr()); - } - } - - public String getJwtFromCookie(final HttpServletRequest request, final String cookieName) { - String jwt = null; - - final Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - if (cookieName.equals(cookie.getName())) { - jwt = cookie.getValue(); - break; - } - } - } - - return jwt; - } - -} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxAuthenticationProvider.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxAuthenticationProvider.java deleted file mode 100644 index 9727d38478..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxAuthenticationProvider.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.security.knox; - -import com.nimbusds.jose.JOSEException; -import org.apache.nifi.authorization.Authorizer; -import org.apache.nifi.authorization.user.NiFiUser; -import org.apache.nifi.authorization.user.NiFiUserDetails; -import org.apache.nifi.authorization.user.StandardNiFiUser.Builder; -import org.apache.nifi.util.NiFiProperties; -import org.apache.nifi.web.security.InvalidAuthenticationException; -import org.apache.nifi.web.security.NiFiAuthenticationProvider; -import org.apache.nifi.web.security.token.NiFiAuthenticationToken; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; - -import java.text.ParseException; - -/** - * - */ -public class KnoxAuthenticationProvider extends NiFiAuthenticationProvider { - - private static final Logger logger = LoggerFactory.getLogger(KnoxAuthenticationProvider.class); - - private final KnoxService knoxService; - - public KnoxAuthenticationProvider(KnoxService knoxService, NiFiProperties nifiProperties, Authorizer authorizer) { - super(nifiProperties, authorizer); - this.knoxService = knoxService; - } - - @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - final KnoxAuthenticationRequestToken request = (KnoxAuthenticationRequestToken) authentication; - - try { - final String jwtPrincipal = knoxService.getAuthenticationFromToken(request.getToken()); - final String mappedIdentity = mapIdentity(jwtPrincipal); - final NiFiUser user = new Builder().identity(mappedIdentity).groups(getUserGroups(mappedIdentity)).clientAddress(request.getClientAddress()).build(); - return new NiFiAuthenticationToken(new NiFiUserDetails(user)); - } catch (ParseException | JOSEException e) { - logger.info("Unable to validate the access token: " + e.getMessage(), e); - throw new InvalidAuthenticationException("Unable to validate the access token.", e); - } - } - - @Override - public boolean supports(Class authentication) { - return KnoxAuthenticationRequestToken.class.isAssignableFrom(authentication); - } -} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxAuthenticationRequestToken.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxAuthenticationRequestToken.java deleted file mode 100644 index e22c8444aa..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxAuthenticationRequestToken.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.security.knox; - -import org.apache.nifi.web.security.NiFiAuthenticationRequestToken; - -/** - * This is an authentication request with a given JWT token. - */ -public class KnoxAuthenticationRequestToken extends NiFiAuthenticationRequestToken { - - private final String token; - - /** - * Creates a representation of the jwt authentication request for a user. - * - * @param token The unique token for this user - * @param clientAddress the address of the client making the request - */ - public KnoxAuthenticationRequestToken(final String token, final String clientAddress) { - super(clientAddress); - setAuthenticated(false); - this.token = token; - } - - @Override - public Object getCredentials() { - return null; - } - - @Override - public Object getPrincipal() { - return token; - } - - public String getToken() { - return token; - } - - @Override - public String toString() { - return ""; - } - -} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxConfiguration.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxConfiguration.java deleted file mode 100644 index 2c162d1024..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxConfiguration.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.security.knox; - -import java.security.interfaces.RSAPublicKey; -import java.util.Set; - -public interface KnoxConfiguration { - - boolean isKnoxEnabled(); - - String getKnoxUrl(); - - Set getAudiences(); - - String getKnoxCookieName(); - - RSAPublicKey getKnoxPublicKey(); -} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxService.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxService.java deleted file mode 100644 index c72de12cb8..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxService.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * 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.security.knox; - -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSObject; -import com.nimbusds.jose.JWSVerifier; -import com.nimbusds.jose.crypto.RSASSAVerifier; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import org.apache.commons.lang3.StringUtils; -import org.apache.nifi.web.security.InvalidAuthenticationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.ParseException; -import java.util.Date; -import java.util.List; -import java.util.Set; - -/** - * KnoxService is a service for managing the Apache Knox SSO. - */ -public class KnoxService { - - private static final Logger logger = LoggerFactory.getLogger(KnoxService.class); - - private KnoxConfiguration configuration; - private JWSVerifier verifier; - private String knoxUrl; - private Set audiences; - - /** - * Creates a new KnoxService. - * - * @param configuration knox configuration - */ - public KnoxService(final KnoxConfiguration configuration) { - this.configuration = configuration; - - // if knox sso support is enabled, validate the configuration - if (configuration.isKnoxEnabled()) { - // ensure the url is provided - knoxUrl = configuration.getKnoxUrl(); - if (StringUtils.isBlank(knoxUrl)) { - throw new RuntimeException("Knox URL is required when Apache Knox SSO support is enabled."); - } - - // ensure the cookie name is set - if (StringUtils.isBlank(configuration.getKnoxCookieName())) { - throw new RuntimeException("Knox Cookie Name is required when Apache Knox SSO support is enabled."); - } - - // create the verifier - verifier = new RSASSAVerifier(configuration.getKnoxPublicKey()); - - // get the audience - audiences = configuration.getAudiences(); - } - } - - /** - * Returns whether Knox support is enabled. - * - * @return whether Knox support is enabled - */ - public boolean isKnoxEnabled() { - return configuration.isKnoxEnabled(); - } - - /** - * Returns the Knox Url. - * - * @return knox url - */ - public String getKnoxUrl() { - if (!configuration.isKnoxEnabled()) { - throw new IllegalStateException("Apache Knox SSO is not enabled."); - } - - return knoxUrl; - } - - /** - * Extracts the authentication from the token and verify it. - * - * @param jwt signed jwt string - * @return the user authentication - * @throws ParseException if the payload of the jwt doesn't represent a valid json object and a jwt claims set - * @throws JOSEException if the JWS object couldn't be verified - */ - public String getAuthenticationFromToken(final String jwt) throws ParseException, JOSEException { - if (!configuration.isKnoxEnabled()) { - throw new IllegalStateException("Apache Knox SSO is not enabled."); - } - - // attempt to parse the signed jwt - final SignedJWT signedJwt = SignedJWT.parse(jwt); - - // validate the token - if (validateToken(signedJwt)) { - final JWTClaimsSet claimsSet = signedJwt.getJWTClaimsSet(); - if (claimsSet == null) { - logger.info("Claims set is missing from Knox JWT."); - throw new InvalidAuthenticationException("The Knox JWT token is not valid."); - } - - // extract the user identity from the token - return claimsSet.getSubject(); - } else { - throw new InvalidAuthenticationException("The Knox JWT token is not valid."); - } - } - - /** - * Validate the specified jwt. - * - * @param jwtToken knox jwt - * @return whether this jwt is valid - * @throws JOSEException if the jws object couldn't be verified - * @throws ParseException if the payload of the jwt doesn't represent a valid json object and a jwt claims set - */ - private boolean validateToken(final SignedJWT jwtToken) throws JOSEException, ParseException { - final boolean validSignature = validateSignature(jwtToken); - final boolean validAudience = validateAudience(jwtToken); - final boolean notExpired = validateExpiration(jwtToken); - - return validSignature && validAudience && notExpired; - } - - /** - * Validate the jwt signature. - * - * @param jwtToken knox jwt - * @return whether this jwt signature is valid - * @throws JOSEException if the jws object couldn't be verified - */ - private boolean validateSignature(final SignedJWT jwtToken) throws JOSEException { - boolean valid = false; - - // ensure the token is signed - if (JWSObject.State.SIGNED.equals(jwtToken.getState())) { - - // ensure the signature is present - if (jwtToken.getSignature() != null) { - - // verify the token - valid = jwtToken.verify(verifier); - } - } - - if (!valid) { - logger.error("The Knox JWT has an invalid signature."); - } - - return valid; - } - - /** - * Validate the jwt audience. - * - * @param jwtToken knox jwt - * @return whether this jwt audience is valid - * @throws ParseException if the payload of the jwt doesn't represent a valid json object and a jwt claims set - */ - private boolean validateAudience(final SignedJWT jwtToken) throws ParseException { - if (audiences == null) { - return true; - } - - final JWTClaimsSet claimsSet = jwtToken.getJWTClaimsSet(); - if (claimsSet == null) { - logger.error("Claims set is missing from Knox JWT."); - return false; - } - - final List tokenAudiences = claimsSet.getAudience(); - if (tokenAudiences == null) { - logger.error("Audience is missing from the Knox JWT."); - return false; - } - - boolean valid = false; - for (final String tokenAudience : tokenAudiences) { - // ensure one of the audiences is matched - if (audiences.contains(tokenAudience)) { - valid = true; - break; - } - } - - if (!valid) { - logger.error(String.format("The Knox JWT does not have the required audience(s). Required one of [%s]. Present in JWT [%s].", - StringUtils.join(audiences, ", "), StringUtils.join(tokenAudiences, ", "))); - } - - return valid; - } - - /** - * Validate the jwt expiration. - * - * @param jwtToken knox jwt - * @return whether this jwt is not expired - * @throws ParseException if the payload of the jwt doesn't represent a valid json object and a jwt claims set - */ - private boolean validateExpiration(final SignedJWT jwtToken) throws ParseException { - boolean valid = false; - - final JWTClaimsSet claimsSet = jwtToken.getJWTClaimsSet(); - if (claimsSet == null) { - logger.error("Claims set is missing from Knox JWT."); - return false; - } - - final Date now = new Date(); - final Date expiration = claimsSet.getExpirationTime(); - - // the token is not expired if the expiration isn't present or the expiration is after now - if (expiration == null || now.before(expiration)) { - valid = true; - } - - if (!valid) { - logger.error("The Knox JWT is expired."); - } - - return valid; - } -} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxServiceFactoryBean.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxServiceFactoryBean.java deleted file mode 100644 index 9c68be94c4..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/KnoxServiceFactoryBean.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.security.knox; - -import org.apache.nifi.util.NiFiProperties; -import org.springframework.beans.factory.FactoryBean; - -public class KnoxServiceFactoryBean implements FactoryBean { - - private KnoxService knoxService = null; - private NiFiProperties properties = null; - - @Override - public KnoxService getObject() { - if (knoxService == null) { - // ensure we only allow knox if login and oidc are disabled - if (properties.isKnoxSsoEnabled() && (properties.isLoginIdentityProviderEnabled() || properties.isOidcEnabled() || properties.isSamlEnabled())) { - throw new RuntimeException("Apache Knox SSO support cannot be enabled if the Login Identity Provider or OpenId Connect or SAML is configured."); - } - - final KnoxConfiguration configuration = new StandardKnoxConfiguration(properties); - knoxService = new KnoxService(configuration); - } - - return knoxService; - } - - @Override - public Class getObjectType() { - return KnoxService.class; - } - - @Override - public boolean isSingleton() { - return true; - } - - public void setProperties(NiFiProperties properties) { - this.properties = properties; - } - -} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/StandardKnoxConfiguration.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/StandardKnoxConfiguration.java deleted file mode 100644 index 5132843c02..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/knox/StandardKnoxConfiguration.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.security.knox; - -import org.apache.nifi.util.NiFiProperties; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPublicKey; -import java.util.Set; - -public class StandardKnoxConfiguration implements KnoxConfiguration { - - private final NiFiProperties properties; - - public StandardKnoxConfiguration(NiFiProperties properties) { - this.properties = properties; - } - - public boolean isKnoxEnabled() { - return properties.isKnoxSsoEnabled(); - } - - public String getKnoxUrl() { - return properties.getKnoxUrl(); - } - - @Override - public Set getAudiences() { - return properties.getKnoxAudiences(); - } - - public String getKnoxCookieName() { - return properties.getKnoxCookieName(); - } - - public RSAPublicKey getKnoxPublicKey() { - // get the path to the public key - final Path knoxPublicKeyPath = properties.getKnoxPublicKeyPath(); - - // ensure the file exists - if (Files.isRegularFile(knoxPublicKeyPath) && Files.exists(knoxPublicKeyPath)) { - try (final InputStream publicKeyStream = Files.newInputStream(knoxPublicKeyPath)) { - final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - final X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(publicKeyStream); - return (RSAPublicKey) certificate.getPublicKey(); - } catch (final IOException | CertificateException e) { - throw new RuntimeException(e.getMessage(), e); - } - } else { - throw new RuntimeException(String.format("The specified Knox public key path does not exist '%s'", knoxPublicKeyPath.toString())); - } - } -} diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/knox/KnoxAuthenticationFilterTest.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/knox/KnoxAuthenticationFilterTest.java deleted file mode 100644 index 4972f4264d..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/knox/KnoxAuthenticationFilterTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.security.knox; - -import org.apache.nifi.util.NiFiProperties; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class KnoxAuthenticationFilterTest { - - private static final String COOKIE_NAME = "hadoop-jwt"; - - private KnoxAuthenticationFilter knoxAuthenticationFilter; - - @BeforeEach - public void setUp() throws Exception { - final NiFiProperties nifiProperties = Mockito.mock(NiFiProperties.class); - when(nifiProperties.isKnoxSsoEnabled()).thenReturn(true); - when(nifiProperties.getKnoxCookieName()).thenReturn(COOKIE_NAME); - - knoxAuthenticationFilter = new KnoxAuthenticationFilter(); - knoxAuthenticationFilter.setProperties(nifiProperties); - } - - @Test - public void testInsecureHttp() { - final HttpServletRequest request = mock(HttpServletRequest.class); - when(request.isSecure()).thenReturn(false); - assertNull(knoxAuthenticationFilter.attemptAuthentication(request)); - } - - @Test - public void testNullCookies() { - final HttpServletRequest request = mock(HttpServletRequest.class); - when(request.isSecure()).thenReturn(true); - when(request.getCookies()).thenReturn(null); - assertNull(knoxAuthenticationFilter.attemptAuthentication(request)); - } - - @Test - public void testNoCookies() { - final HttpServletRequest request = mock(HttpServletRequest.class); - when(request.isSecure()).thenReturn(true); - when(request.getCookies()).thenReturn(new Cookie[] {}); - assertNull(knoxAuthenticationFilter.attemptAuthentication(request)); - } - - @Test - public void testWrongCookieName() { - final String jwt = "my-jwt"; - - final Cookie knoxCookie = mock(Cookie.class); - when(knoxCookie.getName()).thenReturn("not-hadoop-jwt"); - when(knoxCookie.getValue()).thenReturn(jwt); - - final HttpServletRequest request = mock(HttpServletRequest.class); - when(request.isSecure()).thenReturn(true); - when(request.getCookies()).thenReturn(new Cookie[] {knoxCookie}); - - final KnoxAuthenticationRequestToken authRequest = (KnoxAuthenticationRequestToken) knoxAuthenticationFilter.attemptAuthentication(request); - assertNull(authRequest); - } - - @Test - public void testKnoxCookie() { - final String jwt = "my-jwt"; - - final Cookie knoxCookie = mock(Cookie.class); - when(knoxCookie.getName()).thenReturn(COOKIE_NAME); - when(knoxCookie.getValue()).thenReturn(jwt); - - final HttpServletRequest request = mock(HttpServletRequest.class); - when(request.isSecure()).thenReturn(true); - when(request.getCookies()).thenReturn(new Cookie[] {knoxCookie}); - - final KnoxAuthenticationRequestToken authRequest = (KnoxAuthenticationRequestToken) knoxAuthenticationFilter.attemptAuthentication(request); - assertNotNull(authRequest); - assertEquals(jwt, authRequest.getToken()); - } -} \ No newline at end of file diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/knox/KnoxServiceTest.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/knox/KnoxServiceTest.java deleted file mode 100644 index 0983d0a61f..0000000000 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/knox/KnoxServiceTest.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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.security.knox; - -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.PlainJWT; -import com.nimbusds.oauth2.sdk.auth.JWTAuthenticationClaimsSet; -import com.nimbusds.oauth2.sdk.auth.PrivateKeyJWT; -import com.nimbusds.oauth2.sdk.id.Audience; -import com.nimbusds.oauth2.sdk.id.ClientID; -import com.nimbusds.oauth2.sdk.id.JWTID; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.interfaces.RSAPublicKey; -import java.text.ParseException; -import java.util.Date; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.apache.nifi.web.security.InvalidAuthenticationException; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledOnOs; -import org.junit.jupiter.api.condition.OS; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@DisabledOnOs({OS.WINDOWS}) -public class KnoxServiceTest { - - private static final String AUDIENCE = "https://apache-knox/token"; - private static final String AUDIENCE_2 = "https://apache-knox-2/token"; - - @Test - public void testKnoxSsoNotEnabledGetKnoxUrl() { - final KnoxConfiguration configuration = mock(KnoxConfiguration.class); - when(configuration.isKnoxEnabled()).thenReturn(false); - - final KnoxService service = new KnoxService(configuration); - assertFalse(service.isKnoxEnabled()); - - assertThrows(IllegalStateException.class, service::getKnoxUrl); - } - - @Test - public void testKnoxSsoNotEnabledGetAuthenticatedFromToken() { - final KnoxConfiguration configuration = mock(KnoxConfiguration.class); - when(configuration.isKnoxEnabled()).thenReturn(false); - - final KnoxService service = new KnoxService(configuration); - assertFalse(service.isKnoxEnabled()); - - assertThrows(IllegalStateException.class, () -> service.getAuthenticationFromToken("jwt-token-value")); - } - - private JWTAuthenticationClaimsSet getAuthenticationClaimsSet(final String subject, final String audience, final Date expiration) { - return new JWTAuthenticationClaimsSet( - new ClientID(subject), - new Audience(audience).toSingleAudienceList(), - expiration, - null, - null, - new JWTID()); - } - - @Test - public void testSignedJwt() throws Exception { - final String subject = "user-1"; - final Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(5, TimeUnit.SECONDS)); - - final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); - final KeyPair pair = keyGen.generateKeyPair(); - final RSAPublicKey publicKey = (RSAPublicKey) pair.getPublic(); - - final JWTAuthenticationClaimsSet claimsSet = getAuthenticationClaimsSet(subject, AUDIENCE, expiration); - final PrivateKeyJWT privateKeyJWT = new PrivateKeyJWT(claimsSet, JWSAlgorithm.RS256, pair.getPrivate(), null, null); - - final KnoxConfiguration configuration = getConfiguration(publicKey); - final KnoxService service = new KnoxService(configuration); - - assertEquals(subject, service.getAuthenticationFromToken(privateKeyJWT.getClientAssertion().serialize())); - } - - @Test - public void testBadSignedJwt() throws Exception { - final String subject = "user-1"; - final Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(5, TimeUnit.SECONDS)); - - final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); - - final KeyPair pair1 = keyGen.generateKeyPair(); - final KeyPair pair2 = keyGen.generateKeyPair(); - final RSAPublicKey publicKey2 = (RSAPublicKey) pair2.getPublic(); - - // sign the jwt with pair 1 - final JWTAuthenticationClaimsSet claimsSet = getAuthenticationClaimsSet(subject, AUDIENCE, expiration); - final PrivateKeyJWT privateKeyJWT = new PrivateKeyJWT(claimsSet, JWSAlgorithm.RS256, pair1.getPrivate(), null, null); - - // attempt to verify it with pair 2 - final KnoxConfiguration configuration = getConfiguration(publicKey2); - final KnoxService service = new KnoxService(configuration); - - assertThrows(InvalidAuthenticationException.class, () -> service.getAuthenticationFromToken(privateKeyJWT.getClientAssertion().serialize())); - } - - @Test - public void testPlainJwt() throws Exception { - final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); - final KeyPair pair = keyGen.generateKeyPair(); - final RSAPublicKey publicKey = (RSAPublicKey) pair.getPublic(); - - final Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(5, TimeUnit.SECONDS)); - final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .subject("user-1") - .expirationTime(expiration) - .build(); - - final PlainJWT plainJWT = new PlainJWT(claimsSet); - - final KnoxConfiguration configuration = getConfiguration(publicKey); - final KnoxService service = new KnoxService(configuration); - - assertThrows(ParseException.class, () -> service.getAuthenticationFromToken(plainJWT.serialize())); - } - - @Test - public void testExpiredJwt() throws Exception { - final String subject = "user-1"; - - // token expires in 1 sec - final Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)); - - final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); - final KeyPair pair = keyGen.generateKeyPair(); - final RSAPublicKey publicKey = (RSAPublicKey) pair.getPublic(); - - // wait 2 sec - Thread.sleep(TimeUnit.MILLISECONDS.convert(2, TimeUnit.SECONDS)); - - final JWTAuthenticationClaimsSet claimsSet = getAuthenticationClaimsSet(subject, AUDIENCE, expiration); - final PrivateKeyJWT privateKeyJWT = new PrivateKeyJWT(claimsSet, JWSAlgorithm.RS256, pair.getPrivate(), null, null); - - final KnoxConfiguration configuration = getConfiguration(publicKey); - final KnoxService service = new KnoxService(configuration); - - assertThrows(InvalidAuthenticationException.class, () -> service.getAuthenticationFromToken(privateKeyJWT.getClientAssertion().serialize())); - } - - @Test - public void testRequiredAudience() throws Exception { - final String subject = "user-1"; - final Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(5, TimeUnit.SECONDS)); - - final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); - final KeyPair pair = keyGen.generateKeyPair(); - final RSAPublicKey publicKey = (RSAPublicKey) pair.getPublic(); - - final JWTAuthenticationClaimsSet claimsSet = getAuthenticationClaimsSet(subject, AUDIENCE, expiration); - final PrivateKeyJWT privateKeyJWT = new PrivateKeyJWT(claimsSet, JWSAlgorithm.RS256, pair.getPrivate(), null, null); - - final KnoxConfiguration configuration = getConfiguration(publicKey); - when(configuration.getAudiences()).thenReturn(null); - final KnoxService service = new KnoxService(configuration); - - assertEquals(subject, service.getAuthenticationFromToken(privateKeyJWT.getClientAssertion().serialize())); - } - - @Test - public void testInvalidAudience() throws Exception { - final String subject = "user-1"; - final Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(5, TimeUnit.SECONDS)); - - final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); - final KeyPair pair = keyGen.generateKeyPair(); - final RSAPublicKey publicKey = (RSAPublicKey) pair.getPublic(); - - final JWTAuthenticationClaimsSet claimsSet = getAuthenticationClaimsSet(subject, "incorrect-audience", expiration); - final PrivateKeyJWT privateKeyJWT = new PrivateKeyJWT(claimsSet, JWSAlgorithm.RS256, pair.getPrivate(), null, null); - - final KnoxConfiguration configuration = getConfiguration(publicKey); - final KnoxService service = new KnoxService(configuration); - assertThrows(InvalidAuthenticationException.class, () -> service.getAuthenticationFromToken(privateKeyJWT.getClientAssertion().serialize())); - } - - private KnoxConfiguration getConfiguration(final RSAPublicKey publicKey) { - final KnoxConfiguration configuration = mock(KnoxConfiguration.class); - when(configuration.isKnoxEnabled()).thenReturn(true); - when(configuration.getKnoxUrl()).thenReturn("knox-sso-url"); - when(configuration.getKnoxCookieName()).thenReturn("knox-cookie-name"); - when(configuration.getAudiences()).thenReturn(Stream.of(AUDIENCE, AUDIENCE_2).collect(Collectors.toSet())); - when(configuration.getKnoxPublicKey()).thenReturn(publicKey); - return configuration; - } -} \ No newline at end of file diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LoginFilter.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LoginFilter.java index 2180e19a70..4b95b2fb7c 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LoginFilter.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LoginFilter.java @@ -38,8 +38,6 @@ public class LoginFilter implements Filter { private static final String SAML2_AUTHENTICATE_FILTER_PATH = "/nifi-api/saml2/authenticate/consumer"; - private static final String KNOX_REQUEST_PATH = "/nifi-api/access/knox/request"; - private ServletContext servletContext; @Override @@ -50,16 +48,12 @@ public class LoginFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { final boolean supportsOidc = Boolean.parseBoolean(servletContext.getInitParameter("oidc-supported")); - final boolean supportsKnoxSso = Boolean.parseBoolean(servletContext.getInitParameter("knox-supported")); final boolean supportsSAML = Boolean.parseBoolean(servletContext.getInitParameter("saml-supported")); final HttpServletRequest httpServletRequest = (HttpServletRequest) request; final RequestUriBuilder requestUriBuilder = RequestUriBuilder.fromHttpServletRequest(httpServletRequest); - if (supportsKnoxSso) { - final URI redirectUri = requestUriBuilder.path(KNOX_REQUEST_PATH).build(); - sendRedirect(response, redirectUri); - } else if (supportsOidc) { + if (supportsOidc) { final URI redirectUri = requestUriBuilder.path(OAUTH2_AUTHORIZATION_PATH).build(); // Redirect to authorization URL defined in Spring Security OAuth2AuthorizationRequestRedirectFilter sendRedirect(response, redirectUri); diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LogoutFilter.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LogoutFilter.java index 70e1ab91e1..888b15afb3 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LogoutFilter.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LogoutFilter.java @@ -41,8 +41,6 @@ public class LogoutFilter implements Filter { private static final String SAML_SINGLE_LOGOUT_URL = "/nifi-api/access/saml/single-logout/request"; - private static final String KNOX_LOGOUT_URL = "/nifi-api/access/knox/logout"; - private static final String LOGOUT_COMPLETE_URL = "/nifi-api/access/logout/complete"; private ServletContext servletContext; @@ -55,7 +53,6 @@ public class LogoutFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException { final boolean supportsOidc = Boolean.parseBoolean(servletContext.getInitParameter("oidc-supported")); - final boolean supportsKnoxSso = Boolean.parseBoolean(servletContext.getInitParameter("knox-supported")); final boolean supportsSaml = Boolean.parseBoolean(servletContext.getInitParameter("saml-supported")); final boolean supportsSamlSingleLogout = Boolean.parseBoolean(servletContext.getInitParameter("saml-single-logout-supported")); @@ -68,8 +65,6 @@ public class LogoutFilter implements Filter { if (supportsOidc) { sendRedirect(OIDC_LOGOUT_URL, request, response); - } else if (supportsKnoxSso) { - sendRedirect(KNOX_LOGOUT_URL, request, response); } else if (supportsSaml) { final String logoutUrl = supportsSamlSingleLogout ? SAML_SINGLE_LOGOUT_URL : SAML_LOCAL_LOGOUT_URL; sendRedirect(logoutUrl, request, response); diff --git a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node1/nifi.properties b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node1/nifi.properties index 86dddcdd12..68565a897f 100644 --- a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node1/nifi.properties +++ b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node1/nifi.properties @@ -175,12 +175,6 @@ nifi.security.user.oidc.client.id= nifi.security.user.oidc.client.secret= nifi.security.user.oidc.preferred.jwsalgorithm= -# Apache Knox SSO Properties # -nifi.security.user.knox.url= -nifi.security.user.knox.publicKey= -nifi.security.user.knox.cookieName=hadoop-jwt -nifi.security.user.knox.audiences= - # Identity Mapping Properties # # These properties allow normalizing user identities such that identities coming from different identity providers # (certificates, LDAP, Kerberos) can be treated the same internally in NiFi. The following example demonstrates normalizing diff --git a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node2/nifi.properties b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node2/nifi.properties index 11e379e482..15c1b7c1d1 100644 --- a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node2/nifi.properties +++ b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node2/nifi.properties @@ -175,12 +175,6 @@ nifi.security.user.oidc.client.id= nifi.security.user.oidc.client.secret= nifi.security.user.oidc.preferred.jwsalgorithm= -# Apache Knox SSO Properties # -nifi.security.user.knox.url= -nifi.security.user.knox.publicKey= -nifi.security.user.knox.cookieName=hadoop-jwt -nifi.security.user.knox.audiences= - # Identity Mapping Properties # # These properties allow normalizing user identities such that identities coming from different identity providers # (certificates, LDAP, Kerberos) can be treated the same internally in NiFi. The following example demonstrates normalizing diff --git a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/default/nifi.properties b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/default/nifi.properties index a076776bbb..a1f35a480b 100644 --- a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/default/nifi.properties +++ b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/default/nifi.properties @@ -176,12 +176,6 @@ nifi.security.user.oidc.client.id= nifi.security.user.oidc.client.secret= nifi.security.user.oidc.preferred.jwsalgorithm= -# Apache Knox SSO Properties # -nifi.security.user.knox.url= -nifi.security.user.knox.publicKey= -nifi.security.user.knox.cookieName=hadoop-jwt -nifi.security.user.knox.audiences= - # Identity Mapping Properties # # These properties allow normalizing user identities such that identities coming from different identity providers # (certificates, LDAP, Kerberos) can be treated the same internally in NiFi. The following example demonstrates normalizing diff --git a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/pythonic/nifi.properties b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/pythonic/nifi.properties index 0b05dcdd36..90349020c6 100644 --- a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/pythonic/nifi.properties +++ b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/pythonic/nifi.properties @@ -180,12 +180,6 @@ nifi.security.user.oidc.client.id= nifi.security.user.oidc.client.secret= nifi.security.user.oidc.preferred.jwsalgorithm= -# Apache Knox SSO Properties # -nifi.security.user.knox.url= -nifi.security.user.knox.publicKey= -nifi.security.user.knox.cookieName=hadoop-jwt -nifi.security.user.knox.audiences= - # Identity Mapping Properties # # These properties allow normalizing user identities such that identities coming from different identity providers # (certificates, LDAP, Kerberos) can be treated the same internally in NiFi. The following example demonstrates normalizing