Commit 06c80c46 by Johannes Edmeier

Enable CSRF-Protection possible and update samples

closes #805
parent 2de93933
...@@ -11,6 +11,13 @@ A Spring Security configuration could look like this: ...@@ -11,6 +11,13 @@ A Spring Security configuration could look like this:
---- ----
include::{samples-dir}/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/SpringBootAdminApplication.java[tags=configuration-spring-security] include::{samples-dir}/spring-boot-admin-sample-servlet/src/main/java/de/codecentric/boot/admin/SpringBootAdminApplication.java[tags=configuration-spring-security]
---- ----
<1> Grants public access to all static assets and the login page.
<2> Every other request must be authenticated.
<3> Configures login and logout.
<4> Enables HTTP-Basic support. This is needed for the Spring Boot Admin Client to register.
<5> Enables CSRF-Protection using Cookies
<6> Disables CRSF-Protection the endpoint the Spring Boot Admin Client uses to register.
<7> Disables CRSF-Protection for the actuator endpoints.
For a complete sample look at https://github.com/codecentric/spring-boot-admin/tree/master/spring-boot-admin-samples/spring-boot-admin-sample-servlet/[spring-boot-admin-sample-servlet. For a complete sample look at https://github.com/codecentric/spring-boot-admin/tree/master/spring-boot-admin-samples/spring-boot-admin-sample-servlet/[spring-boot-admin-sample-servlet.
...@@ -50,3 +57,16 @@ WARNING: You should configure HTTPS for your SBA Server or (service registry) wh ...@@ -50,3 +57,16 @@ WARNING: You should configure HTTPS for your SBA Server or (service registry) wh
WARNING: When using Spring Cloud Discovery, you must be aware that anybody who can query your service registry can obtain the credentials. WARNING: When using Spring Cloud Discovery, you must be aware that anybody who can query your service registry can obtain the credentials.
TIP: When using this approach the SBA Server decides whether or not the user can access the registered applications. There are more complex solutions possible (using OAuth2) to let the clients decide if the user can access the endpoints. For that please have a look at the samples in https://github.com/joshiste/spring-boot-admin-samples[joshiste/spring-boot-admin-samples^]. TIP: When using this approach the SBA Server decides whether or not the user can access the registered applications. There are more complex solutions possible (using OAuth2) to let the clients decide if the user can access the endpoints. For that please have a look at the samples in https://github.com/joshiste/spring-boot-admin-samples[joshiste/spring-boot-admin-samples^].
==== CSRF on Actuator Endpoints ====
Some of the actuator endpoints (e.g. `/loggers`) support POST requests. When using Spring Security you need to ignore the actuator endpoints for CSRF-Protection as the Spring Boot Admin Server currently lacks support.
[source,java]
----
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.ignoringAntMatchers("/actuator/**");
}
----
...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Profile; ...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Profile;
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.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
...@@ -39,8 +40,13 @@ public class SpringBootAdminApplication { ...@@ -39,8 +40,13 @@ public class SpringBootAdminApplication {
public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()// http.authorizeRequests()
.and().csrf().disable(); .anyRequest()
.permitAll()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
} }
} }
...@@ -67,7 +73,9 @@ public class SpringBootAdminApplication { ...@@ -67,7 +73,9 @@ public class SpringBootAdminApplication {
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and() .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and() .logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and() .httpBasic().and()
.csrf().disable(); .csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
// @formatter:on // @formatter:on
} }
} }
......
...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Profile; ...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Profile;
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.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
...@@ -42,8 +43,13 @@ public class SpringBootAdminApplication { ...@@ -42,8 +43,13 @@ public class SpringBootAdminApplication {
public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()// http.authorizeRequests()
.and().csrf().disable(); .anyRequest()
.permitAll()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
} }
} }
...@@ -70,7 +76,9 @@ public class SpringBootAdminApplication { ...@@ -70,7 +76,9 @@ public class SpringBootAdminApplication {
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and() .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and() .logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and() .httpBasic().and()
.csrf().disable(); .csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
// @formatter:on // @formatter:on
} }
} }
......
...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Profile; ...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Profile;
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.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import com.hazelcast.config.Config; import com.hazelcast.config.Config;
import com.hazelcast.config.EvictionPolicy; import com.hazelcast.config.EvictionPolicy;
import com.hazelcast.config.InMemoryFormat; import com.hazelcast.config.InMemoryFormat;
...@@ -50,8 +51,13 @@ public class SpringBootAdminApplication { ...@@ -50,8 +51,13 @@ public class SpringBootAdminApplication {
public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()// http.authorizeRequests()
.and().csrf().disable(); .anyRequest()
.permitAll()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
} }
} }
...@@ -78,7 +84,9 @@ public class SpringBootAdminApplication { ...@@ -78,7 +84,9 @@ public class SpringBootAdminApplication {
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and() .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and() .logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and() .httpBasic().and()
.csrf().disable(); .csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
// @formatter:on // @formatter:on
} }
} }
......
...@@ -42,6 +42,7 @@ import org.springframework.http.HttpMethod; ...@@ -42,6 +42,7 @@ import org.springframework.http.HttpMethod;
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.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
...@@ -59,8 +60,13 @@ public class SpringBootAdminApplication { ...@@ -59,8 +60,13 @@ public class SpringBootAdminApplication {
public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()// http.authorizeRequests()
.and().csrf().disable(); .anyRequest()
.permitAll()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
} }
} }
...@@ -81,14 +87,19 @@ public class SpringBootAdminApplication { ...@@ -81,14 +87,19 @@ public class SpringBootAdminApplication {
successHandler.setTargetUrlParameter("redirectTo"); successHandler.setTargetUrlParameter("redirectTo");
http.authorizeRequests() http.authorizeRequests()
.antMatchers(adminContextPath + "/assets/**").permitAll() .antMatchers(adminContextPath + "/assets/**").permitAll() // <1>
.antMatchers(adminContextPath + "/login").permitAll() .antMatchers(adminContextPath + "/login").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated() // <2>
.and() .and()
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and() .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and() // <3>
.logout().logoutUrl(adminContextPath + "/logout").and() .logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and() .httpBasic().and() // <4>
.csrf().disable(); .csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // <5>
.ignoringAntMatchers(
"/instances", // <6>
"/actuator/**" // <7>
);
// @formatter:on // @formatter:on
} }
} }
......
...@@ -28,6 +28,7 @@ import org.springframework.context.annotation.Profile; ...@@ -28,6 +28,7 @@ import org.springframework.context.annotation.Profile;
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.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
...@@ -44,8 +45,13 @@ public class SpringBootAdminApplication extends SpringBootServletInitializer { ...@@ -44,8 +45,13 @@ public class SpringBootAdminApplication extends SpringBootServletInitializer {
public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()// http.authorizeRequests()
.and().csrf().disable(); .anyRequest()
.permitAll()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
} }
} }
...@@ -72,7 +78,9 @@ public class SpringBootAdminApplication extends SpringBootServletInitializer { ...@@ -72,7 +78,9 @@ public class SpringBootAdminApplication extends SpringBootServletInitializer {
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and() .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and() .logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and() .httpBasic().and()
.csrf().disable(); .csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
// @formatter:on // @formatter:on
} }
} }
......
...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Profile; ...@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Profile;
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.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
...@@ -38,8 +39,13 @@ public class SpringBootAdminApplication { ...@@ -38,8 +39,13 @@ public class SpringBootAdminApplication {
public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter { public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()// http.authorizeRequests()
.and().csrf().disable(); .anyRequest()
.permitAll()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
} }
} }
...@@ -66,7 +72,9 @@ public class SpringBootAdminApplication { ...@@ -66,7 +72,9 @@ public class SpringBootAdminApplication {
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and() .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and() .logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and() .httpBasic().and()
.csrf().disable(); .csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringAntMatchers("/instances", "/actuator/**");
// @formatter:on // @formatter:on
} }
} }
......
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
</figure> </figure>
<h1 class="title has-text-primary">Spring Boot Admin</h1> <h1 class="title has-text-primary">Spring Boot Admin</h1>
<form method="post"> <form method="post">
<input type="hidden"
th:if="${_csrf}"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}"/>
<div class="field"> <div class="field">
<p class="is-medium has-text-danger" th:unless="${param.error == null}"> <p class="is-medium has-text-danger" th:unless="${param.error == null}">
Invalid username or password Invalid username or password
......
...@@ -21,9 +21,11 @@ import {Observable} from '@/utils/rxjs' ...@@ -21,9 +21,11 @@ import {Observable} from '@/utils/rxjs'
import uri from '@/utils/uri'; import uri from '@/utils/uri';
import _ from 'lodash'; import _ from 'lodash';
const actuatorMimeTypes = ['application/vnd.spring-boot.actuator.v2+json', const actuatorMimeTypes = [
'application/vnd.spring-boot.actuator.v2+json',
'application/vnd.spring-boot.actuator.v1+json', 'application/vnd.spring-boot.actuator.v1+json',
'application/json']; 'application/json'
];
class Instance { class Instance {
constructor(id) { constructor(id) {
......
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