1

In Spring Boot version 2.2 I have an implementation of HandlerInterceptor and expose info, health, shutdown endpoints of Actuator.

I'd like to set that interceptor only for the shutdown endpoint, but not sure how to do it.

Already know that the code on the following page is useful for setting an interceptor for all endpoints.

@Configuration
public class ActuatorConfig extends WebMvcEndpointManagementContextConfiguration {

  @Autowired
  private AuthenticationInterceptor authenticationInterceptor;

  public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebAnnotationEndpointDiscoverer endpointDiscoverer,
                                                                       EndpointMediaTypes endpointMediaTypes,
                                                                       CorsEndpointProperties corsProperties,
                                                                       WebEndpointProperties webEndpointProperties) {
    WebMvcEndpointHandlerMapping mapping = super.webEndpointServletHandlerMapping(
      endpointDiscoverer,
      endpointMediaTypes,
      corsProperties,
      webEndpointProperties);

    mapping.setInterceptors(authenticationInterceptor);

    return mapping;
  }
}

Also I checked this page

ksky8864
  • 57
  • 4

1 Answers1

1

The comments from spring team on github issue link suggest to create a filter for intercepting actuator endpoint.

You can create a servlet filter and add authentication logic.

Here is a example:

@Component
public class ActuatorFilter implements Filter {
    private final BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor();
    private String encryptedPassword;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        try {
            File file = ResourceUtils.getFile("classpath:password.txt");
            try (FileReader reader = new FileReader(file)) {
                char[] chars = new char[(int) file.length()];
                reader.read(chars);
                encryptedPassword = new String(chars);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        String url = request.getRequestURI().toString();
        String rawPassword = request.getHeader("Authorization");

        if(url.equals("/actuator/shutdown") && !passwordEncryptor.checkPassword(rawPassword,encryptedPassword)){
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            PrintWriter out = response.getWriter();
            out.print("Invalid password");
            out.flush();
            return;
        }
        chain.doFilter(req, res);
    }

    @Override
    public void destroy() { }
}

In the above code i have used jasypt for encrypting password and matching it in filter.

You can use new BasicPasswordEncryptor().encryptPassword(rawPassword); to get a encrypted password and save it in either DB or file. In the above code i have saved the encrypted password in password.txt in resources folder

enter image description here

Ajit Soman
  • 3,926
  • 3
  • 22
  • 41