DEV Community

Cover image for Spring Boot Actuator: qué exponer, qué ocultar y qué mirar antes de agregar endpoints
Juan Torchia
Juan Torchia Subscriber

Posted on • Originally published at juanchi.dev

Spring Boot Actuator: qué exponer, qué ocultar y qué mirar antes de agregar endpoints

Spring Boot Actuator: qué exponer, qué ocultar y qué mirar antes de agregar endpoints

Hay una configuración que aparece en casi todos los tutoriales de Spring Boot y que se copia sin leerla bien:

management:
  endpoints:
    web:
      exposure:
        include: "*"
Enter fullscreen mode Exit fullscreen mode

Un asterisco. Todos los endpoints. De una. Y el tutorial sigue con el paso siguiente sin detenerse un segundo en lo que eso significa.

Mi tesis es simple: Actuator no es malo. El error es habilitarlo sin una política clara de qué exponer, qué restringir y para quién. Esa diferencia entre herramienta operativa y superficie pública innecesaria no la resuelve Spring Boot solo: la resolvés vos con criterio explícito.

Tengo más de treinta años de historia con la tecnología, y uno de los patrones que más veo repetirse no es el bug dramático que tira producción: es la decisión pequeña tomada sin política, que se acumula hasta que alguien la encuentra desde afuera.


Spring Boot Actuator endpoints seguridad: qué dice la documentación y qué no dice

La documentación oficial de Spring Boot Actuator es clara en algo que los tutoriales suelen saltear: por defecto, sobre HTTP solo están habilitados health e info. El resto existe pero no se expone automáticamente.

Lo que la documentación describe con precisión:

  • La distinción entre habilitar un endpoint (que exista en el contexto) y exponerlo (que sea accesible por HTTP o JMX).
  • Que shutdown está habilitado pero no expuesto por defecto, precisamente porque su impacto es irreversible.
  • Que env y configprops pueden mostrar valores sensibles, y que Spring Boot ofrece sanitización configurable para esos casos.
  • Que la seguridad de los endpoints es responsabilidad del desarrollador: Spring Boot no agrega autenticación automática sobre Actuator.

Lo que la documentación no resuelve por vos:

  • Qué endpoints tienen sentido para vos operación concreta.
  • Si el puerto de management está separado del puerto de la app o compartido.
  • Si hay un proxy, API gateway o balanceador de carga delante que filtra o no esas rutas.
  • Si el equipo que opera el sistema tiene acceso diferenciado del tráfico público.

Esa brecha entre "lo que Spring Boot configura por defecto" y "lo que necesitás en producción" es exactamente donde se acumulan las decisiones implícitas.


El error más común: habilitar todo y securizar después (o nunca)

La receta que circula en tutoriales, Stack Overflow y repositorios de ejemplo suele tener esta forma:

# application.yml — patrón común que vale revisar antes de copiar
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always
Enter fullscreen mode Exit fullscreen mode

El costo oculto de este patrón no es que "sea peligroso" en abstracto. El costo concreto es que:

  1. /actuator/env expone variables de entorno, incluyendo claves, URLs de base de datos y tokens si no están sanitizadas.
  2. /actuator/heapdump puede devolver un dump del heap de la JVM, que en muchos sistemas contiene datos en memoria.
  3. /actuator/shutdown permite apagar la aplicación vía HTTP POST si está habilitado y expuesto.
  4. /actuator/loggers permite cambiar el nivel de logging en caliente, lo que puede generar ruido operativo o exponer información de diagnóstico.

Ninguno de esos endpoints es malo en sí mismo. heapdump es invaluable para diagnosticar un leak de memoria. loggers es exactamente la herramienta que querés cuando necesitás DEBUG sin reiniciar. El problema es exponerlos sin decidir quién puede acceder y desde dónde.

La comparación que me resulta útil: es parecido a lo que pasa con los Docker healthchecks. Un healthcheck mal diseñado no falla porque Docker sea malo; falla porque nadie definió qué significa "sano" para ese contenedor en particular. Con Actuator pasa lo mismo: la herramienta es sólida, pero el criterio de exposición tiene que ser explícito.


Matriz de decisión: qué exponer, qué restringir, qué directamente no habilitar

Esta matriz es un criterio prudente, no una regla absoluta. Cada fila representa un análisis que vale hacer antes de incluir ese endpoint.

Endpoint ¿Qué expone? Criterio recomendado
health Estado de la app y sus dependencias Exponer. show-details: when-authorized en producción
info Metadata de build, versión, git commit Exponer si hay datos útiles. No expone nada sensible por defecto
metrics Métricas JVM, HTTP, custom Exponer solo a sistemas de monitoreo internos (Prometheus, etc.)
loggers Niveles de logging actuales Restringir a operadores. Útil, pero con acceso controlado
env Variables de entorno Restringir. Revisar sanitización antes de habilitar
configprops Propiedades de configuración Restringir. Puede mostrar valores sensibles
heapdump Dump del heap de la JVM Solo en ambientes controlados. No en producción pública
threaddump Estado de los threads activos Útil para diagnóstico. Restringir a operadores
shutdown Apaga la aplicación No habilitar salvo que haya una razón operativa muy clara
mappings Todos los endpoints REST de la app Información de superficie. Restringir
beans Todos los beans del contexto Spring Solo en desarrollo. No en producción

La configuración que yo usaría como punto de partida en un ambiente productivo:

