Commit 2df50500 authored by Phillip Webb's avatar Phillip Webb

Merge pull request #25868 from hatefpalizgar

* pr/25868:
  Polish 'Allow remote devtools access with Spring Security'
  Allow remote devtools access with Spring Security

Closes gh-25868
parents c45bb2bd 0699fdcc
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -26,12 +26,14 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore; ...@@ -26,12 +26,14 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.security.ConditionalOnDefaultWebSecurity; import org.springframework.boot.autoconfigure.security.ConditionalOnDefaultWebSecurity;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration; import org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration; import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration; import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.Bean; 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.security.config.Customizer; 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.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
...@@ -46,6 +48,7 @@ import org.springframework.security.web.SecurityFilterChain; ...@@ -46,6 +48,7 @@ import org.springframework.security.web.SecurityFilterChain;
* of the custom security configuration. * of the custom security configuration.
* *
* @author Madhura Bhave * @author Madhura Bhave
* @author Hatef Palizgar
* @since 2.1.0 * @since 2.1.0
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
...@@ -58,6 +61,7 @@ import org.springframework.security.web.SecurityFilterChain; ...@@ -58,6 +61,7 @@ import org.springframework.security.web.SecurityFilterChain;
public class ManagementWebSecurityAutoConfiguration { public class ManagementWebSecurityAutoConfiguration {
@Bean @Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
SecurityFilterChain managementSecurityFilterChain(HttpSecurity http) throws Exception { SecurityFilterChain managementSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests((requests) -> { http.authorizeRequests((requests) -> {
requests.requestMatchers(EndpointRequest.to(HealthEndpoint.class, InfoEndpoint.class)).permitAll(); requests.requestMatchers(EndpointRequest.to(HealthEndpoint.class, InfoEndpoint.class)).permitAll();
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
package org.springframework.boot.actuate.autoconfigure.security.servlet; package org.springframework.boot.actuate.autoconfigure.security.servlet;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
...@@ -27,6 +29,7 @@ import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAu ...@@ -27,6 +29,7 @@ import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAu
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration; import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration; import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
...@@ -35,6 +38,7 @@ import org.springframework.boot.test.context.assertj.AssertableWebApplicationCon ...@@ -35,6 +38,7 @@ import org.springframework.boot.test.context.assertj.AssertableWebApplicationCon
import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean; 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.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockFilterChain; import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
...@@ -45,6 +49,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; ...@@ -45,6 +49,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -53,6 +58,7 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -53,6 +58,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link ManagementWebSecurityAutoConfiguration}. * Tests for {@link ManagementWebSecurityAutoConfiguration}.
* *
* @author Madhura Bhave * @author Madhura Bhave
* @author Hatef Palizgar
*/ */
class ManagementWebSecurityAutoConfigurationTests { class ManagementWebSecurityAutoConfigurationTests {
...@@ -121,7 +127,7 @@ class ManagementWebSecurityAutoConfigurationTests { ...@@ -121,7 +127,7 @@ class ManagementWebSecurityAutoConfigurationTests {
@Test @Test
void backsOffIfSecurityFilterChainBeanIsPresent() { void backsOffIfSecurityFilterChainBeanIsPresent() {
this.contextRunner.withUserConfiguration(TestSecurityFilterChainConfig.class).run((context) -> { this.contextRunner.withUserConfiguration(TestSecurityFilterChainConfig.class).run((context) -> {
assertThat(context.getBeansOfType(SecurityFilterChain.class).size()).isEqualTo(1); assertThat(context.getBeansOfType(SecurityFilterChain.class)).hasSize(1);
assertThat(context.containsBean("testSecurityFilterChain")).isTrue(); assertThat(context.containsBean("testSecurityFilterChain")).isTrue();
}); });
} }
...@@ -146,6 +152,21 @@ class ManagementWebSecurityAutoConfigurationTests { ...@@ -146,6 +152,21 @@ class ManagementWebSecurityAutoConfigurationTests {
.doesNotHaveBean(MANAGEMENT_SECURITY_FILTER_CHAIN_BEAN)); .doesNotHaveBean(MANAGEMENT_SECURITY_FILTER_CHAIN_BEAN));
} }
@Test
void backOffIfRemoteDevToolsSecurityFilterChainIsPresent() {
this.contextRunner.withUserConfiguration(TestRemoteDevToolsSecurityFilterChainConfig.class).run((context) -> {
SecurityFilterChain testSecurityFilterChain = context.getBean("testSecurityFilterChain",
SecurityFilterChain.class);
SecurityFilterChain testRemoteDevToolsSecurityFilterChain = context
.getBean("testRemoteDevToolsSecurityFilterChain", SecurityFilterChain.class);
List<SecurityFilterChain> orderedSecurityFilterChains = context.getBeanProvider(SecurityFilterChain.class)
.orderedStream().collect(Collectors.toList());
assertThat(orderedSecurityFilterChains).containsExactly(testRemoteDevToolsSecurityFilterChain,
testSecurityFilterChain);
assertThat(context).doesNotHaveBean(ManagementWebSecurityAutoConfiguration.class);
});
}
private HttpStatus getResponseStatus(AssertableWebApplicationContext context, String path) private HttpStatus getResponseStatus(AssertableWebApplicationContext context, String path)
throws IOException, javax.servlet.ServletException { throws IOException, javax.servlet.ServletException {
FilterChainProxy filterChainProxy = context.getBean(FilterChainProxy.class); FilterChainProxy filterChainProxy = context.getBean(FilterChainProxy.class);
...@@ -185,4 +206,16 @@ class ManagementWebSecurityAutoConfigurationTests { ...@@ -185,4 +206,16 @@ class ManagementWebSecurityAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false)
static class TestRemoteDevToolsSecurityFilterChainConfig extends TestSecurityFilterChainConfig {
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER - 1)
SecurityFilterChain testRemoteDevToolsSecurityFilterChain(HttpSecurity http) throws Exception {
return http.requestMatcher(new AntPathRequestMatcher("/**")).authorizeRequests().anyRequest().anonymous()
.and().csrf().disable().build();
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment