Spring Boot Actuator offers powerful insights into your application’s internals, enabling production-grade monitoring and management. However, if misconfigured, these same tools can expose sensitive information, leading to serious security breaches. A notable example of this occurred when researchers discovered an unprotected Spring Boot Actuator endpoint in a Volkswagen telematics service. A single open /actuator/heapdump
endpoint granted access to a heap dump containing AWS credentials in plaintext. Those credentials led to the download of 9 terabytes of GPS data from hundreds of thousands of cars.
This blog post aims to be a detailed, practical guide on how to use Spring Boot Actuator securely in Kubernetes environments (Amazon EKS and Azure AKS), while still leveraging its capabilities for health checks and Prometheus-based monitoring. We’ll cover secure endpoint exposure, access control with Spring Security, Traefik ingress configuration, and Helm deployment patterns. The guide will also highlight common pitfalls and lessons from the Volkswagen incident.
The Danger of Misconfigured Actuator Endpoints
The Volkswagen data breach demonstrates how powerful observability tools can become liabilities. In this case, the application exposed the /actuator/heapdump
endpoint without authentication. When a heap dump is generated, it includes the entire memory contents of the JVM — including secrets, credentials, tokens, and sensitive data.
An attacker obtained plaintext AWS keys from this heap dump, which then provided access to an S3 bucket storing terabytes of vehicle tracking data. This breach did not involve a zero-day vulnerability, but rather a classic example of poor configuration.
Actuator Endpoint Overview and Exposure Matrix
Spring Boot Actuator provides a number of endpoints under /actuator/*
. Some are safe to expose publicly, some are only safe internally, and others should never be exposed under any circumstances.
Endpoint | Purpose | Risk Level | Recommended Exposure |
---|---|---|---|
/health | App health status | Low | Public (unauthenticated) for probes |
/prometheus | Prometheus metrics | Medium | Internal network only |
/metrics | Raw metrics | Medium | Internal or authenticated only |
/env | Configuration/environment values | High | Never |
/heapdump | Full memory dump | Critical | Never |
/beans | Spring bean map | Medium | Internal, authenticated |
/loggers | Dynamic log level management | High | Internal, admin-only |
/mappings | Endpoint mapping overview | Medium | Internal, authenticated |
/shutdown | Graceful shutdown | High | Never (disabled by default) |
Secure Configuration in application.yml
Limit the exposed endpoints explicitly:
management:
endpoints:
web:
exposure:
include: health,prometheus
exclude: env,heapdump,beans,loggers,threaddump,shutdown
endpoint:
health:
show-details: never
probes:
enabled: true
This ensures only Kubernetes-friendly health checks and Prometheus metrics are exposed, without detailed component-level health info to unauthenticated users.
Adding Spring Security to Protect Endpoints
To lock down the sensitive endpoints, Spring Security should be configured using the modern SecurityFilterChain
setup:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authz -> authz
.requestMatchers("/actuator/health", "/actuator/health/**", "/actuator/prometheus").permitAll()
.requestMatchers("/actuator/**").hasRole("ACTUATOR")
.anyRequest().authenticated())
.httpBasic()
.and()
.csrf().disable();
return http.build();
}
}
Create a user with the ACTUATOR role in your configuration:
spring:
security:
user:
name: actuator_user
password: ${ACTUATOR_PASSWORD}
roles: ACTUATOR
Store passwords in Kubernetes Secrets and inject them via environment variables.
Kubernetes Liveness/Readiness Probes
Expose Kubernetes-friendly endpoints using Spring Boot’s probe support:
management:
endpoint:
health:
probes:
enabled: true
show-details: never
health:
livenessState:
enabled: true
readinessState:
enabled: true
Deployment probe example:
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
These endpoints return simple status checks and don’t require authentication, which is important for compatibility with Kubernetes.
Prometheus Scraping
To enable Prometheus scraping:
- Add Micrometer’s Prometheus registry to your dependencies.
- Expose
/actuator/prometheus
in your application. - Ensure Prometheus has access via service discovery or annotations.
For secure setups, allow access from only known IP ranges (e.g., monitoring namespace) or use basic auth.
Traefik Ingress Protection
To restrict public access to sensitive endpoints, configure Traefik ingress rules and middleware.
Example ingress annotations:
traefik.ingress.kubernetes.io/auth-type: "basic"
traefik.ingress.kubernetes.io/auth-secret: "actuator-auth-secret"
traefik.ingress.kubernetes.io/auth-realm: "Protected Area"
You can isolate the /actuator
path with these annotations in a separate rule, applying Basic Auth just to that path.
Network Policies for Cluster-Level Protection
Use Kubernetes network policies to restrict which namespaces or pods can reach your application’s Actuator endpoints.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-actuator
spec:
podSelector:
matchLabels:
app: my-spring-app
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 8080
This ensures that only Prometheus or known services can access the Actuator endpoints.
Summary
Using Spring Boot Actuator in a Kubernetes environment requires careful planning and security awareness. You need to:
- Limit exposed endpoints using Spring Boot configuration.
- Protect all but the essential endpoints with Spring Security.
- Use Traefik ingress rules to guard external access.
- Apply network policies and TLS for internal traffic control.
The Volkswagen data leak could have been prevented with proper Actuator endpoint configuration. This guide ensures your deployment remains observable without compromising security.
When in doubt, keep it locked down. Start with nothing exposed, then open only what’s necessary.