springboot06:Actuator


spring boot06:Actuator

什么是 Spring Boot Actuator

Spring Boot Actuator 模块提供了生产级别的功能,比如健康检查,审计,指标收集,HTTP 跟踪等,帮助我们监控和管理Spring Boot 应用。这个模块是一个采集应用内部信息暴露给外部的模块,上述的功能都可以通过HTTP 和 JMX 访问。

因为暴露内部信息的特性,Actuator 也可以和一些外部的应用监控系统整合(Prometheus, Graphite, DataDog, Influx, Wavefront, New Relic等)。这些监控系统提供了出色的仪表板,图形,分析和警报,可帮助你通过一个统一友好的界面,监视和管理你的应用程序。

Actuator使用Micrometer与这些外部应用程序监视系统集成。这样一来,只需很少的配置即可轻松集成外部的监控系统。

Micrometer 为 Java 平台上的性能数据收集提供了一个通用的 API,应用程序只需要使用 Micrometer 的通用 API 来收集性能指标即可。Micrometer 会负责完成与不同监控系统的适配工作。这就使得切换监控系统变得很容易。

对比 Slf4j 之于 Java Logger 中的定位。

MAVEN依赖项

<dependency>
    <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

只要加上了该 maven 依赖,SpringBoot 在运行時就会自动开启/actuator/health/actuator/info这两个 endpoint,我们就可以透过这两个 endpoint 查看 SpringBoot 运行的情況。

Endpoints

端点,给外部来与应用程序进行访问和交互。

介绍

打比方来说,/health 端点 提供了关于应用健康情况的一些基础信息。/metrics 端点提供了一些有用的应用程序指标(JVM 内存使用、系统CPU使用等)。

这些 Actuator 模块本来就有的端点我们称之为原生端点。根据端点的作用的话,我们大概可以分为三大类:

  • 应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与Spring Boot应用密切相关的配置类信息。
  • 度量指标类:获取应用程序运行过程中用于监控的度量指标,比如:内存信息、线程池信息、HTTP请求统计等。
  • 操作控制类:提供了对应用的关闭等操作类功能。

endpoint 是我们使用 Spring Boot Actuator 最需要关心的对象,列举一些你可能感兴趣的 endpoint

ID Description
beans 查看 Spring 容器中的所有对象
configprops 查看被 @ConfigurationProperties 修饰的对象列表
env 查看 application.yaml 配置的环境配置信息
health 健康检查端点
info 应用信息
metrics 统计信息
mappings 服务契约 @RequestMapping 相关的端点
shutdown 优雅下线

例如 health,只需要访问如下 endpoint 即可获取应用的状态

curl "localhost:8080/actuator/health"

了解 endpoint 的 enable 和 exposure 状态

Spring Boot Actuator 针对于所有 endpoint 都提供了两种状态的配置

  • enabled 启用状态。默认情况下除了 shutdown 之外,其他 endpoint 都是启用状态。这也很好理解,其他 endpoint 基本都是查看行为,shutdown 却会影响应用的运行状态。
  • exposure 暴露状态。endpoint 的 enabled 设置为 true 后,还需要暴露一次,才能够被访问,默认情况下只有 health 和 info 是暴露的。

需要注意的就是:

  • 每一个端点都可以通过配置来单独禁用或者启动
  • enabled 不启用时,相关的 endpoint 的代码完全不会被 Spring 上下文加载,所以 enabled 为 false 时,exposure 配置了也无济于事。
  • 不同于Actuator 1.x,Actuator 2.x 的大多数端点默认被禁掉。 Actuator 2.x 中的默认端点增加了/actuator前缀。默认暴露的两个端点为/actuator/health/actuator/info

相关配置

我们可以通过以下配置,来配置通过JMX 和 HTTP 暴露的端点。

Property Default
management.endpoints.jmx.exposure.exclude
management.endpoints.jmx.exposure.include *
management.endpoints.web.exposure.exclude
management.endpoints.web.exposure.include info, healt

可以打开所有的监控点

management.endpoints.web.exposure.include=*

也可以选择打开部分,”*” 代表暴露所有的端点,如果指定多个端点,用”,”分开

management.endpoints.web.exposure.exclude=beans,trace

