Shervin Asgari
Shervin Asgari

Reputation: 24509

Spring security gives access denied on /actuator/health

I am trying to understand why Spring security gives access denied on /actuator/health Can anyone spot the problem?

The logs says:

27/02/2020 11:24:57.902 [http-nio-4104-exec-1] [,,] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/actuator/health'; against '/actuator/**'
27/02/2020 11:24:57.902 [http-nio-4104-exec-1] [,,] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /actuator/health; Attributes: [hasIpAddress('127.0.0.1/32')]
27/02/2020 11:24:57.902 [http-nio-4104-exec-1] [,,] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@187dbd2d: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
27/02/2020 11:24:57.909 [http-nio-4104-exec-1] [,,] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@790ce264, returned: -1
27/02/2020 11:24:57.912 [http-nio-4104-exec-1] [,,] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at no.gjensidige.bank.nasasupport.jwt.JwtTokenFilter.doFilterInternal(JwtTokenFilter.java:60) [15 skipped]
at ch.qos.logback.access.tomcat.LogbackValve.invoke(LogbackValve.java:256) [41 skipped]
at java.base/java.lang.Thread.run(Thread.java:830) [13 skipped]


http
                .antMatcher("/**") // If you want to override the security provided by Spring Boot.
                .cors().and()
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/actuator/**")
                .access("hasIpAddress('127.0.0.1/32')")
                .antMatchers("/api")
                .hasAnyAuthority("not important")
  .antMatchers("/actuator/health", "/open/**")
                .permitAll()
                .anyRequest()
                .denyAll();

Anyone spot the error? I am using spring-boot-2.2.2.RELEASE

I had to add this: @SpringBootApplication(exclude = {UserDetailsServiceAutoConfiguration.class}) to remove the default generated password. I get the same error if UserDetailsServiceAutoConfiguration is excluded or not.

Upvotes: 2

Views: 8498

Answers (3)

Shervin Asgari
Shervin Asgari

Reputation: 24509

I found the problem. I don't know why our configuration didn't work, but I change the order. I defined /actuator/health permitAll() first, then defined /actuator/** access after.

http.antMatcher("/**")
            .cors().and()
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/actuator/health", "/open/**")
            .permitAll()
            .antMatchers("/actuator/**")
            .access("hasIpAddress('127.0.0.1/32')")
            .antMatchers("/api")
            .hasAnyAuthority("not important")
            .anyRequest()
            .denyAll();

Upvotes: 0

Ralf
Ralf

Reputation: 6853

We use this configuration to achieve what seems similar to your requirements: The health and prometheus endpoints must be accessible without authentication. Any request is permitted from localhost (running Docker container in our case) or from anywhere for authenticated users.

private static final String ACTUATOR_BASE                = "/actuator";
private static final String MATCHERS_ACTUATOR_HEALTH     = ACTUATOR_BASE + "/health";
private static final String MATCHERS_ACTUATOR_PROMETHEUS = ACTUATOR_BASE + "/prometheus";

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .antMatchers(MATCHERS_ACTUATOR_HEALTH).permitAll()
        .antMatchers(MATCHERS_ACTUATOR_PROMETHEUS).permitAll()
        .anyRequest()
        .access("hasIpAddress('127.0.0.0/8') or hasIpAddress('::1') or isAuthenticated()")
        .and()
        .httpBasic()
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

Upvotes: 2

Pranjal Gore
Pranjal Gore

Reputation: 592

As soon as you add the Actuator to a secure application you get an additional filter chain that applies only to the actuator endpoints. It has an order of ManagementServerProperties.BASIC_AUTH_ORDER. If you want your application security rules to apply to the actuator endpoints you can add a filter chain ordered earlier than the actuator one, this can be done using ManagementServerProperties.ACCESS_OVERRIDE_ORDER. In short, try doing this:

@Configuration
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter {
    // your implementation
}

Reference

Upvotes: 0

Related Questions