Commit b0b7bc0e authored by Dave Syer's avatar Dave Syer

Fix tests

Some assumptions were being made in tests, e.g. about
there being an AuthenticationManager @Bean, which were
false with the new Security 3.2.1 updates from Rob.

Also parent-child contexts with the actuator were
problematic because they didn't exclude the web configuration
for the management security in the parent context.

Fixes gh-244
parent 6b0eba37
...@@ -33,6 +33,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; ...@@ -33,6 +33,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.security.AuthenticationManagerConfiguration; import org.springframework.boot.autoconfigure.security.AuthenticationManagerConfiguration;
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.security.SecurityPrequisite; import org.springframework.boot.autoconfigure.security.SecurityPrequisite;
...@@ -43,12 +44,12 @@ import org.springframework.context.annotation.Bean; ...@@ -43,12 +44,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer; import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
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.builders.WebSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer; import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
...@@ -145,10 +146,17 @@ public class ManagementSecurityAutoConfiguration { ...@@ -145,10 +146,17 @@ public class ManagementSecurityAutoConfiguration {
} }
@Configuration
@ConditionalOnExpression("${management.security.enabled:true} && !${security.basic.enabled:true}")
@ConditionalOnMissingBean(WebSecurityConfiguration.class)
@EnableWebSecurity
protected static class WebSecurityEnabler extends AuthenticationManagerConfiguration {
}
@Configuration @Configuration
@ConditionalOnMissingBean({ ManagementWebSecurityConfigurerAdapter.class }) @ConditionalOnMissingBean({ ManagementWebSecurityConfigurerAdapter.class })
@ConditionalOnExpression("${management.security.enabled:true}") @ConditionalOnExpression("${management.security.enabled:true}")
@EnableWebSecurity @ConditionalOnWebApplication
// Give user-supplied filters a chance to be last in line // Give user-supplied filters a chance to be last in line
@Order(Ordered.LOWEST_PRECEDENCE - 10) @Order(Ordered.LOWEST_PRECEDENCE - 10)
protected static class ManagementWebSecurityConfigurerAdapter extends protected static class ManagementWebSecurityConfigurerAdapter extends
...@@ -198,13 +206,6 @@ public class ManagementSecurityAutoConfiguration { ...@@ -198,13 +206,6 @@ public class ManagementSecurityAutoConfiguration {
return entryPoint; return entryPoint;
} }
@Configuration
@ConditionalOnMissingBean(AuthenticationManager.class)
@Order(Ordered.LOWEST_PRECEDENCE - 4)
protected static class ManagementAuthenticationManagerConfiguration extends
AuthenticationManagerConfiguration {
}
} }
private static String[] getEndpointPaths( private static String[] getEndpointPaths(
......
...@@ -98,8 +98,8 @@ public class ManagementSecurityAutoConfigurationTests { ...@@ -98,8 +98,8 @@ public class ManagementSecurityAutoConfigurationTests {
private UserDetails getUser() { private UserDetails getUser() {
ProviderManager manager = this.context.getBean(ProviderManager.class); ProviderManager manager = this.context.getBean(ProviderManager.class);
ProviderManager parent = (ProviderManager) ReflectionTestUtils.getField( ProviderManager parent = (ProviderManager) ReflectionTestUtils.getField(manager,
manager, "parent"); "parent");
DaoAuthenticationProvider provider = (DaoAuthenticationProvider) parent DaoAuthenticationProvider provider = (DaoAuthenticationProvider) parent
.getProviders().get(0); .getProviders().get(0);
UserDetailsService service = (UserDetailsService) ReflectionTestUtils.getField( UserDetailsService service = (UserDetailsService) ReflectionTestUtils.getField(
...@@ -159,7 +159,7 @@ public class ManagementSecurityAutoConfigurationTests { ...@@ -159,7 +159,7 @@ public class ManagementSecurityAutoConfigurationTests {
public void testSecurityPropertiesNotAvailable() throws Exception { public void testSecurityPropertiesNotAvailable() throws Exception {
this.context = new AnnotationConfigWebApplicationContext(); this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext()); this.context.setServletContext(new MockServletContext());
this.context.register(TestConfiguration.class, this.context.register(TestConfiguration.class, SecurityAutoConfiguration.class,
ManagementSecurityAutoConfiguration.class, ManagementSecurityAutoConfiguration.class,
EndpointAutoConfiguration.class, EndpointAutoConfiguration.class,
ManagementServerPropertiesAutoConfiguration.class, ManagementServerPropertiesAutoConfiguration.class,
......
...@@ -19,8 +19,6 @@ package org.springframework.boot.actuate.autoconfigure; ...@@ -19,8 +19,6 @@ package org.springframework.boot.actuate.autoconfigure;
import org.junit.After; import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
...@@ -61,9 +59,8 @@ public class SpringApplicationHierarchyTests { ...@@ -61,9 +59,8 @@ public class SpringApplicationHierarchyTests {
public static class Child { public static class Child {
} }
@EnableAutoConfiguration(exclude = { ServerPropertiesAutoConfiguration.class, @EnableAutoConfiguration(exclude = { JolokiaAutoConfiguration.class,
JolokiaAutoConfiguration.class, EndpointMBeanExportAutoConfiguration.class, EndpointMBeanExportAutoConfiguration.class })
SecurityAutoConfiguration.class })
public static class Parent { public static class Parent {
} }
......
...@@ -25,7 +25,6 @@ import org.apache.commons.logging.LogFactory; ...@@ -25,7 +25,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.security.SecurityProperties.User; import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
...@@ -45,11 +44,12 @@ import org.springframework.security.config.annotation.authentication.configurers ...@@ -45,11 +44,12 @@ import org.springframework.security.config.annotation.authentication.configurers
@Configuration @Configuration
@ConditionalOnBean(ObjectPostProcessor.class) @ConditionalOnBean(ObjectPostProcessor.class)
@ConditionalOnMissingBean(AuthenticationManager.class) @ConditionalOnMissingBean(AuthenticationManager.class)
@ConditionalOnWebApplication
@Order(Ordered.LOWEST_PRECEDENCE - 3) @Order(Ordered.LOWEST_PRECEDENCE - 3)
public class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { public class AuthenticationManagerConfiguration extends
GlobalAuthenticationConfigurerAdapter {
private static Log logger = LogFactory.getLog(AuthenticationManagerConfiguration.class); private static Log logger = LogFactory
.getLog(AuthenticationManagerConfiguration.class);
@Autowired @Autowired
private List<SecurityPrequisite> dependencies; private List<SecurityPrequisite> dependencies;
...@@ -60,14 +60,15 @@ public class AuthenticationManagerConfiguration extends GlobalAuthenticationConf ...@@ -60,14 +60,15 @@ public class AuthenticationManagerConfiguration extends GlobalAuthenticationConf
@Autowired @Autowired
private SecurityProperties security; private SecurityProperties security;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception { public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.apply(new BootDefaultingAuthenticationConfigurerAdapter()); auth.apply(new BootDefaultingAuthenticationConfigurerAdapter());
} }
/** /**
* We must add {@link BootDefaultingAuthenticationConfigurerAdapter} in the * We must add {@link BootDefaultingAuthenticationConfigurerAdapter} in the init phase
* init phase of the last {@link GlobalAuthenticationConfigurerAdapter}. The * of the last {@link GlobalAuthenticationConfigurerAdapter}. The reason is that the
* reason is that the typical flow is something like: * typical flow is something like:
* *
* <ul> * <ul>
* <li>A * <li>A
...@@ -75,26 +76,25 @@ public class AuthenticationManagerConfiguration extends GlobalAuthenticationConf ...@@ -75,26 +76,25 @@ public class AuthenticationManagerConfiguration extends GlobalAuthenticationConf
* exists that adds a {@link SecurityConfigurer} to the * exists that adds a {@link SecurityConfigurer} to the
* {@link AuthenticationManagerBuilder}</li> * {@link AuthenticationManagerBuilder}</li>
* <li> * <li>
* {@link AuthenticationManagerConfiguration#init(AuthenticationManagerBuilder)} * {@link AuthenticationManagerConfiguration#init(AuthenticationManagerBuilder)} adds
* adds BootDefaultingAuthenticationConfigurerAdapter so it is after the * BootDefaultingAuthenticationConfigurerAdapter so it is after the
* {@link SecurityConfigurer} in the first step</li> * {@link SecurityConfigurer} in the first step</li>
* <li>We then can default an {@link AuthenticationProvider} if necessary. * <li>We then can default an {@link AuthenticationProvider} if necessary. Note we can
* Note we can only invoke the * only invoke the
* {@link AuthenticationManagerBuilder#authenticationProvider(AuthenticationProvider)} * {@link AuthenticationManagerBuilder#authenticationProvider(AuthenticationProvider)}
* method since all other methods add a {@link SecurityConfigurer} which is * method since all other methods add a {@link SecurityConfigurer} which is not
* not allowed in the configure stage. It is not allowed because we * allowed in the configure stage. It is not allowed because we guarantee all init
* guarantee all init methods are invoked before configure, which cannot be * methods are invoked before configure, which cannot be guaranteed at this point.</li>
* guaranteed at this point.</li>
* </ul> * </ul>
* *
* @author Rob Winch * @author Rob Winch
*/ */
private class BootDefaultingAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { private class BootDefaultingAuthenticationConfigurerAdapter extends
GlobalAuthenticationConfigurerAdapter {
@Override @Override
public void configure(AuthenticationManagerBuilder auth) public void configure(AuthenticationManagerBuilder auth) throws Exception {
throws Exception { if (auth.isConfigured()) {
if(auth.isConfigured()) {
return; return;
} }
...@@ -104,18 +104,14 @@ public class AuthenticationManagerConfiguration extends GlobalAuthenticationConf ...@@ -104,18 +104,14 @@ public class AuthenticationManagerConfiguration extends GlobalAuthenticationConf
+ user.getPassword() + "\n\n"); + user.getPassword() + "\n\n");
} }
AuthenticationManagerBuilder defaultAuth = new AuthenticationManagerBuilder(objectPostProcessor); AuthenticationManagerBuilder defaultAuth = new AuthenticationManagerBuilder(
AuthenticationManagerConfiguration.this.objectPostProcessor);
Set<String> roles = new LinkedHashSet<String>(user.getRole()); Set<String> roles = new LinkedHashSet<String>(user.getRole());
AuthenticationManager parent = defaultAuth. AuthenticationManager parent = defaultAuth.inMemoryAuthentication()
inMemoryAuthentication() .withUser(user.getName()).password(user.getPassword())
.withUser(user.getName()) .roles(roles.toArray(new String[roles.size()])).and().and().build();
.password(user.getPassword())
.roles(roles.toArray(new String[roles.size()]))
.and()
.and()
.build();
auth.parentAuthenticationManager(parent); auth.parentAuthenticationManager(parent);
} }
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package sample.secure; package sample.secure;
import static org.junit.Assert.assertEquals;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -28,6 +30,7 @@ import org.springframework.context.annotation.PropertySource; ...@@ -28,6 +30,7 @@ import org.springframework.context.annotation.PropertySource;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
...@@ -35,8 +38,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; ...@@ -35,8 +38,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import sample.secure.SampleSecureApplicationTests.TestConfiguration; import sample.secure.SampleSecureApplicationTests.TestConfiguration;
import static org.junit.Assert.assertEquals;
/** /**
* Basic integration tests for demo application. * Basic integration tests for demo application.
* *
...@@ -58,7 +59,7 @@ public class SampleSecureApplicationTests { ...@@ -58,7 +59,7 @@ public class SampleSecureApplicationTests {
@Before @Before
public void init() { public void init() {
AuthenticationManager authenticationManager = context AuthenticationManager authenticationManager = context
.getBean(AuthenticationManager.class); .getBean(AuthenticationManagerBuilder.class).getOrBuild();
authentication = authenticationManager authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); .authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
} }
...@@ -94,7 +95,6 @@ public class SampleSecureApplicationTests { ...@@ -94,7 +95,6 @@ public class SampleSecureApplicationTests {
@PropertySource("classpath:test.properties") @PropertySource("classpath:test.properties")
@Configuration @Configuration
protected static class TestConfiguration { protected static class TestConfiguration {
} }
} }
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