Actuator 默认所有的监控点路径都在/actuator/*,当然如果有需要这个路径也支持定制。

management.endpoints.web.base-path=/minitor

设置完重启后,再次访问地址就会变成/minitor/*

端点解析

这个部分推荐看官方文档学习,这里就直接放一些最常用的health端点配置信息了

/health端点

/health端点会聚合你程序的健康指标,来检查程序的健康情况。端点公开的应用健康信息取决于:

management.endpoint.health.show-details=always

该属性可以使用以下值之一进行配置:

Name Description
never 不展示详细信息,up或者down的状态,默认配置
when-authorized 详细信息将会展示给通过认证的用户。授权的角色可以通过management.endpoint.health.roles配置
always 对所有用户暴露详细信息

按照上述配置,配置成always之后,我们启动项目,访问http://localhost:8080/actuator/health端口,可以看到这样的信息:

/health端点有很多自动配置的健康指示器:如redis、rabbitmq、db等组件。当你的项目有依赖对应组件的时候,这些健康指示器就会被自动装配,继而采集对应的信息。如上面的 diskSpace 节点信息就是DiskSpaceHealthIndicator 在起作用。具体有些哪些健康指示器,这里不做一一介绍了,看官网

当如上的组件有一个状态异常,应用服务的整体状态即为down。我们也可以通过配置禁用某个组件的健康监测。

management.health.mongo.enabled: false

或者禁用所有自动配置的健康指示器:

management.health.defaults.enabled: false

常用搭配Module

demo-admin-server

 <dependency>
      <groupId>de.codecentric</groupId>
      <artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>

配置文件:

server:
  port: 8000

demo-admin-client

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>

配置文件:

server:
  port: 8080
  servlet:
    context-path: /demo
spring:
  application:
    # Spring Boot Admin展示的客户端项目名,不设置,会使用自动生成的随机id
    name: spring-boot-demo-admin-client
  boot:
    admin:
      client:
        # Spring Boot Admin 服务端地址
        url: "http://localhost:8000/"
        instance:
          metadata:
            # 客户端端点信息的安全认证信息
            user.name: ${spring.security.user.name}
            user.password: ${spring.security.user.password}
  security:
    user:
      name: xkcoding
      password: 123456
management:
  endpoint:
    health:
      # 端点健康情况,默认值"never",设置为"always"可以显示硬盘使用情况和线程情况
      show-details: always
  endpoints:
    web:
      exposure:
        # 设置端点暴露的哪些内容,默认["health","info"],设置"*"代表暴露所有可访问的端点
        include: "*"

运行步骤:

  1. 进入 spring-boot-demo-admin-server 服务端,启动管控台服务端程序
  2. 进入 spring-boot-demo-admin-client 客户端,启动客户端程序,注册到服务端
  3. 观察服务端里,客户端程序的运行状态等信息

了解 Spring Boot Actuator 的安全风险

从上文的介绍可知,有一些 Spring Boot Actuator 提供的 endpoint 是会将应用重要的信息暴露出去的,以 env 为例来感受下一个典型的 application.yaml 的示例。

server:
  port: 8080
spring:
  datasource:
   url: jdbc:mysql://testDbHost:3306/kirito
    username: kirito
    password: 123456
kirito:
  ak: kirito@xxx_ak
  sk: kirito@xxx_sk
management:
  endpoints:
    web:
      exposure:
        include: "*"

复制

上面的配置再经典不过,我们看看访问 localhost:8080/actuator/env 之后的返回值

{
  "activeProfiles": [],
  "propertySources": [
    {
      "name": "server.ports",
      "properties": {
        "local.server.port": {
          "value": 8080
        }
      }
    },
    {
      "name": "Config resource 'class path resource [application.yaml]' via location 'optional:classpath:/'",
      "properties": {
        "server.port": {
          "value": 8080,
          "origin": "class path resource [application.yaml] - 2:9"
        },
        "spring.datasource.url": {
          "value": "jdbc:mysql://testDbHost:3306/kirito",
          "origin": "class path resource [application.yaml] - 5:44"
        },
        "spring.datasource.username": {
          "value": "kirito",
          "origin": "class path resource [application.yaml] - 6:15"
        },
        "spring.datasource.password": {
          "value": "******",
          "origin": "class path resource [application.yaml] - 7:15"
        },
        "kirito.ak": {
          "value": "kirito@xxx_ak",
          "origin": "class path resource [application.yaml] - 10:7"
        },
        "kirito.sk": {
          "value": "kirito@xxx_sk",
          "origin": "class path resource [application.yaml] - 11:7"
        },
        "management.endpoints.web.exposure.include": {
          "value": "*",
          "origin": "class path resource [application.yaml] - 17:18"
        }
      }
    }
  ]
}

可以发现,对于内置的敏感配置信息 spring.datasource.passwordSpring Boot Actuator 是进行了脱敏的,但是对于自定义的一些敏感配置,如 kirito.ak 和 kirito.sk 却被暴露出来了。

可能有的读者会立马提出质疑:我们的机器都部署内网,并且一般都是通过反向代理对外暴露的服务,这类 endpoint 是不会被外部用户访问到的。那我只能说太天真了,例如以下情况都是导致安全漏洞的真实 case:

  • 反向代理误配置了根节点,将 actuator 的 endpoint 和 web 服务一起暴露了出去
  • 线上配置没问题,测试环境部署时开通了公网 SLB,导致 actuator 的 endpoint 暴露了出去
  • 同一环境中某台机器被攻陷,导致应用配置信息泄露

安全建议

针对 Spring Boot Actuator 提供的 endpoint,采取以下几种措施,可以尽可能降低被安全攻击的风险

  1. 最小粒度暴露 endpoint。只开启并暴露真正用到的 endpoint,而不是配置:management.endpoints.web.exposure.include=*
  2. 为 endpoint 配置独立的访问端口,从而和 web 服务的端口分离开,避免暴露 web 服务时,误将 actuator 的 endpoint 也暴露出去。例:management.port=8099
  3. 引入 spring-boot-starter-security 依赖,为 actuator 的 endpoint 配置访问控制。
  4. 慎重评估是否需要引入 spring-boot-stater-actuator。以我个人的经验,我至今还没有遇到什么需求是一定需要引入spring-boot-stater-actuator 才能解决,如果你并不了解上文所述的安全风险,我建议你先去除掉该依赖。

参考资料

Spring Boot Actuator 模块 详解:健康检查,度量,指标收集和监控

Spring boot——Actuator 详解

警惕 Spring Boot Actuator 引发的安全问题


文章作者: 银色回廊
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 银色回廊 !
评论
  目录