# application.yml — punto de partida prudente para producción
management:
  server:
    port: 8081  # puerto separado, no expuesto públicamente
  endpoints:
    web:
      exposure:
        include: health, info, metrics, loggers
  endpoint:
    health:
      show-details: when-authorized
    env:
      enabled: false  # deshabilitar si no hay política de sanitización definida
Enter fullscreen mode Exit fullscreen mode

Separar el puerto de management (management.server.port) del puerto de la aplicación es una decisión que simplifica mucho la política: el tráfico interno llega al 8081, el tráfico público no tiene acceso a ese puerto en absoluto. Es una forma de convertir la seguridad en una propiedad estructural en lugar de depender solo de autenticación.


Lo que no podés concluir sin experimento, logs o datos propios

Hay un límite honesto que vale nombrar. Esta guía está basada en la documentación oficial y en análisis prudente. Lo que no podés concluir solo con esto:

  • Que vos configuración actual es segura: eso requiere revisar qué hay delante de la aplicación (proxy, gateway, firewall) y cómo está configurado.
  • Que separar el puerto de management es suficiente: si el puerto 8081 está expuesto en el security group o en el firewall de red, la separación no sirve.
  • Que la sanitización de env cubre todas las claves sensibles: Spring Boot sanitiza por patrones conocidos (password, secret, key, etc.), pero si usás nombres de variables no convencionales, vale verificarlo.
  • Que agregar Spring Security sobre Actuator es la única solución: también podés resolver el acceso a nivel de red, de proxy o de ingress. La capa correcta depende de la arquitectura.

Si querés inspeccionar qué tráfico llega realmente a los endpoints de management en un ambiente local, una herramienta como Sniffnet puede ayudarte a visualizar conexiones sin meterte en tcpdump desde el primer momento.


FAQ: Spring Boot Actuator endpoints seguridad

¿Cuáles son los endpoints de Actuator que están habilitados por defecto?

Según la documentación oficial, sobre HTTP solo health e info están expuestos por defecto. El resto están habilitados en el contexto pero no accesibles por HTTP. La excepción es shutdown, que no está habilitado por defecto justamente por su impacto.

¿Qué diferencia hay entre habilitar y exponer un endpoint?

Habilitar significa que el endpoint existe en el contexto de Spring y puede ser invocado internamente. Exponer significa que es accesible desde el exterior (HTTP o JMX). Podés tener un endpoint habilitado y no expuesto: existe pero nadie puede llamarlo desde fuera. La propiedad management.endpoints.web.exposure.include controla la exposición HTTP.

¿Es suficiente con Spring Security para proteger Actuator?

Spring Security es una capa válida, pero no es la única ni necesariamente la primera línea. Separar el puerto de management y restringir acceso a ese puerto a nivel de red o proxy es una política más robusta porque no depende de la correcta configuración de cada regla de seguridad en el código. Idealmente, ambas capas conviven.

¿/actuator/health expone información sensible?

Con la configuración por defecto, health devuelve solo el estado (UP o DOWN). El detalle de dependencias (base de datos, disco, etc.) aparece solo si configurás show-details: always. La opción intermedia y más razonable en producción es show-details: when-authorized: el sistema de monitoreo ve el detalle, el tráfico anónimo no.

¿Qué pasa si uso include: "*" en producción?

Se exponen todos los endpoints habilitados, incluyendo env, configprops, heapdump y potencialmente shutdown si lo habilitaste. No es una configuración inválida en todos los contextos, pero requiere que el acceso al puerto de management esté completamente restringido a sistemas internos. Si ese puerto es accesible públicamente, cualquiera puede consultar variables de entorno o pedir un dump del heap.

¿Cómo valido qué endpoints están realmente expuestos en mi app?

El endpoint /actuator devuelve un JSON con los endpoints activos y sus URLs. Es el primer lugar donde mirar. También podés revisar los logs de startup de Spring Boot: loguea los endpoints registrados si tenés el nivel adecuado. Y si tenés Prometheus o cualquier sistema de scraping configurado, verificá que solo raspe el puerto de management y no el puerto público.


Mi postura: Actuator es una herramienta operativa, no una opción de conveniencia

Cuando vi por primera vez la anécdota de Docker que mencioné al principio del post sobre healthchecks, lo que me quedó fue la misma lección que aplica acá: el valor de la herramienta está en describir un contrato explícito, no en activarla y ver qué pasa.

Con Actuator es igual. No es una feature que "agregás" a la app. Es una política de observabilidad que define qué información operativa se expone, a quién y desde dónde. Esa política puede ser tan simple como dos líneas en el YAML o tan elaborada como roles diferenciados con Spring Security, pero tiene que existir de forma consciente.

Lo incómodo es que el tutorial que más circula muestra el include: "*" como si fuera el paso natural. Y técnicamente funciona. Pero "funciona" y "es una decisión tomada con criterio" son cosas distintas, y la diferencia importa cuando el sistema crece.

La decisión práctica para el próximo paso es esta: abrí el application.yml del proyecto en el que estás trabajando ahora, buscá la sección management.endpoints, y preguntate si lo que está ahí es una política explícita o el resultado de copiar un tutorial sin cuestionarlo. Si es lo segundo, dedicale quince minutos antes de que el sistema salga a un ambiente compartido.

No porque Actuator sea peligroso. Sino porque las decisiones implícitas son las que se acumulan.


Fuentes:


Este artículo fue publicado originalmente en juanchi.dev

Top comments (0)