3

I updated an already existing application from Spring Boot 1.3 to 2.0.1. This application makes use of the Actuator and exposes a REST-style API.

In Boot 1.3 the API could be used without authentication and the actuator endpoint was configured to be password protected:

security.user.name=foo
security.user.password=bar
security-user.role=ADMIN

I updated this like documented in the configuration changelog and renamed the entries from security.user.name to spring.security.user.name and alike.

But when I try to curl my API, I am denied because I do not provide credentials: CURL is denied because unauthenticated access was tried

In the Spring Blog I found a possible solution how to configure Spring Security on a detailled level:

http
    .authorizeRequests()
        // 1
        .requestMatchers(EndpointRequest.to("status", "info"))
            .permitAll()
        // 2
        .requestMatchers(EndpointRequest.toAnyEndpoint())
            .hasRole("ACTUATOR")
        // 3 
        .requestMatchers(StaticResourceRequest.toCommonLocations())
            .permitAll()
        // 4
        .antMatchers("/**")
            .hasRole("USER")
    .and()
  ...

but this is more fine-grained than I need and I am looking for an application.properties based solution.

Is there a way to solve this without additional code ?

Marged
  • 10,577
  • 10
  • 57
  • 99

2 Answers2

9

When you set spring.security.user.name and spring.security.user.password, you are configuring form login via spring-security for the whole application, including the Actuator endpoints.

Unfortunately, in Spring Boot 2.0 you cannot set a different username/password or disable authentication for the Actuator endpoints using the properties. This means you have to explicitly allow the actuator endpoints through Security configuration.

Through spring-security, you can also allow public access to your endpoints and require credentials for the actuator endpoints very easily:

@Configuration
public class BasicSecurityConfig extends WebSecurityConfigurerAdapter {

    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/actuator/**").hasRole("ACTUATOR")
                .anyRequest().permitAll();
    }
}

(I assumed you were using WebMvc, not WebFlux, which is a bit different)

Verify that you have the following in the application.properties:

spring.security.user.name=user
spring.security.user.password=pass
spring.security.user.roles=ACTUATOR,USER   # and others, if you like

management.endpoint.health.roles=ACTUATOR

See here for a quick and nice explanation between the differences in Actuator in Spring 1.x vs 2.0.

MuratOzkan
  • 2,599
  • 13
  • 25
  • And how would this need to look like when I want all other - that means those not equal to `/actuator` - unprotected ? – Marged May 11 '18 at 15:06
  • This configuration is exactly that! It requires ACTUATOR role only for paths starting with `/actuator`. For everything else, it doesn't require any credentials. – MuratOzkan May 12 '18 at 07:40
  • Today I had the time to finally try this. Unfortunately the REST service is still protected while the Actuator asks for a password too. The class is contained in the JAR but obviously not used / not working. Other classes with @Configuration annotation that I stored in the same package are used and I can see them in the beans. – Marged Jul 10 '18 at 13:48
  • Well, you have to make sure that this configuration is available as a bean or it won't work. I tested this with 2.0.2.RELEASE. Try making a barebones project to verify. – MuratOzkan Jul 10 '18 at 13:57
  • How would I write test for just checking the authentication functionality? – JonB Feb 27 '19 at 13:24
2

For Spring Boot 2.0, when we override the configure method of WebSecurityConfigurerAdapter all existing security backs off and we can provide our custom security. In your case you just need to authenticate the actuator endpoints, which can be done as follows:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {  
        http.authorizeRequests().antMatchers("/actuator/**").authenticated();
    }

}

No changes are required in the application.properties file.