ApplicationSecurityAutoConfiguration.java
package cn.home1.cloud.config.server.security;
import static cn.home1.cloud.config.server.security.Role.ACTUATOR;
import static cn.home1.cloud.config.server.security.Role.ADMIN;
import static cn.home1.cloud.config.server.security.Role.HOOK;
import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.security.SecurityDataConfiguration;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.config.server.config.ConfigServerProperties;
import org.springframework.cloud.config.server.environment.EnvironmentController;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
/**
* see: https://github.com/spring-projects/spring-boot/issues/12323
* see: {@link org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration}
* see: https://spring.io/blog/2017/09/15/security-changes-in-spring-boot-2-0-m4
*/
@Configuration
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
@ConditionalOnProperty(prefix = "spring.security", name = "enabled", havingValue = "true")
@EnableConfigurationProperties(SecurityProperties.class)
@Import({SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class,
SecurityDataConfiguration.class})
public class ApplicationSecurityAutoConfiguration {
@Bean
@ConditionalOnMissingBean(AuthenticationEventPublisher.class)
public DefaultAuthenticationEventPublisher authenticationEventPublisher(
ApplicationEventPublisher publisher) {
return new DefaultAuthenticationEventPublisher(publisher);
}
@ConditionalOnProperty(prefix = "spring.security", name = "enabled", havingValue = "true")
@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER)
//@Order(ApplicationSecurityAutoConfiguration.ACCESS_OVERRIDE_ORDER)
static class ApplicationWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
// /**
// * org.springframework.boot.autoconfigure.security.SecurityProperties.ACCESS_OVERRIDE_ORDER
// *
// * TODO deprecated in spring-boot 2.x
// */
// public static final int ACCESS_OVERRIDE_ORDER = 2147483640;
@Autowired
private ConfigSecurity configSecurity;
@Autowired
private ConfigServerProperties configServerProperties;
@Autowired
private EnvironmentController environmentController;
/**
* TODO rename
*/
@Value("${management.endpoints.web.base-path:}")
private String managementContextPath;
@Override
public void init(final WebSecurity web) throws Exception {
super.init(web);
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.userDetailsService()).passwordEncoder(NoOpPasswordEncoder.getInstance());
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
final String configServerPrefix = this.configServerProperties.getPrefix();
//final String loginEndpoint = configServerPrefix + "/users/login";
final String monitorEndpoint = configServerPrefix + "/monitor";
//super.configure(http); // default config
http //
.authorizeRequests() //
.requestMatchers(EndpointRequest.to("health", "info")).permitAll() //
.requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole(ACTUATOR.toString()) //
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() //
.antMatchers(configServerPrefix + "/").permitAll() //
.antMatchers(configServerPrefix + "/deployKeyPublic").permitAll() //
.antMatchers(configServerPrefix + "/decrypt").hasRole(ADMIN.toString()) //
.antMatchers(configServerPrefix + "/encrypt", monitorEndpoint).permitAll() //
.antMatchers(configServerPrefix + "/encryptParentPassword").hasRole(ADMIN.toString()) //
.antMatchers(configServerPrefix + "/monitor").hasAnyRole(ADMIN.toString(), HOOK.toString()) //
.antMatchers(new String[]{ //
configServerPrefix + "/{application}/{profiles:.*[^-].*}", //
configServerPrefix + "/{application}/{profiles}/{label:.*}", //
configServerPrefix + "/{application}-{profiles}.json", //
configServerPrefix + "/{label}/{application}-{profiles}.json", //
configServerPrefix + "/{application}-{profiles}.properties", //
configServerPrefix + "/{application}/{name}-{profiles}.properties", //
configServerPrefix + "/{application}-{profiles}.yml", //
configServerPrefix + "/{application}-{profiles}.yaml", //
configServerPrefix + "/{label}/{application}-{profiles}.yml", //
configServerPrefix + "/{label}/{application}-{profiles}.yaml", //
configServerPrefix + "/{application}/{profiles}/{label}/**", //
}).access("@applicationConfigSecurity.checkAuthentication(#application,#profiles)")//
.anyRequest().hasRole(ADMIN.toString()) //
//.antMatchers("/**").hasRole(USER.toString()) //
.and() //
.csrf().disable() //
.formLogin().disable() //
.httpBasic().and() //
.sessionManagement().sessionCreationPolicy(STATELESS).and() //
;
}
@Bean
public ApplicationConfigSecurity applicationConfigSecurity() {
return new ApplicationConfigSecurity();
}
@Bean
public PrivilegedUserProperties privilegedUserProperties() {
return new PrivilegedUserProperties();
}
@Bean
public GitFileConfigUserDetailsService userDetailsService() {
final GitFileConfigUserDetailsService userDetailsService = new GitFileConfigUserDetailsService();
userDetailsService.setConfigSecurity(this.configSecurity);
userDetailsService.setDefaultLabel(this.configServerProperties.getDefaultLabel());
userDetailsService.setPrivilegedUserProperties(this.privilegedUserProperties());
userDetailsService.setEnvironmentController(this.environmentController);
return userDetailsService;
}
}
}