From 553d2cec57339671eabd5ee03e56546b6b3589e3 Mon Sep 17 00:00:00 2001 From: Jason Koch Date: Thu, 9 May 2024 18:41:51 -0700 Subject: [PATCH] feat: add support to disable spring security web filters (#279) --- .../eclipse/jifa/server/Configuration.java | 7 +++ .../configurer/SecurityCryptoConfigurer.java | 59 +++++++++++++++++++ ...rer.java => SecurityFilterConfigurer.java} | 38 +----------- site/docs/guide/configuration.md | 8 +++ 4 files changed, 77 insertions(+), 35 deletions(-) create mode 100644 server/src/main/java/org/eclipse/jifa/server/configurer/SecurityCryptoConfigurer.java rename server/src/main/java/org/eclipse/jifa/server/configurer/{SecurityConfigurer.java => SecurityFilterConfigurer.java} (85%) diff --git a/server/src/main/java/org/eclipse/jifa/server/Configuration.java b/server/src/main/java/org/eclipse/jifa/server/Configuration.java index be337454..2e4621bf 100644 --- a/server/src/main/java/org/eclipse/jifa/server/Configuration.java +++ b/server/src/main/java/org/eclipse/jifa/server/Configuration.java @@ -166,6 +166,13 @@ public class Configuration { */ private Set disabledFileTransferMethods = Collections.emptySet(); + /** + * Install the web security filters. Default is true. + * + * Use this to allow integration with custom security filters. + */ + private boolean securityFiltersEnabled = true; + @PostConstruct private void init() { if (role == Role.MASTER) { diff --git a/server/src/main/java/org/eclipse/jifa/server/configurer/SecurityCryptoConfigurer.java b/server/src/main/java/org/eclipse/jifa/server/configurer/SecurityCryptoConfigurer.java new file mode 100644 index 00000000..e4b3f8a4 --- /dev/null +++ b/server/src/main/java/org/eclipse/jifa/server/configurer/SecurityCryptoConfigurer.java @@ -0,0 +1,59 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ +package org.eclipse.jifa.server.configurer; + +import com.nimbusds.jose.jwk.JWKSet; +import com.nimbusds.jose.jwk.RSAKey; +import com.nimbusds.jose.jwk.source.ImmutableJWKSet; +import org.eclipse.jifa.server.ConfigurationAccessor; +import org.eclipse.jifa.server.service.CipherService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.jwt.JwtDecoder; +import org.springframework.security.oauth2.jwt.JwtEncoder; +import org.springframework.security.oauth2.jwt.JwtTimestampValidator; +import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; +import org.springframework.security.oauth2.jwt.NimbusJwtEncoder; +import java.time.Duration; + +import static org.eclipse.jifa.server.enums.Role.MASTER; +import static org.eclipse.jifa.server.enums.Role.STANDALONE_WORKER; + +@Configuration +public class SecurityCryptoConfigurer extends ConfigurationAccessor { + + @Bean + public JwtEncoder jwtEncoder(CipherService cipherService) { + RSAKey jwk = new RSAKey.Builder(cipherService.getPublicKey()).privateKey(cipherService.getPrivateKey()).build(); + return new NimbusJwtEncoder(new ImmutableJWKSet<>(new JWKSet(jwk))); + } + + @Bean + @Primary + public JwtDecoder jwtDecoder(CipherService cipherService) { + NimbusJwtDecoder decoder = NimbusJwtDecoder.withPublicKey(cipherService.getPublicKey()).build(); + + if (getRole() == MASTER || getRole() == STANDALONE_WORKER) { + decoder.setJwtValidator(new JwtTimestampValidator(Duration.ZERO)); + } + return decoder; + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/server/src/main/java/org/eclipse/jifa/server/configurer/SecurityConfigurer.java b/server/src/main/java/org/eclipse/jifa/server/configurer/SecurityFilterConfigurer.java similarity index 85% rename from server/src/main/java/org/eclipse/jifa/server/configurer/SecurityConfigurer.java rename to server/src/main/java/org/eclipse/jifa/server/configurer/SecurityFilterConfigurer.java index bdb63d19..f824121a 100644 --- a/server/src/main/java/org/eclipse/jifa/server/configurer/SecurityConfigurer.java +++ b/server/src/main/java/org/eclipse/jifa/server/configurer/SecurityFilterConfigurer.java @@ -12,9 +12,6 @@ ********************************************************************************/ package org.eclipse.jifa.server.configurer; -import com.nimbusds.jose.jwk.JWKSet; -import com.nimbusds.jose.jwk.RSAKey; -import com.nimbusds.jose.jwk.source.ImmutableJWKSet; import jakarta.annotation.Nullable; import jakarta.servlet.Filter; import jakarta.servlet.http.Cookie; @@ -22,9 +19,9 @@ import org.eclipse.jifa.server.Constant; import org.eclipse.jifa.server.condition.ConditionalOnRole; import org.eclipse.jifa.server.filter.JwtTokenRefreshFilter; -import org.eclipse.jifa.server.service.CipherService; import org.eclipse.jifa.server.service.JwtService; import org.eclipse.jifa.server.service.UserService; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; @@ -39,14 +36,7 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; -import org.springframework.security.oauth2.jwt.JwtDecoder; -import org.springframework.security.oauth2.jwt.JwtEncoder; -import org.springframework.security.oauth2.jwt.JwtTimestampValidator; -import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; -import org.springframework.security.oauth2.jwt.NimbusJwtEncoder; import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint; import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver; import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler; @@ -56,8 +46,6 @@ import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import java.time.Duration; - import static org.eclipse.jifa.server.Constant.COOKIE_JIFA_TOKEN_KEY; import static org.eclipse.jifa.server.Constant.HTTP_API_PREFIX; import static org.eclipse.jifa.server.Constant.HTTP_HANDSHAKE_MAPPING; @@ -70,23 +58,8 @@ @Configuration @EnableWebSecurity @EnableMethodSecurity -public class SecurityConfigurer extends ConfigurationAccessor { - - @Bean - public JwtEncoder jwtEncoder(CipherService cipherService) { - RSAKey jwk = new RSAKey.Builder(cipherService.getPublicKey()).privateKey(cipherService.getPrivateKey()).build(); - return new NimbusJwtEncoder(new ImmutableJWKSet<>(new JWKSet(jwk))); - } - - @Bean - public JwtDecoder jwtDecoder(CipherService cipherService) { - NimbusJwtDecoder decoder = NimbusJwtDecoder.withPublicKey(cipherService.getPublicKey()).build(); - - if (getRole() == MASTER || getRole() == STANDALONE_WORKER) { - decoder.setJwtValidator(new JwtTimestampValidator(Duration.ZERO)); - } - return decoder; - } +@ConditionalOnProperty(value = "jifa.security-filters-enabled", havingValue = "true", matchIfMissing = true) +public class SecurityFilterConfigurer extends ConfigurationAccessor { @Bean public SecurityFilterChain configure(HttpSecurity hs, UserService userService, JwtService jwtService, @@ -178,11 +151,6 @@ public FilterRegistrationBean refreshJwtTokenFilter(JwtService jwtServic return frb; } - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - @Bean CorsConfigurationSource corsConfigurationSource() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); diff --git a/site/docs/guide/configuration.md b/site/docs/guide/configuration.md index bb7aca99..b9d00c08 100644 --- a/site/docs/guide/configuration.md +++ b/site/docs/guide/configuration.md @@ -171,6 +171,14 @@ Type: String Default: password +## security-filters-enabled + +Whether to enable the default security filters for web authentication. If set to 'false', the web security filters will not be enabled. + +Use this option if you intend to customize JIFA with an alternative authentication and authorization layer. + +Default: true + ## input-files Local files to be analyzed, used only in `STANDALONE_WORKER` role.