Extract actuator security into separate classes
So spring-security + a web app is secure by default (you don't need the actuator).
This commit is contained in:
parent
285dd5b270
commit
bd26b28aa5
|
|
@ -44,8 +44,7 @@ import org.crsh.vfs.spi.AbstractFSDriver;
|
||||||
import org.crsh.vfs.spi.FSDriver;
|
import org.crsh.vfs.spi.FSDriver;
|
||||||
import org.springframework.beans.factory.ListableBeanFactory;
|
import org.springframework.beans.factory.ListableBeanFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties;
|
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties.Management;
|
|
||||||
import org.springframework.boot.actuate.properties.ShellProperties;
|
import org.springframework.boot.actuate.properties.ShellProperties;
|
||||||
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellAuthenticationProperties;
|
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellAuthenticationProperties;
|
||||||
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellProperties;
|
import org.springframework.boot.actuate.properties.ShellProperties.CrshShellProperties;
|
||||||
|
|
@ -96,8 +95,9 @@ import org.springframework.util.StringUtils;
|
||||||
* Security. This authentication method will get enabled if <code>shell.auth</code> is set
|
* Security. This authentication method will get enabled if <code>shell.auth</code> is set
|
||||||
* to <code>spring</code> or if no explicit <code>shell.auth</code> is provided and a
|
* to <code>spring</code> or if no explicit <code>shell.auth</code> is provided and a
|
||||||
* {@link AuthenticationManager} is available. In the latter case shell access will be
|
* {@link AuthenticationManager} is available. In the latter case shell access will be
|
||||||
* restricted to users having roles that match those configured in {@link Management}.
|
* restricted to users having roles that match those configured in
|
||||||
* Required roles can be overridden by <code>shell.auth.spring.roles</code>.
|
* {@link ManagementServerProperties}. Required roles can be overridden by
|
||||||
|
* <code>shell.auth.spring.roles</code>.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* To add customizations to the shell simply define beans of type {@link CRaSHPlugin} in
|
* To add customizations to the shell simply define beans of type {@link CRaSHPlugin} in
|
||||||
|
|
@ -119,7 +119,7 @@ import org.springframework.util.StringUtils;
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass({ PluginLifeCycle.class })
|
@ConditionalOnClass({ PluginLifeCycle.class })
|
||||||
@EnableConfigurationProperties({ ShellProperties.class })
|
@EnableConfigurationProperties({ ShellProperties.class })
|
||||||
@AutoConfigureAfter(SecurityAutoConfiguration.class)
|
@AutoConfigureAfter(ManagementSecurityAutoConfiguration.class)
|
||||||
public class CrshAutoConfiguration {
|
public class CrshAutoConfiguration {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
@ -170,7 +170,7 @@ public class CrshAutoConfiguration {
|
||||||
public static class AuthenticationManagerAdapterAutoConfiguration {
|
public static class AuthenticationManagerAdapterAutoConfiguration {
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private SecurityProperties securityProperties;
|
private ManagementServerProperties management;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public CRaSHPlugin<?> shellAuthenticationManager() {
|
public CRaSHPlugin<?> shellAuthenticationManager() {
|
||||||
|
|
@ -184,9 +184,9 @@ public class CrshAutoConfiguration {
|
||||||
// In case no shell.auth property is provided fall back to Spring Security
|
// In case no shell.auth property is provided fall back to Spring Security
|
||||||
// based authentication and get role to access shell from SecurityProperties.
|
// based authentication and get role to access shell from SecurityProperties.
|
||||||
SpringAuthenticationProperties authenticationProperties = new SpringAuthenticationProperties();
|
SpringAuthenticationProperties authenticationProperties = new SpringAuthenticationProperties();
|
||||||
if (this.securityProperties != null) {
|
if (this.management != null) {
|
||||||
authenticationProperties.setRoles(new String[] { this.securityProperties
|
authenticationProperties.setRoles(new String[] { this.management
|
||||||
.getManagement().getRole() });
|
.getSecurity().getRole() });
|
||||||
}
|
}
|
||||||
return authenticationProperties;
|
return authenticationProperties;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.event.ContextClosedEvent;
|
import org.springframework.context.event.ContextClosedEvent;
|
||||||
import org.springframework.context.event.ContextRefreshedEvent;
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
|
|
||||||
|
|
@ -182,7 +181,7 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||||
if (DISABLED_PORT.equals(managementServerProperties.getPort())) {
|
if (DISABLED_PORT.equals(managementServerProperties.getPort())) {
|
||||||
return DISABLE;
|
return DISABLE;
|
||||||
}
|
}
|
||||||
if (!(beanFactory instanceof GenericWebApplicationContext)) {
|
if (!(beanFactory instanceof WebApplicationContext)) {
|
||||||
// Current context is no a a webapp
|
// Current context is no a a webapp
|
||||||
return DIFFERENT;
|
return DIFFERENT;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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.springframework.boot.actuate.autoconfigure;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||||
|
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||||
|
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||||
|
import org.springframework.boot.actuate.web.ErrorController;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.security.AuthenticationManagerConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.security.SecurityPrequisite;
|
||||||
|
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||||
|
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.IgnoredRequestConfigurer;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link EnableAutoConfiguration Auto-configuration} for security of framework endpoints.
|
||||||
|
* Many aspects of the behavior can be controller with {@link ManagementServerProperties}
|
||||||
|
* via externalized application properties (or via an bean definition of that type to set
|
||||||
|
* the defaults).
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The framework {@link Endpoint}s (used to expose application information to operations)
|
||||||
|
* include a {@link Endpoint#isSensitive() sensitive} configuration option which will be
|
||||||
|
* used as a security hint by the filter created here.
|
||||||
|
*
|
||||||
|
* @author Dave Syer
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnClass({ EnableWebSecurity.class })
|
||||||
|
@AutoConfigureAfter(SecurityAutoConfiguration.class)
|
||||||
|
@EnableConfigurationProperties
|
||||||
|
public class ManagementSecurityAutoConfiguration {
|
||||||
|
|
||||||
|
private static final String[] NO_PATHS = new String[0];
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean({ IgnoredPathsWebSecurityConfigurerAdapter.class })
|
||||||
|
public SecurityConfigurer<Filter, WebSecurity> ignoredPathsWebSecurityConfigurerAdapter() {
|
||||||
|
return new IgnoredPathsWebSecurityConfigurerAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
protected static class ManagementSecurityPropertiesConfiguration implements
|
||||||
|
SecurityPrequisite {
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private SecurityProperties security;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private ManagementServerProperties management;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
if (this.management != null && this.security != null) {
|
||||||
|
this.security.getUser().getRole()
|
||||||
|
.add(this.management.getSecurity().getRole());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the ignored paths in early
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
|
||||||
|
private static class IgnoredPathsWebSecurityConfigurerAdapter implements
|
||||||
|
SecurityConfigurer<Filter, WebSecurity> {
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private ErrorController errorController;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private EndpointHandlerMapping endpointHandlerMapping;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ManagementServerProperties management;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SecurityProperties security;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(WebSecurity builder) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(WebSecurity builder) throws Exception {
|
||||||
|
IgnoredRequestConfigurer ignoring = builder.ignoring();
|
||||||
|
// The ignores are not cumulative, so to prevent overwriting the defaults we
|
||||||
|
// add them back.
|
||||||
|
List<String> ignored = SecurityAutoConfiguration.getIgnored(this.security);
|
||||||
|
ignored.addAll(Arrays.asList(getEndpointPaths(this.endpointHandlerMapping,
|
||||||
|
false)));
|
||||||
|
if (!this.management.getSecurity().isEnabled()) {
|
||||||
|
ignored.addAll(Arrays.asList(getEndpointPaths(
|
||||||
|
this.endpointHandlerMapping, true)));
|
||||||
|
}
|
||||||
|
if (ignored.contains("none")) {
|
||||||
|
ignored.remove("none");
|
||||||
|
}
|
||||||
|
if (this.errorController != null) {
|
||||||
|
ignored.add(this.errorController.getErrorPath());
|
||||||
|
}
|
||||||
|
ignoring.antMatchers(ignored.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnMissingBean({ ManagementWebSecurityConfigurerAdapter.class })
|
||||||
|
@ConditionalOnExpression("${management.security.enabled:true}")
|
||||||
|
@EnableWebSecurity
|
||||||
|
// Give user-supplied filters a chance to be last in line
|
||||||
|
@Order(Ordered.LOWEST_PRECEDENCE - 10)
|
||||||
|
protected static class ManagementWebSecurityConfigurerAdapter extends
|
||||||
|
WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SecurityProperties security;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ManagementServerProperties management;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private EndpointHandlerMapping endpointHandlerMapping;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
|
||||||
|
// secure endpoints
|
||||||
|
String[] paths = getEndpointPaths(this.endpointHandlerMapping, true);
|
||||||
|
if (paths.length > 0 && this.management.getSecurity().isEnabled()) {
|
||||||
|
// Always protect them if present
|
||||||
|
if (this.security.isRequireSsl()) {
|
||||||
|
http.requiresChannel().anyRequest().requiresSecure();
|
||||||
|
}
|
||||||
|
http.exceptionHandling().authenticationEntryPoint(entryPoint());
|
||||||
|
http.requestMatchers().antMatchers(paths);
|
||||||
|
http.authorizeRequests().anyRequest()
|
||||||
|
.hasRole(this.management.getSecurity().getRole()) //
|
||||||
|
.and().httpBasic() //
|
||||||
|
.and().anonymous().disable();
|
||||||
|
|
||||||
|
// No cookies for management endpoints by default
|
||||||
|
http.csrf().disable();
|
||||||
|
http.sessionManagement().sessionCreationPolicy(
|
||||||
|
this.management.getSecurity().getSessions());
|
||||||
|
|
||||||
|
SecurityAutoConfiguration.configureHeaders(http.headers(),
|
||||||
|
this.security.getHeaders());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthenticationEntryPoint entryPoint() {
|
||||||
|
BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
|
||||||
|
entryPoint.setRealmName(this.security.getBasic().getRealm());
|
||||||
|
return entryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnMissingBean(AuthenticationManager.class)
|
||||||
|
protected static class ManagementAuthenticationManagerConfiguration extends
|
||||||
|
AuthenticationManagerConfiguration {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] getEndpointPaths(
|
||||||
|
EndpointHandlerMapping endpointHandlerMapping, boolean secure) {
|
||||||
|
if (endpointHandlerMapping == null) {
|
||||||
|
return NO_PATHS;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Endpoint<?>> endpoints = endpointHandlerMapping.getEndpoints();
|
||||||
|
List<String> paths = new ArrayList<String>(endpoints.size());
|
||||||
|
for (Endpoint<?> endpoint : endpoints) {
|
||||||
|
if (endpoint.isSensitive() == secure) {
|
||||||
|
paths.add(endpoint.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths.toArray(new String[paths.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ public class ManagementServerPropertiesAutoConfiguration {
|
||||||
|
|
||||||
@Bean(name = "org.springframework.actuate.properties.ManagementServerProperties")
|
@Bean(name = "org.springframework.actuate.properties.ManagementServerProperties")
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public ManagementServerProperties serverProperties() {
|
public ManagementServerProperties managementServerProperties() {
|
||||||
return new ManagementServerProperties();
|
return new ManagementServerProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,11 @@ import java.net.InetAddress;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.security.SecurityPrequisite;
|
||||||
import org.springframework.boot.context.embedded.properties.ServerProperties;
|
import org.springframework.boot.context.embedded.properties.ServerProperties;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties for the management server (e.g. port and path settings).
|
* Properties for the management server (e.g. port and path settings).
|
||||||
|
|
@ -30,7 +33,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
* @see ServerProperties
|
* @see ServerProperties
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties(name = "management", ignoreUnknownFields = false)
|
@ConfigurationProperties(name = "management", ignoreUnknownFields = false)
|
||||||
public class ManagementServerProperties {
|
public class ManagementServerProperties implements SecurityPrequisite {
|
||||||
|
|
||||||
private Integer port;
|
private Integer port;
|
||||||
|
|
||||||
|
|
@ -41,6 +44,8 @@ public class ManagementServerProperties {
|
||||||
|
|
||||||
private boolean allowShutdown = false;
|
private boolean allowShutdown = false;
|
||||||
|
|
||||||
|
private Security security = maybeCreateSecurity();
|
||||||
|
|
||||||
public boolean isAllowShutdown() {
|
public boolean isAllowShutdown() {
|
||||||
return this.allowShutdown;
|
return this.allowShutdown;
|
||||||
}
|
}
|
||||||
|
|
@ -82,4 +87,50 @@ public class ManagementServerProperties {
|
||||||
this.contextPath = contextPath;
|
this.contextPath = contextPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Security getSecurity() {
|
||||||
|
return this.security;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Security {
|
||||||
|
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
private String role = "ADMIN";
|
||||||
|
|
||||||
|
private SessionCreationPolicy sessions = SessionCreationPolicy.STATELESS;
|
||||||
|
|
||||||
|
public SessionCreationPolicy getSessions() {
|
||||||
|
return this.sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessions(SessionCreationPolicy sessions) {
|
||||||
|
this.sessions = sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRole(String role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRole() {
|
||||||
|
return this.role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Security maybeCreateSecurity() {
|
||||||
|
if (ClassUtils
|
||||||
|
.isPresent("org.springframework.security.core.Authentication", null)) {
|
||||||
|
return new Security();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,6 @@ org.springframework.boot.actuate.autoconfigure.ErrorMvcAutoConfiguration,\
|
||||||
org.springframework.boot.actuate.autoconfigure.ManagementServerPropertiesAutoConfiguration,\
|
org.springframework.boot.actuate.autoconfigure.ManagementServerPropertiesAutoConfiguration,\
|
||||||
org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration,\
|
org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration,\
|
||||||
org.springframework.boot.actuate.autoconfigure.MetricRepositoryAutoConfiguration,\
|
org.springframework.boot.actuate.autoconfigure.MetricRepositoryAutoConfiguration,\
|
||||||
org.springframework.boot.actuate.autoconfigure.SecurityAutoConfiguration,\
|
org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration,\
|
||||||
org.springframework.boot.actuate.autoconfigure.TraceRepositoryAutoConfiguration,\
|
org.springframework.boot.actuate.autoconfigure.TraceRepositoryAutoConfiguration,\
|
||||||
org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfiguration
|
org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfiguration
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import org.crsh.processor.term.ProcessorIOHandler;
|
||||||
import org.crsh.vfs.Resource;
|
import org.crsh.vfs.Resource;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.boot.autoconfigure.security.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.mock.env.MockEnvironment;
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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.springframework.boot.actuate.autoconfigure;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.boot.TestUtils;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurationReportLoggingInitializer;
|
||||||
|
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
|
||||||
|
import org.springframework.boot.context.initializer.LoggingApplicationContextInitializer;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
import org.springframework.mock.web.MockServletContext;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.ProviderManager;
|
||||||
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ManagementSecurityAutoConfiguration}.
|
||||||
|
*
|
||||||
|
* @author Dave Syer
|
||||||
|
*/
|
||||||
|
public class ManagementSecurityAutoConfigurationTests {
|
||||||
|
|
||||||
|
private AnnotationConfigWebApplicationContext context;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWebConfiguration() throws Exception {
|
||||||
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
|
this.context.setServletContext(new MockServletContext());
|
||||||
|
this.context.register(SecurityAutoConfiguration.class,
|
||||||
|
ManagementSecurityAutoConfiguration.class,
|
||||||
|
EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class,
|
||||||
|
ManagementServerPropertiesAutoConfiguration.class,
|
||||||
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
assertNotNull(this.context.getBean(AuthenticationManager.class));
|
||||||
|
// 6 for static resources, one for management endpoints and one for the rest
|
||||||
|
assertEquals(8, this.context.getBean(FilterChainProxy.class).getFilterChains()
|
||||||
|
.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWebConfigurationWithExtraRole() throws Exception {
|
||||||
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
|
this.context.setServletContext(new MockServletContext());
|
||||||
|
this.context.register(EndpointAutoConfiguration.class,
|
||||||
|
EndpointWebMvcAutoConfiguration.class,
|
||||||
|
ManagementServerPropertiesAutoConfiguration.class,
|
||||||
|
SecurityAutoConfiguration.class,
|
||||||
|
ManagementSecurityAutoConfiguration.class,
|
||||||
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
|
debugRefresh(this.context);
|
||||||
|
UserDetails user = getUser();
|
||||||
|
assertTrue(user.getAuthorities().containsAll(
|
||||||
|
AuthorityUtils
|
||||||
|
.commaSeparatedStringToAuthorityList("ROLE_USER,ROLE_ADMIN")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserDetails getUser() {
|
||||||
|
ProviderManager manager = this.context.getBean(ProviderManager.class);
|
||||||
|
DaoAuthenticationProvider provider = (DaoAuthenticationProvider) manager
|
||||||
|
.getProviders().get(0);
|
||||||
|
UserDetailsService service = (UserDetailsService) ReflectionTestUtils.getField(
|
||||||
|
provider, "userDetailsService");
|
||||||
|
UserDetails user = service.loadUserByUsername("user");
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDisableIgnoredStaticApplicationPaths() throws Exception {
|
||||||
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
|
this.context.setServletContext(new MockServletContext());
|
||||||
|
this.context.register(SecurityAutoConfiguration.class,
|
||||||
|
ManagementSecurityAutoConfiguration.class,
|
||||||
|
EndpointAutoConfiguration.class,
|
||||||
|
ManagementServerPropertiesAutoConfiguration.class,
|
||||||
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
|
TestUtils.addEnviroment(this.context, "security.ignored:none");
|
||||||
|
this.context.refresh();
|
||||||
|
// Just the application and management endpoints now
|
||||||
|
assertEquals(2, this.context.getBean(FilterChainProxy.class).getFilterChains()
|
||||||
|
.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDisableBasicAuthOnApplicationPaths() throws Exception {
|
||||||
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
|
this.context.setServletContext(new MockServletContext());
|
||||||
|
this.context.register(SecurityAutoConfiguration.class,
|
||||||
|
ManagementSecurityAutoConfiguration.class,
|
||||||
|
EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class,
|
||||||
|
ManagementServerPropertiesAutoConfiguration.class,
|
||||||
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
|
TestUtils.addEnviroment(this.context, "security.basic.enabled:false");
|
||||||
|
this.context.refresh();
|
||||||
|
// Just the management endpoints (one filter) and ignores now
|
||||||
|
assertEquals(7, this.context.getBean(FilterChainProxy.class).getFilterChains()
|
||||||
|
.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverrideAuthenticationManager() throws Exception {
|
||||||
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
|
this.context.setServletContext(new MockServletContext());
|
||||||
|
this.context.register(TestConfiguration.class,
|
||||||
|
|
||||||
|
SecurityAutoConfiguration.class, ManagementSecurityAutoConfiguration.class,
|
||||||
|
EndpointAutoConfiguration.class,
|
||||||
|
ManagementServerPropertiesAutoConfiguration.class,
|
||||||
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
|
this.context.refresh();
|
||||||
|
assertEquals(this.context.getBean(TestConfiguration.class).authenticationManager,
|
||||||
|
this.context.getBean(AuthenticationManager.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AnnotationConfigWebApplicationContext debugRefresh(
|
||||||
|
AnnotationConfigWebApplicationContext context) {
|
||||||
|
TestUtils.addEnviroment(context, "debug:true");
|
||||||
|
LoggingApplicationContextInitializer logging = new LoggingApplicationContextInitializer();
|
||||||
|
logging.initialize(context);
|
||||||
|
AutoConfigurationReportLoggingInitializer initializer = new AutoConfigurationReportLoggingInitializer();
|
||||||
|
initializer.initialize(context);
|
||||||
|
context.refresh();
|
||||||
|
initializer.onApplicationEvent(new ContextRefreshedEvent(context));
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
protected static class TestConfiguration {
|
||||||
|
|
||||||
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationManager myAuthenticationManager() {
|
||||||
|
this.authenticationManager = new AuthenticationManager() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authentication authenticate(Authentication authentication)
|
||||||
|
throws AuthenticationException {
|
||||||
|
return new TestingAuthenticationToken("foo", "bar");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return this.authenticationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -126,6 +126,16 @@
|
||||||
<artifactId>spring-security-acl</artifactId>
|
<artifactId>spring-security-acl</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-web</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-config</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.amqp</groupId>
|
<groupId>org.springframework.amqp</groupId>
|
||||||
<artifactId>spring-rabbit</artifactId>
|
<artifactId>spring-rabbit</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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.springframework.boot.autoconfigure.security;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class AuthenticationManagerConfiguration {
|
||||||
|
|
||||||
|
private static Log logger = LogFactory
|
||||||
|
.getLog(AuthenticationManagerConfiguration.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SecurityProperties security;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private List<SecurityPrequisite> dependencies;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationManager authenticationManager(
|
||||||
|
ObjectPostProcessor<Object> objectPostProcessor) throws Exception {
|
||||||
|
|
||||||
|
InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> builder = new AuthenticationManagerBuilder(
|
||||||
|
objectPostProcessor).inMemoryAuthentication();
|
||||||
|
User user = this.security.getUser();
|
||||||
|
|
||||||
|
if (user.isDefaultPassword()) {
|
||||||
|
logger.info("\n\nUsing default password for application endpoints: "
|
||||||
|
+ user.getPassword() + "\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add the management role...
|
||||||
|
Set<String> roles = new LinkedHashSet<String>(user.getRole());
|
||||||
|
|
||||||
|
builder.withUser(user.getName()).password(user.getPassword())
|
||||||
|
.roles(roles.toArray(new String[roles.size()]));
|
||||||
|
|
||||||
|
return builder.and().build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,30 +14,21 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure;
|
package org.springframework.boot.autoconfigure.security;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
|
||||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
|
||||||
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties;
|
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties.Headers;
|
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties.User;
|
|
||||||
import org.springframework.boot.actuate.web.ErrorController;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
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.security.SecurityProperties.Headers;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
@ -47,10 +38,7 @@ import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||||
import org.springframework.security.authentication.ProviderManager;
|
import org.springframework.security.authentication.ProviderManager;
|
||||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
|
||||||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
||||||
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
|
||||||
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;
|
||||||
|
|
@ -76,11 +64,6 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
* events.
|
* events.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* The framework {@link Endpoint}s (used to expose application information to operations)
|
|
||||||
* include a {@link Endpoint#isSensitive() sensitive} configuration option which will be
|
|
||||||
* used as a security hint by the filter created here.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Some common simple customizations:
|
* Some common simple customizations:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Switch off security completely and permanently: remove Spring Security from the
|
* <li>Switch off security completely and permanently: remove Spring Security from the
|
||||||
|
|
@ -95,14 +78,15 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@EnableConfigurationProperties
|
||||||
@ConditionalOnClass({ EnableWebSecurity.class })
|
@ConditionalOnClass({ EnableWebSecurity.class })
|
||||||
@ConditionalOnMissingBean(annotation = EnableWebSecurity.class)
|
@ConditionalOnMissingBean(annotation = EnableWebSecurity.class)
|
||||||
@EnableConfigurationProperties
|
|
||||||
public class SecurityAutoConfiguration {
|
public class SecurityAutoConfiguration {
|
||||||
|
|
||||||
private static final String[] NO_PATHS = new String[0];
|
private static List<String> DEFAULT_IGNORED = Arrays.asList("/css/**", "/js/**",
|
||||||
|
"/images/**", "/**/favicon.ico");
|
||||||
|
|
||||||
@Bean(name = "org.springframework.actuate.properties.SecurityProperties")
|
@Bean(name = "org.springframework.autoconfigure.security.SecurityProperties")
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public SecurityProperties securityProperties() {
|
public SecurityProperties securityProperties() {
|
||||||
return new SecurityProperties();
|
return new SecurityProperties();
|
||||||
|
|
@ -114,41 +98,18 @@ public class SecurityAutoConfiguration {
|
||||||
return new DefaultAuthenticationEventPublisher();
|
return new DefaultAuthenticationEventPublisher();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean({ ApplicationWebSecurityConfigurerAdapter.class })
|
|
||||||
@ConditionalOnExpression("${security.basic.enabled:true}")
|
|
||||||
public WebSecurityConfigurerAdapter applicationWebSecurityConfigurerAdapter() {
|
|
||||||
return new ApplicationWebSecurityConfigurerAdapter();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean({ ManagementWebSecurityConfigurerAdapter.class })
|
|
||||||
@ConditionalOnExpression("${security.management.enabled:true}")
|
|
||||||
public WebSecurityConfigurerAdapter managementWebSecurityConfigurerAdapter() {
|
|
||||||
return new ManagementWebSecurityConfigurerAdapter();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean({ IgnoredPathsWebSecurityConfigurerAdapter.class })
|
@ConditionalOnMissingBean({ IgnoredPathsWebSecurityConfigurerAdapter.class })
|
||||||
|
@ConditionalOnBean(annotation = EnableWebSecurity.class)
|
||||||
public SecurityConfigurer<Filter, WebSecurity> ignoredPathsWebSecurityConfigurerAdapter() {
|
public SecurityConfigurer<Filter, WebSecurity> ignoredPathsWebSecurityConfigurerAdapter() {
|
||||||
return new IgnoredPathsWebSecurityConfigurerAdapter();
|
return new IgnoredPathsWebSecurityConfigurerAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the ignored paths in early
|
// Get the ignored paths in early
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
@EnableWebSecurity
|
|
||||||
private static class IgnoredPathsWebSecurityConfigurerAdapter implements
|
private static class IgnoredPathsWebSecurityConfigurerAdapter implements
|
||||||
SecurityConfigurer<Filter, WebSecurity> {
|
SecurityConfigurer<Filter, WebSecurity> {
|
||||||
|
|
||||||
private static List<String> DEFAULT_IGNORED = Arrays.asList("/css/**", "/js/**",
|
|
||||||
"/images/**", "/**/favicon.ico");
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private ErrorController errorController;
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private EndpointHandlerMapping endpointHandlerMapping;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SecurityProperties security;
|
private SecurityProperties security;
|
||||||
|
|
||||||
|
|
@ -159,29 +120,18 @@ public class SecurityAutoConfiguration {
|
||||||
@Override
|
@Override
|
||||||
public void init(WebSecurity builder) throws Exception {
|
public void init(WebSecurity builder) throws Exception {
|
||||||
IgnoredRequestConfigurer ignoring = builder.ignoring();
|
IgnoredRequestConfigurer ignoring = builder.ignoring();
|
||||||
ignoring.antMatchers(getEndpointPaths(this.endpointHandlerMapping, false));
|
List<String> ignored = getIgnored(this.security);
|
||||||
List<String> ignored = new ArrayList<String>(this.security.getIgnored());
|
|
||||||
if (!this.security.getManagement().isEnabled()) {
|
|
||||||
ignored.addAll(Arrays.asList(getEndpointPaths(
|
|
||||||
this.endpointHandlerMapping, true)));
|
|
||||||
}
|
|
||||||
if (ignored.isEmpty()) {
|
|
||||||
ignored.addAll(DEFAULT_IGNORED);
|
|
||||||
}
|
|
||||||
else if (ignored.contains("none")) {
|
|
||||||
ignored.remove("none");
|
|
||||||
}
|
|
||||||
if (this.errorController != null) {
|
|
||||||
ignored.add(this.errorController.getErrorPath());
|
|
||||||
}
|
|
||||||
ignoring.antMatchers(ignored.toArray(new String[0]));
|
ignoring.antMatchers(ignored.toArray(new String[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give user-supplied filters a chance to be last in line
|
@ConditionalOnMissingBean({ ApplicationWebSecurityConfigurerAdapter.class })
|
||||||
|
@ConditionalOnExpression("${security.basic.enabled:true}")
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
@Order(Ordered.LOWEST_PRECEDENCE - 5)
|
@Order(Ordered.LOWEST_PRECEDENCE - 5)
|
||||||
private static class ApplicationWebSecurityConfigurerAdapter extends
|
protected static class ApplicationWebSecurityConfigurerAdapter extends
|
||||||
WebSecurityConfigurerAdapter {
|
WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
@ -201,8 +151,10 @@ public class SecurityAutoConfiguration {
|
||||||
if (this.security.getBasic().isEnabled() && paths.length > 0) {
|
if (this.security.getBasic().isEnabled() && paths.length > 0) {
|
||||||
http.exceptionHandling().authenticationEntryPoint(entryPoint());
|
http.exceptionHandling().authenticationEntryPoint(entryPoint());
|
||||||
http.requestMatchers().antMatchers(paths);
|
http.requestMatchers().antMatchers(paths);
|
||||||
http.authorizeRequests().anyRequest()
|
http.authorizeRequests()
|
||||||
.hasRole(this.security.getUser().getRole()) //
|
.anyRequest()
|
||||||
|
.hasAnyRole(
|
||||||
|
this.security.getUser().getRole().toArray(new String[0])) //
|
||||||
.and().httpBasic() //
|
.and().httpBasic() //
|
||||||
.and().anonymous().disable();
|
.and().anonymous().disable();
|
||||||
}
|
}
|
||||||
|
|
@ -247,111 +199,15 @@ public class SecurityAutoConfiguration {
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
@Configuration
|
||||||
|
@ConditionalOnMissingBean(AuthenticationManager.class)
|
||||||
// Give user-supplied filters a chance to be last in line
|
protected static class ApplicationAuthenticationManagerConfiguration extends
|
||||||
@Order(Ordered.LOWEST_PRECEDENCE - 10)
|
AuthenticationManagerConfiguration {
|
||||||
private static class ManagementWebSecurityConfigurerAdapter extends
|
|
||||||
WebSecurityConfigurerAdapter {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SecurityProperties security;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ManagementServerProperties management;
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private EndpointHandlerMapping endpointHandlerMapping;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
|
||||||
|
|
||||||
// secure endpoints
|
|
||||||
String[] paths = getEndpointPaths(this.endpointHandlerMapping, true);
|
|
||||||
if (paths.length > 0 && this.security.getManagement().isEnabled()) {
|
|
||||||
// Always protect them if present
|
|
||||||
if (this.security.isRequireSsl()) {
|
|
||||||
http.requiresChannel().anyRequest().requiresSecure();
|
|
||||||
}
|
|
||||||
http.exceptionHandling().authenticationEntryPoint(entryPoint());
|
|
||||||
http.requestMatchers().antMatchers(paths);
|
|
||||||
http.authorizeRequests().anyRequest()
|
|
||||||
.hasRole(this.security.getManagement().getRole()) //
|
|
||||||
.and().httpBasic() //
|
|
||||||
.and().anonymous().disable();
|
|
||||||
|
|
||||||
// No cookies for management endpoints by default
|
|
||||||
http.csrf().disable();
|
|
||||||
http.sessionManagement().sessionCreationPolicy(
|
|
||||||
this.security.getManagement().getSessions());
|
|
||||||
|
|
||||||
SecurityAutoConfiguration.configureHeaders(http.headers(),
|
|
||||||
this.security.getHeaders());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private AuthenticationEntryPoint entryPoint() {
|
|
||||||
BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
|
|
||||||
entryPoint.setRealmName(this.security.getBasic().getRealm());
|
|
||||||
return entryPoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnMissingBean(AuthenticationManager.class)
|
public static void configureHeaders(HeadersConfigurer<?> configurer,
|
||||||
@Configuration
|
|
||||||
public static class AuthenticationManagerConfiguration {
|
|
||||||
|
|
||||||
private static Log logger = LogFactory
|
|
||||||
.getLog(AuthenticationManagerConfiguration.class);
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SecurityProperties security;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public AuthenticationManager authenticationManager(
|
|
||||||
ObjectPostProcessor<Object> objectPostProcessor) throws Exception {
|
|
||||||
|
|
||||||
InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> builder = new AuthenticationManagerBuilder(
|
|
||||||
objectPostProcessor).inMemoryAuthentication();
|
|
||||||
User user = this.security.getUser();
|
|
||||||
|
|
||||||
if (user.isDefaultPassword()) {
|
|
||||||
logger.info("\n\nUsing default password for application endpoints: "
|
|
||||||
+ user.getPassword() + "\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> roles = new LinkedHashSet<String>(Arrays.asList(this.security
|
|
||||||
.getManagement().getRole(), user.getRole()));
|
|
||||||
|
|
||||||
builder.withUser(user.getName()).password(user.getPassword())
|
|
||||||
.roles(roles.toArray(new String[roles.size()]));
|
|
||||||
|
|
||||||
return builder.and().build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String[] getEndpointPaths(
|
|
||||||
EndpointHandlerMapping endpointHandlerMapping, boolean secure) {
|
|
||||||
if (endpointHandlerMapping == null) {
|
|
||||||
return NO_PATHS;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Endpoint<?>> endpoints = endpointHandlerMapping.getEndpoints();
|
|
||||||
List<String> paths = new ArrayList<String>(endpoints.size());
|
|
||||||
for (Endpoint<?> endpoint : endpoints) {
|
|
||||||
if (endpoint.isSensitive() == secure) {
|
|
||||||
paths.add(endpoint.getPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return paths.toArray(new String[paths.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void configureHeaders(HeadersConfigurer<?> configurer,
|
|
||||||
SecurityProperties.Headers headers) throws Exception {
|
SecurityProperties.Headers headers) throws Exception {
|
||||||
if (headers.getHsts() != Headers.HSTS.none) {
|
if (headers.getHsts() != Headers.HSTS.none) {
|
||||||
boolean includeSubdomains = headers.getHsts() == Headers.HSTS.all;
|
boolean includeSubdomains = headers.getHsts() == Headers.HSTS.all;
|
||||||
|
|
@ -373,4 +229,15 @@ public class SecurityAutoConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<String> getIgnored(SecurityProperties security) {
|
||||||
|
List<String> ignored = new ArrayList<String>(security.getIgnored());
|
||||||
|
if (ignored.isEmpty()) {
|
||||||
|
ignored.addAll(DEFAULT_IGNORED);
|
||||||
|
}
|
||||||
|
else if (ignored.contains("none")) {
|
||||||
|
ignored.remove("none");
|
||||||
|
}
|
||||||
|
return ignored;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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.springframework.boot.autoconfigure.security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface for beans that need to be initialized before any security
|
||||||
|
* configuration is evaluated.
|
||||||
|
*
|
||||||
|
* @author Dave Syer
|
||||||
|
*/
|
||||||
|
public interface SecurityPrequisite {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,9 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.actuate.properties;
|
package org.springframework.boot.autoconfigure.security;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
@ -30,7 +31,7 @@ import org.springframework.util.StringUtils;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties(name = "security", ignoreUnknownFields = false)
|
@ConfigurationProperties(name = "security", ignoreUnknownFields = false)
|
||||||
public class SecurityProperties {
|
public class SecurityProperties implements SecurityPrequisite {
|
||||||
|
|
||||||
private boolean requireSsl;
|
private boolean requireSsl;
|
||||||
|
|
||||||
|
|
@ -45,8 +46,6 @@ public class SecurityProperties {
|
||||||
|
|
||||||
private List<String> ignored = new ArrayList<String>();
|
private List<String> ignored = new ArrayList<String>();
|
||||||
|
|
||||||
private Management management = new Management();
|
|
||||||
|
|
||||||
private User user = new User();
|
private User user = new User();
|
||||||
|
|
||||||
public Headers getHeaders() {
|
public Headers getHeaders() {
|
||||||
|
|
@ -57,10 +56,6 @@ public class SecurityProperties {
|
||||||
return this.user;
|
return this.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Management getManagement() {
|
|
||||||
return this.management;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionCreationPolicy getSessions() {
|
public SessionCreationPolicy getSessions() {
|
||||||
return this.sessions;
|
return this.sessions;
|
||||||
}
|
}
|
||||||
|
|
@ -193,47 +188,13 @@ public class SecurityProperties {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Management {
|
|
||||||
|
|
||||||
private boolean enabled = true;
|
|
||||||
|
|
||||||
private String role = "ADMIN";
|
|
||||||
|
|
||||||
private SessionCreationPolicy sessions = SessionCreationPolicy.STATELESS;
|
|
||||||
|
|
||||||
public SessionCreationPolicy getSessions() {
|
|
||||||
return this.sessions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSessions(SessionCreationPolicy sessions) {
|
|
||||||
this.sessions = sessions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRole(String role) {
|
|
||||||
this.role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRole() {
|
|
||||||
return this.role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return this.enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
this.enabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class User {
|
public static class User {
|
||||||
|
|
||||||
private String name = "user";
|
private String name = "user";
|
||||||
|
|
||||||
private String password = UUID.randomUUID().toString();
|
private String password = UUID.randomUUID().toString();
|
||||||
|
|
||||||
private String role = "USER";
|
private List<String> role = new ArrayList<String>(Arrays.asList("USER"));
|
||||||
|
|
||||||
private boolean defaultPassword = true;
|
private boolean defaultPassword = true;
|
||||||
|
|
||||||
|
|
@ -258,14 +219,10 @@ public class SecurityProperties {
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRole() {
|
public List<String> getRole() {
|
||||||
return this.role;
|
return this.role;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRole(String role) {
|
|
||||||
this.role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDefaultPassword() {
|
public boolean isDefaultPassword() {
|
||||||
return this.defaultPassword;
|
return this.defaultPassword;
|
||||||
}
|
}
|
||||||
|
|
@ -14,6 +14,7 @@ org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
|
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
|
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
|
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
|
||||||
|
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
|
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
|
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
|
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,16 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure;
|
package org.springframework.boot.autoconfigure.security;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.TestUtils;
|
import org.springframework.boot.TestUtils;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurationReportLoggingInitializer;
|
||||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||||
|
import org.springframework.boot.context.initializer.LoggingApplicationContextInitializer;
|
||||||
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.context.event.ContextRefreshedEvent;
|
||||||
import org.springframework.mock.web.MockServletContext;
|
import org.springframework.mock.web.MockServletContext;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
|
@ -46,13 +49,11 @@ public class SecurityAutoConfigurationTests {
|
||||||
this.context = new AnnotationConfigWebApplicationContext();
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
this.context.setServletContext(new MockServletContext());
|
this.context.setServletContext(new MockServletContext());
|
||||||
this.context.register(SecurityAutoConfiguration.class,
|
this.context.register(SecurityAutoConfiguration.class,
|
||||||
EndpointAutoConfiguration.class,
|
|
||||||
ManagementServerPropertiesAutoConfiguration.class,
|
|
||||||
PropertyPlaceholderAutoConfiguration.class);
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
this.context.refresh();
|
debugRefresh(this.context);
|
||||||
assertNotNull(this.context.getBean(AuthenticationManager.class));
|
assertNotNull(this.context.getBean(AuthenticationManager.class));
|
||||||
// 4 for static resources, one for management endpoints and one for the rest
|
// 4 for static resources and one for the rest
|
||||||
assertEquals(6, this.context.getBean(FilterChainProxy.class).getFilterChains()
|
assertEquals(5, this.context.getBean(FilterChainProxy.class).getFilterChains()
|
||||||
.size());
|
.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,13 +62,11 @@ public class SecurityAutoConfigurationTests {
|
||||||
this.context = new AnnotationConfigWebApplicationContext();
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
this.context.setServletContext(new MockServletContext());
|
this.context.setServletContext(new MockServletContext());
|
||||||
this.context.register(SecurityAutoConfiguration.class,
|
this.context.register(SecurityAutoConfiguration.class,
|
||||||
EndpointAutoConfiguration.class,
|
|
||||||
ManagementServerPropertiesAutoConfiguration.class,
|
|
||||||
PropertyPlaceholderAutoConfiguration.class);
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
TestUtils.addEnviroment(this.context, "security.ignored:none");
|
TestUtils.addEnviroment(this.context, "security.ignored:none");
|
||||||
this.context.refresh();
|
this.context.refresh();
|
||||||
// Just the application and management endpoints now
|
// Just the application endpoints now
|
||||||
assertEquals(2, this.context.getBean(FilterChainProxy.class).getFilterChains()
|
assertEquals(1, this.context.getBean(FilterChainProxy.class).getFilterChains()
|
||||||
.size());
|
.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,14 +75,11 @@ public class SecurityAutoConfigurationTests {
|
||||||
this.context = new AnnotationConfigWebApplicationContext();
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
this.context.setServletContext(new MockServletContext());
|
this.context.setServletContext(new MockServletContext());
|
||||||
this.context.register(SecurityAutoConfiguration.class,
|
this.context.register(SecurityAutoConfiguration.class,
|
||||||
EndpointAutoConfiguration.class,
|
|
||||||
ManagementServerPropertiesAutoConfiguration.class,
|
|
||||||
PropertyPlaceholderAutoConfiguration.class);
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
TestUtils.addEnviroment(this.context, "security.basic.enabled:false");
|
TestUtils.addEnviroment(this.context, "security.basic.enabled:false");
|
||||||
this.context.refresh();
|
this.context.refresh();
|
||||||
// Just the management endpoints and default ignores now
|
// No security at all not even ignores
|
||||||
assertEquals(5, this.context.getBean(FilterChainProxy.class).getFilterChains()
|
assertEquals(0, this.context.getBeanNamesForType(FilterChainProxy.class).length);
|
||||||
.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -91,14 +87,24 @@ public class SecurityAutoConfigurationTests {
|
||||||
this.context = new AnnotationConfigWebApplicationContext();
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
this.context.setServletContext(new MockServletContext());
|
this.context.setServletContext(new MockServletContext());
|
||||||
this.context.register(TestConfiguration.class, SecurityAutoConfiguration.class,
|
this.context.register(TestConfiguration.class, SecurityAutoConfiguration.class,
|
||||||
EndpointAutoConfiguration.class,
|
|
||||||
ManagementServerPropertiesAutoConfiguration.class,
|
|
||||||
PropertyPlaceholderAutoConfiguration.class);
|
PropertyPlaceholderAutoConfiguration.class);
|
||||||
this.context.refresh();
|
this.context.refresh();
|
||||||
assertEquals(this.context.getBean(TestConfiguration.class).authenticationManager,
|
assertEquals(this.context.getBean(TestConfiguration.class).authenticationManager,
|
||||||
this.context.getBean(AuthenticationManager.class));
|
this.context.getBean(AuthenticationManager.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static AnnotationConfigWebApplicationContext debugRefresh(
|
||||||
|
AnnotationConfigWebApplicationContext context) {
|
||||||
|
TestUtils.addEnviroment(context, "debug:true");
|
||||||
|
LoggingApplicationContextInitializer logging = new LoggingApplicationContextInitializer();
|
||||||
|
logging.initialize(context);
|
||||||
|
AutoConfigurationReportLoggingInitializer initializer = new AutoConfigurationReportLoggingInitializer();
|
||||||
|
initializer.initialize(context);
|
||||||
|
context.refresh();
|
||||||
|
initializer.onApplicationEvent(new ContextRefreshedEvent(context));
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
protected static class TestConfiguration {
|
protected static class TestConfiguration {
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.actuate.properties;
|
package org.springframework.boot.autoconfigure.security;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
|
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||||
import org.springframework.boot.bind.RelaxedDataBinder;
|
import org.springframework.boot.bind.RelaxedDataBinder;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
|
|
||||||
|
|
@ -44,8 +44,7 @@ public class ReproIntegrationTests {
|
||||||
@Test
|
@Test
|
||||||
public void securityDependencies() throws Exception {
|
public void securityDependencies() throws Exception {
|
||||||
this.cli.run("secure.groovy");
|
this.cli.run("secure.groovy");
|
||||||
assertThat(this.cli.getHttpOutput(),
|
assertThat(this.cli.getOutput(), containsString("Hello World"));
|
||||||
containsString("{\"message\":\"Hello World\"}"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@ package org.test
|
||||||
// No security features added just a test that the dependencies are resolved
|
// No security features added just a test that the dependencies are resolved
|
||||||
@Grab("spring-boot-starter-security")
|
@Grab("spring-boot-starter-security")
|
||||||
|
|
||||||
@RestController
|
@Controller
|
||||||
class SampleController {
|
class Sample implements CommandLineRunner {
|
||||||
|
|
||||||
@RequestMapping("/")
|
@Override
|
||||||
public def hello() {
|
void run(String... args) {
|
||||||
[message: "Hello World"]
|
println "Hello World"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import org.junit.BeforeClass;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties;
|
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.http.HttpRequest;
|
import org.springframework.http.HttpRequest;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties;
|
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.http.HttpRequest;
|
import org.springframework.http.HttpRequest;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties;
|
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.actuate.properties.SecurityProperties;
|
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.http.HttpRequest;
|
import org.springframework.http.HttpRequest;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ public class UnsecureManagementSampleActuatorApplicationTests {
|
||||||
public ConfigurableApplicationContext call() throws Exception {
|
public ConfigurableApplicationContext call() throws Exception {
|
||||||
return SpringApplication.run(
|
return SpringApplication.run(
|
||||||
SampleActuatorApplication.class,
|
SampleActuatorApplication.class,
|
||||||
"--security.management.enabled=false");
|
"--management.security.enabled=false");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
context = future.get(60, TimeUnit.SECONDS);
|
context = future.get(60, TimeUnit.SECONDS);
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
@ -24,14 +24,6 @@
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.security</groupId>
|
|
||||||
<artifactId>spring-security-config</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.security</groupId>
|
|
||||||
<artifactId>spring-security-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.thymeleaf</groupId>
|
<groupId>org.thymeleaf</groupId>
|
||||||
<artifactId>thymeleaf-spring3</artifactId>
|
<artifactId>thymeleaf-spring3</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.boot.sample.ops.ui;
|
package org.springframework.boot.sample.ops.ui;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
@ -39,9 +41,6 @@ import org.springframework.http.client.ClientHttpResponse;
|
||||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic integration tests for demo application.
|
* Basic integration tests for demo application.
|
||||||
*
|
*
|
||||||
|
|
@ -92,30 +91,6 @@ public class SampleSecureApplicationTests {
|
||||||
assertTrue("Wrong body:\n" + entity.getBody(), entity.getBody().contains("body"));
|
assertTrue("Wrong body:\n" + entity.getBody(), entity.getBody().contains("body"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMetrics() throws Exception {
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
ResponseEntity<Map> entity = getRestTemplate().getForEntity(
|
|
||||||
"http://localhost:8080/metrics", Map.class);
|
|
||||||
assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testError() throws Exception {
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
|
|
||||||
ResponseEntity<String> entity = getRestTemplate().exchange(
|
|
||||||
"http://localhost:8080/error", HttpMethod.GET,
|
|
||||||
new HttpEntity<Void>(headers), String.class);
|
|
||||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
|
||||||
assertTrue("Wrong body:\n" + entity.getBody(), entity.getBody()
|
|
||||||
.contains("<html>"));
|
|
||||||
assertTrue("Wrong body:\n" + entity.getBody(), entity.getBody()
|
|
||||||
.contains("<body>"));
|
|
||||||
assertTrue("Wrong body:\n" + entity.getBody(), entity.getBody()
|
|
||||||
.contains("Please contact the operator with the above information"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private RestTemplate getRestTemplate() {
|
private RestTemplate getRestTemplate() {
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
|
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,8 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.env.SimpleCommandLinePropertySource;
|
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -108,17 +106,6 @@ public class LoggingApplicationContextInitializer implements
|
||||||
LoggingSystem loggingSystem = LoggingSystem.get(springApplication.getClass()
|
LoggingSystem loggingSystem = LoggingSystem.get(springApplication.getClass()
|
||||||
.getClassLoader());
|
.getClassLoader());
|
||||||
loggingSystem.beforeInitialize();
|
loggingSystem.beforeInitialize();
|
||||||
if (this.parseArgs && this.springBootLogging == null
|
|
||||||
&& !ObjectUtils.isEmpty(args)) {
|
|
||||||
SimpleCommandLinePropertySource parsedArgs = new SimpleCommandLinePropertySource(
|
|
||||||
args);
|
|
||||||
if (parsedArgs.containsProperty("debug")) {
|
|
||||||
this.springBootLogging = LogLevel.DEBUG;
|
|
||||||
}
|
|
||||||
if (parsedArgs.containsProperty("trace")) {
|
|
||||||
this.springBootLogging = LogLevel.TRACE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -130,6 +117,15 @@ public class LoggingApplicationContextInitializer implements
|
||||||
|
|
||||||
ConfigurableEnvironment environment = applicationContext.getEnvironment();
|
ConfigurableEnvironment environment = applicationContext.getEnvironment();
|
||||||
|
|
||||||
|
if (this.parseArgs && this.springBootLogging == null) {
|
||||||
|
if (environment.containsProperty("debug")) {
|
||||||
|
this.springBootLogging = LogLevel.DEBUG;
|
||||||
|
}
|
||||||
|
if (environment.containsProperty("trace")) {
|
||||||
|
this.springBootLogging = LogLevel.TRACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, String> mapping : ENVIRONMENT_SYSTEM_PROPERTY_MAPPING
|
for (Map.Entry<String, String> mapping : ENVIRONMENT_SYSTEM_PROPERTY_MAPPING
|
||||||
.entrySet()) {
|
.entrySet()) {
|
||||||
if (environment.containsProperty(mapping.getKey())) {
|
if (environment.containsProperty(mapping.getKey())) {
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ public class LoggingApplicationContextInitializerTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseDebugArg() throws Exception {
|
public void parseDebugArg() throws Exception {
|
||||||
this.initializer.initialize(this.springApplication, new String[] { "--debug" });
|
TestUtils.addEnviroment(this.context, "debug");
|
||||||
this.initializer.initialize(this.context);
|
this.initializer.initialize(this.context);
|
||||||
this.logger.debug("testatdebug");
|
this.logger.debug("testatdebug");
|
||||||
this.logger.trace("testattrace");
|
this.logger.trace("testattrace");
|
||||||
|
|
@ -142,8 +142,7 @@ public class LoggingApplicationContextInitializerTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseTraceArg() throws Exception {
|
public void parseTraceArg() throws Exception {
|
||||||
this.context = new GenericApplicationContext();
|
TestUtils.addEnviroment(this.context, "trace");
|
||||||
this.initializer.initialize(this.springApplication, new String[] { "--trace" });
|
|
||||||
this.initializer.initialize(this.context);
|
this.initializer.initialize(this.context);
|
||||||
this.logger.debug("testatdebug");
|
this.logger.debug("testatdebug");
|
||||||
this.logger.trace("testattrace");
|
this.logger.trace("testattrace");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue