This is an automated email from the ASF dual-hosted git repository.

exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 67ba13796e NIFI-12150 Restored NiFiRegistrySecurityConfig required for 
Registry
67ba13796e is described below

commit 67ba13796e3d34b43daec25a28f93febabd88aec
Author: Joseph Witt <joew...@apache.org>
AuthorDate: Fri Sep 29 09:17:15 2023 -0700

    NIFI-12150 Restored NiFiRegistrySecurityConfig required for Registry
    
    - NiFiRegistrySecurityConfig was removed mistakenly in NIFI-12147 and 
updating extractor to match changes in NIFI-12147 for DN extraction
    
    This closes #7815
    
    Signed-off-by: David Handermann <exceptionfact...@apache.org>
---
 .../web/security/NiFiRegistrySecurityConfig.java   | 155 +++++++++++++++++++++
 .../x509/SubjectDnX509PrincipalExtractor.java      |  35 +++++
 2 files changed, 190 insertions(+)

diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java
new file mode 100644
index 0000000000..cfcc8a3a6c
--- /dev/null
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java
@@ -0,0 +1,155 @@
+/*
+ * 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.registry.web.security;
+
+import org.apache.nifi.registry.security.authorization.Authorizer;
+import org.apache.nifi.registry.security.authorization.resource.ResourceType;
+import org.apache.nifi.registry.security.identity.IdentityMapper;
+import org.apache.nifi.registry.service.AuthorizationService;
+import 
org.apache.nifi.registry.web.security.authentication.AnonymousIdentityFilter;
+import 
org.apache.nifi.registry.web.security.authentication.IdentityAuthenticationProvider;
+import org.apache.nifi.registry.web.security.authentication.IdentityFilter;
+import 
org.apache.nifi.registry.web.security.authentication.jwt.JwtIdentityProvider;
+import 
org.apache.nifi.registry.web.security.authentication.x509.X509IdentityAuthenticationProvider;
+import 
org.apache.nifi.registry.web.security.authentication.x509.X509IdentityProvider;
+import 
org.apache.nifi.registry.web.security.authorization.ResourceAuthorizationFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+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;
+import org.springframework.security.authentication.ProviderManager;
+import 
org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import 
org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import 
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.SecurityFilterChain;
+import 
org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
+import 
org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Spring Security Filter Configuration
+ */
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class NiFiRegistrySecurityConfig {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(NiFiRegistrySecurityConfig.class);
+
+    @Autowired
+    private IdentityMapper identityMapper;
+
+    @Autowired
+    private AuthorizationService authorizationService;
+
+    @Autowired
+    private Authorizer authorizer;
+
+    @Autowired
+    private X509IdentityProvider x509IdentityProvider;
+
+    @Autowired
+    private JwtIdentityProvider jwtIdentityProvider;
+
+    @Bean
+    public SecurityFilterChain securityFilterChain(final HttpSecurity http) 
throws Exception {
+        return http
+                .addFilterBefore(x509AuthenticationFilter(), 
AnonymousAuthenticationFilter.class)
+                .addFilterBefore(jwtAuthenticationFilter(), 
AnonymousAuthenticationFilter.class)
+                // Add Resource Authorization after Spring Security but before 
Jersey Resources
+                .addFilterAfter(resourceAuthorizationFilter(), 
FilterSecurityInterceptor.class)
+                .anonymous().authenticationFilter(new 
AnonymousIdentityFilter()).and()
+                .csrf().disable()
+                .logout().disable()
+                .rememberMe().disable()
+                .requestCache().disable()
+                .servletApi().disable()
+                .securityContext().disable()
+                .sessionManagement().disable()
+                .headers()
+                    .xssProtection().and()
+                    .contentSecurityPolicy("frame-ancestors 'self'").and()
+                    
.httpStrictTransportSecurity().maxAgeInSeconds(31540000).and()
+                    .frameOptions().sameOrigin().and()
+                .authorizeRequests()
+                    .antMatchers(
+                            "/access/token",
+                            "/access/token/identity-provider",
+                            "/access/token/kerberos",
+                            "/access/oidc/callback",
+                            "/access/oidc/exchange",
+                            "/access/oidc/request"
+                    ).permitAll()
+                    .anyRequest().fullyAuthenticated()
+                    .and()
+                .exceptionHandling()
+                    
.authenticationEntryPoint(http401AuthenticationEntryPoint()).and()
+                .build();
+    }
+
+    @Bean
+    public AuthenticationManager authenticationManager() {
+        return new ProviderManager(x509AuthenticationProvider(), 
jwtAuthenticationProvider());
+    }
+
+    private IdentityFilter x509AuthenticationFilter() {
+        return new IdentityFilter(x509IdentityProvider);
+    }
+
+    private IdentityAuthenticationProvider x509AuthenticationProvider() {
+        return new X509IdentityAuthenticationProvider(authorizer, 
x509IdentityProvider, identityMapper);
+    }
+
+    private IdentityFilter jwtAuthenticationFilter() {
+        return new IdentityFilter(jwtIdentityProvider);
+    }
+
+    private IdentityAuthenticationProvider jwtAuthenticationProvider() {
+        return new IdentityAuthenticationProvider(authorizer, 
jwtIdentityProvider, identityMapper);
+    }
+
+    private ResourceAuthorizationFilter resourceAuthorizationFilter() {
+        return ResourceAuthorizationFilter.builder()
+                    .setAuthorizationService(authorizationService)
+                    .addResourceType(ResourceType.Actuator)
+                    .addResourceType(ResourceType.Swagger)
+                    .build();
+    }
+
+    private AuthenticationEntryPoint http401AuthenticationEntryPoint() {
+        // This gets used for both secured and unsecured configurations. It 
will be called by Spring Security if a request makes it through the filter 
chain without being authenticated.
+        // For unsecured, this should never be reached because the custom 
AnonymousAuthenticationFilter should always populate a fully-authenticated 
anonymous user
+        // For secured, this will cause attempt to access any API endpoint 
(except those explicitly ignored) without providing credentials to return a 401 
Unauthorized challenge
+        return (request, response, authenticationException) -> {
+
+            // return a 401 response
+            final int status = HttpServletResponse.SC_UNAUTHORIZED;
+            logger.info("Client could not be authenticated due to: {} 
Returning 401 response.", authenticationException.toString());
+            logger.debug("", authenticationException);
+
+            if (!response.isCommitted()) {
+                response.setStatus(status);
+                response.setContentType("text/plain");
+                response.getWriter().println(String.format("%s Contact the 
system administrator.", authenticationException.getLocalizedMessage()));
+            }
+        };
+    }
+}
diff --git 
a/nifi-registry/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/SubjectDnX509PrincipalExtractor.java
 
b/nifi-registry/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/SubjectDnX509PrincipalExtractor.java
new file mode 100644
index 0000000000..69cb62695a
--- /dev/null
+++ 
b/nifi-registry/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/x509/SubjectDnX509PrincipalExtractor.java
@@ -0,0 +1,35 @@
+/*
+ * 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.registry.web.security.authentication.x509;
+
+import 
org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
+import org.springframework.stereotype.Component;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * Principal extractor for extracting a DN.
+ */
+@Component
+public class SubjectDnX509PrincipalExtractor implements X509PrincipalExtractor 
{
+
+    @Override
+    public Object extractPrincipal(X509Certificate cert) {
+        return cert.getSubjectX500Principal().getName().trim();
+    }
+
+}

Reply via email to