Use oauth2 scope instead of role to secure spring actuator management endpoints

I've upgraded to Spring Cloud Dalston recently, that means Spring Boot 1.5.1, and I can not secure the management endpoints by checking an oauth2 scope anymore. It worked before in Spring Cloud Camden.

This is the configuration that worked before :

@Configuration
public class SecurityConfiguration extends ResourceServerConfigurerAdapter {

    @Value("${management.context-path}")
    private String managementContextPath;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() 
                // some paths I don't want to secure at all
                .antMatchers("/path1/**", "/path2/**").permitAll() 
                // access to health endpoint is open to anyone
                .antMatchers(HttpMethod.GET, managementContextPath + "/health").permitAll() 
                // but app.admin scope is necessary for other management endpoints
                .antMatchers(managementContextPath + "/**").access("#oauth2.hasScope('my-super-scope')") //
                // And we make sure the user is authenticated for all the other cases
                .anyRequest().authenticated();
    }
}

And this is the important part of the config :

security:
  oauth2:
    client:
      clientId: a-client
      clientSecret: the-client-password
    resource:
      tokenInfoUri: http://my-spring-oauth2-provider/oauth/check_token

management:
  context-path: /my-context
  security:
    enabled: true
endpoints:
  health:
    sensitive: false

When I try to POST on /my-context/refresh I get a HTTP 401 "Full authentication is needed" even though I give a valid OAuth2 token

Looking through the log I saw that my request was considered anonymous, and checking the FilterChainProxy log saw that the OAuth2AuthenticationProcessingFilter was not called. After a bit of digging I found that I could change the oauth2 resource filter order, so I tried that and now I have an OAuth2 authentication, yeah, finished right ?

Hum, no, now I have an Access is denied. User must have one of the these roles: ACTUATOR error.

I tried a few other things, including disabling management security (but my rules are not applied and access is open to everyone), playing with (ugh) @Order (no change), and even, lo and behold, reading and applying the documentation which says :

To override the application access rules add a @Bean of type WebSecurityConfigurerAdapter and use @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) if you don’t want to override the actuator access rules, or @Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER) if you do want to override the actuator access rules.

But this did not change the error : User must have one of these roles: ACTUATOR

Does anybody have a workaround/idea ?


Update : I'm also using Zuul, so I finally created a specific zuul route to the endpoint I needed (cloud bus refresh in my case), unprotected on an other backend service that was not exposed otherwise, and protected that zuul route with oauth2.

I'm leaving this question here nevertheless, if anyone finds a workaround, could be useful.

Upvotes: 3

Views: 1925

Answers (2)

RemusS
RemusS

Reputation: 1545

I confronted with this issue also. The workaround that I used was to expose the actuator action on a new endpoint which I defined, and just call the actuator bean to handle request.

For example to secure /my-context/refresh with Oauth2 , I just expose a new resource at {whatever-api-prefix}/refreshConfig and I exposed a request handler on the rest controller for this URL; in the rest controller I wire the RefreshEndpoint bean and in the request handler I just call the refreshEndpoint.refresh().

Upvotes: 1

Ion Pana
Ion Pana

Reputation: 21

Probably being captain obvious, but see http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-monitoring.html. You can override the role with management.security.roles and simply add whatever role your Oauth2 credentials have.

Upvotes: 2

Related Questions