Unifies security configurations (#2448)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-06-12 09:06:50 +03:00
committed by GitHub
parent 4cfd90b745
commit 2098dc6223
4 changed files with 19 additions and 26 deletions

View File

@@ -33,6 +33,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
@@ -46,8 +47,8 @@ import org.springframework.security.web.access.intercept.AuthorizationFilter;
@Configuration @Configuration
class ControllerDownloadSecurityConfiguration { class ControllerDownloadSecurityConfiguration {
private static final String DDI_DL_ANT_MATCHER = DdiRestConstants.BASE_V1_REQUEST_MAPPING + private static final String DDI_DL_ANT_MATCHER =
"/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/*"; DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/*";
private final ControllerManagement controllerManagement; private final ControllerManagement controllerManagement;
private final TenantConfigurationManagement tenantConfigurationManagement; private final TenantConfigurationManagement tenantConfigurationManagement;
@@ -73,16 +74,15 @@ class ControllerDownloadSecurityConfiguration {
* Filter to protect the hawkBit server DDI download interface against too many requests. * Filter to protect the hawkBit server DDI download interface against too many requests.
* *
* @param securityProperties for filter configuration * @param securityProperties for filter configuration
* @return the spring filter registration bean for registering a denial of service protection filter in the filter chain * @return the spring filter registration bean for registering a denial-of-service protection filter in the filter chain
*/ */
@Bean @Bean
@ConditionalOnProperty(prefix = "hawkbit.server.security.dos.filter", name = "enabled", matchIfMissing = true) @ConditionalOnProperty(prefix = "hawkbit.server.security.dos.filter", name = "enabled", matchIfMissing = true)
public FilterRegistrationBean<DosFilter> dosFilterDDIDL(final HawkbitSecurityProperties securityProperties) { public FilterRegistrationBean<DosFilter> dosFilterDDIDL(final HawkbitSecurityProperties securityProperties) {
final FilterRegistrationBean<DosFilter> filterRegBean = SecurityManagedConfiguration.dosFilter(List.of(DDI_DL_ANT_MATCHER), final FilterRegistrationBean<DosFilter> filterRegBean = SecurityManagedConfiguration.dosFilter(
securityProperties.getDos().getFilter(), securityProperties.getClients()); List.of(DDI_DL_ANT_MATCHER), securityProperties.getDos().getFilter(), securityProperties.getClients());
filterRegBean.setOrder(SecurityManagedConfiguration.DOS_FILTER_ORDER); filterRegBean.setOrder(SecurityManagedConfiguration.DOS_FILTER_ORDER);
filterRegBean.setName("dosDDiDlFilter"); filterRegBean.setName("dosDDiDlFilter");
return filterRegBean; return filterRegBean;
} }
@@ -91,15 +91,9 @@ class ControllerDownloadSecurityConfiguration {
protected SecurityFilterChain filterChainDDIDL(final HttpSecurity http) throws Exception { protected SecurityFilterChain filterChainDDIDL(final HttpSecurity http) throws Exception {
http http
.securityMatcher(DDI_DL_ANT_MATCHER) .securityMatcher(DDI_DL_ANT_MATCHER)
.csrf(AbstractHttpConfigurer::disable);
if (securityProperties.isRequireSsl()) {
http.requiresChannel(crmRegistry -> crmRegistry.anyRequest().requiresSecure());
}
http
.authorizeHttpRequests(amrmRegistry -> amrmRegistry.anyRequest().authenticated()) .authorizeHttpRequests(amrmRegistry -> amrmRegistry.anyRequest().authenticated())
.anonymous(AbstractHttpConfigurer::disable) .anonymous(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(new AuthenticationFilters.SecurityHeaderAuthenticationFilter( .addFilterBefore(new AuthenticationFilters.SecurityHeaderAuthenticationFilter(
new SecurityHeaderAuthenticator( new SecurityHeaderAuthenticator(
tenantConfigurationManagement, tenantAware, systemSecurityContext, tenantConfigurationManagement, tenantAware, systemSecurityContext,
@@ -118,6 +112,10 @@ class ControllerDownloadSecurityConfiguration {
(request, response, authException) -> response.setStatus(HttpStatus.UNAUTHORIZED.value()))) (request, response, authException) -> response.setStatus(HttpStatus.UNAUTHORIZED.value())))
.sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); .sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
if (securityProperties.isRequireSsl()) {
http.redirectToHttps(Customizer.withDefaults());
}
MdcHandler.Filter.addMdcFilter(http); MdcHandler.Filter.addMdcFilter(http);
return http.build(); return http.build();

View File

@@ -97,11 +97,9 @@ class ControllerSecurityConfiguration {
@Value("${hawkbit.server.security.cors.disable-for-ddi-api:false}") final boolean disableCorsForDdiApi) throws Exception { @Value("${hawkbit.server.security.cors.disable-for-ddi-api:false}") final boolean disableCorsForDdiApi) throws Exception {
http http
.securityMatcher(DDI_ANT_MATCHERS) .securityMatcher(DDI_ANT_MATCHERS)
.csrf(AbstractHttpConfigurer::disable);
http
.authorizeHttpRequests(amrmRegistry -> amrmRegistry.anyRequest().authenticated()) .authorizeHttpRequests(amrmRegistry -> amrmRegistry.anyRequest().authenticated())
.anonymous(AbstractHttpConfigurer::disable) .anonymous(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(new AuthenticationFilters.SecurityHeaderAuthenticationFilter( .addFilterBefore(new AuthenticationFilters.SecurityHeaderAuthenticationFilter(
new SecurityHeaderAuthenticator( new SecurityHeaderAuthenticator(
tenantConfigurationManagement, tenantAware, tenantConfigurationManagement, tenantAware,

View File

@@ -122,9 +122,6 @@ public class MgmtSecurityConfiguration {
.authenticated()) .authenticated())
.anonymous(AbstractHttpConfigurer::disable) .anonymous(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable)
.requestCache(AbstractHttpConfigurer::disable)
.exceptionHandling(Customizer.withDefaults())
.sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterAfter( .addFilterAfter(
// Servlet filter to create metadata after successful authentication over RESTful. // Servlet filter to create metadata after successful authentication over RESTful.
(request, response, chain) -> { (request, response, chain) -> {
@@ -134,7 +131,10 @@ public class MgmtSecurityConfiguration {
} }
chain.doFilter(request, response); chain.doFilter(request, response);
}, },
SessionManagementFilter.class); SessionManagementFilter.class)
.requestCache(AbstractHttpConfigurer::disable)
.exceptionHandling(Customizer.withDefaults())
.sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
if (securityProperties.getCors().isEnabled()) { if (securityProperties.getCors().isEnabled()) {
http.cors(configurer -> configurer.configurationSource(securityProperties.getCors().toCorsConfigurationSource())); http.cors(configurer -> configurer.configurationSource(securityProperties.getCors().toCorsConfigurationSource()));

View File

@@ -22,19 +22,17 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer; import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@EnableWebSecurity @EnableWebSecurity
@Configuration @Configuration
@EnableConfigurationProperties({ OidcClientProperties.class }) @EnableConfigurationProperties(OidcClientProperties.class)
public class SecurityConfiguration extends VaadinWebSecurity { public class SecurityConfiguration extends VaadinWebSecurity {
private Customizer<OAuth2LoginConfigurer<HttpSecurity>> oAuth2LoginConfigurerCustomizer; private Customizer<OAuth2LoginConfigurer<HttpSecurity>> oAuth2LoginConfigurerCustomizer;
@Autowired(required = false) @Autowired(required = false)
public void setOAuth2LoginConfigurerCustomizer( public void setOAuth2LoginConfigurerCustomizer(
@Qualifier("hawkbitOAuth2ClientCustomizer") final Customizer<OAuth2LoginConfigurer<HttpSecurity>> oauth2LoginConfigurerCustomizer @Qualifier("hawkbitOAuth2ClientCustomizer") final Customizer<OAuth2LoginConfigurer<HttpSecurity>> oauth2LoginConfigurerCustomizer) {
) {
this.oAuth2LoginConfigurerCustomizer = oauth2LoginConfigurerCustomizer; this.oAuth2LoginConfigurerCustomizer = oauth2LoginConfigurerCustomizer;
} }
@@ -45,8 +43,7 @@ public class SecurityConfiguration extends VaadinWebSecurity {
@Override @Override
protected void configure(final HttpSecurity http) throws Exception { protected void configure(final HttpSecurity http) throws Exception {
http.authorizeHttpRequests( http.authorizeHttpRequests(authorize -> authorize.requestMatchers("/images/*.png").permitAll());
authorize -> authorize.requestMatchers(new AntPathRequestMatcher("/images/*.png")).permitAll());
super.configure(http); super.configure(http);