安全指南

数据库最小权限、密钥处理、TLS、HTTP 认证与网络暴露面

pg_exporter 位于两个信任域之间:它先向 PostgreSQL 或 pgBouncer 认证,再通过 HTTP 暴露指标与管理端点。两侧必须独立加固;数据库 TLS 不会保护 HTTP 监听端口,HTTP Basic Auth 也不会降低数据库权限。

威胁面

表面 敏感能力 主要控制
PostgreSQL 连接 读取监控视图并执行采集器 SQL 专用登录角色、pg_monitorpg_hba.conf、TLS
目标 URL 包含主机、用户,通常还包含密码 .pgpass、密钥文件、文件权限、密钥管理系统
/metrics 暴露拓扑、对象名、负载与容量 私网、防火墙、TLS/认证
/explain/stat 暴露采集器定义、准入、耗时与错误 限制或认证 HTTP 访问
/reload 触发配置解析与查询计划原子替换 限制或认证 HTTP 访问
采集器 SQL 消耗数据库资源,并可能通过 Label 暴露信息 查询审查、最小权限、超时、TTL、基数审查

使用专用数据库角色

PostgreSQL 10+ 内置的 pg_monitor 角色覆盖默认采集器所需的只读权限:

CREATE ROLE monitor
  WITH LOGIN
       PASSWORD 'replace-this-secret'
       CONNECTION LIMIT 5;

GRANT pg_monitor TO monitor;

不要为了省去权限审查而让 exporter 使用超级用户。可选自定义采集器可能需要访问自己的视图、函数或 Schema,请按对象单独授权。

监控 pgBouncer 时,需要使用本地策略允许的 stats_usersadmin_users 账户连接管理数据库。此模式下 exporter 使用管理端 SHOW 接口,而不是 PostgreSQL 系统目录。

不要把密码放进进程参数

目标 URL 的取值优先级如下:

  1. --url / -u
  2. PG_EXPORTER_URL
  3. PGURL
  4. PG_EXPORTER_URL_FILE 指向的文件
  5. postgresql:///?sslmode=disable

命令参数可能出现在进程列表中,建议使用以下方式之一。

.pgpass

db.example.com:5432:*:monitor:replace-this-secret
chmod 600 ~/.pgpass
export PG_EXPORTER_URL='postgres://[email protected]:5432/postgres?sslmode=verify-full'

RPM/DEB 服务以 prometheus 用户运行。自 v1.4.0 起该用户 HOME 为 /var/lib/prometheus,但软件包不会创建目录:

sudo install -d -o prometheus -g prometheus -m 0750 /var/lib/prometheus
sudo install -o prometheus -g prometheus -m 0600 ./pgpass /var/lib/prometheus/.pgpass

密钥文件

PG_EXPORTER_URL_FILE 适合 systemd credential、Docker/Kubernetes Secret 挂载以及其他文件型密钥交付:

export PG_EXPORTER_URL_FILE=/run/secrets/pg_exporter_url
pg_exporter --config=/etc/pg_exporter.yml

文件应包含一个 URL,可以带首尾空白。显式配置的文件不存在或不可读时,进程会致命退出。日志会遮盖 URL 用户信息与 password= 查询参数中的密码,但日志脱敏不能替代源密钥保护。

保护数据库连接

未提供 sslmode 时,pg_exporter 会为常见的同机部署主动添加 sslmode=disable。这在不可信网络上并不安全;远程目标应显式选择 libpq TLS 策略:

export PG_EXPORTER_URL='postgres://[email protected]:5432/postgres?sslmode=verify-full&sslrootcert=/etc/pg_exporter/ca.crt'

尽可能使用 verify-full,同时验证证书链与主机名。require 会加密流量,但不能提供同等的服务器身份保证。

官方 Docker 镜像基于 scratch,没有系统 CA 包。请将所需 CA 文件挂载进容器,并在 sslrootcert 中引用精确路径。

缩小 HTTP 暴露面

如果 Prometheus 与 exporter 在同一台主机上,只监听回环地址:

pg_exporter --web.listen-address=127.0.0.1:9630

需要远程抓取时,只允许监控网段通过防火墙或服务网格访问。监听端口同时包含管理端点,并不存在独立的管理端口。

TLS 与 Basic Auth

--web.config.file 使用 Prometheus exporter-toolkit 格式,并在每个 HTTP 请求时重新读取。最小示例:

tls_server_config:
  cert_file: /etc/pg_exporter/web.crt
  key_file: /etc/pg_exporter/web.key
  min_version: TLS12

basic_auth_users:
  prometheus: "$2y$10$replace_with_a_bcrypt_hash"
pg_exporter --web.config.file=/etc/pg_exporter/web.yml

请生成 bcrypt 哈希,不要把明文密码写进文件,例如使用 htpasswd -nBC 10 prometheus。mTLS、响应头与限流配置以 exporter-toolkit Web 配置为准。

启用 Basic Auth 后,Prometheus 抓取任务也要配置认证:

scrape_configs:
  - job_name: postgresql
    scheme: https
    basic_auth:
      username: prometheus
      password_file: /etc/prometheus/secrets/pg_exporter_password
    tls_config:
      ca_file: /etc/prometheus/ca/pg_exporter-ca.crt
    static_configs:
      - targets: ['db.example.com:9630']

保护配置文件

发布软件包以较严格的权限将 /etc/pg_exporter.yml/etc/default/pg_exporter 交给 prometheus 用户。复制或模板化文件时应保留相同的所有权与权限。数据库密码不应放在采集器 YAML 中;该文件用于查询和指标元数据,不是连接密钥。

部署前还要审查自定义 Label。数据库名、客户标识、租户名与 SQL 指纹都可能成为 Prometheus 标签,并继续流向远端存储、告警与仪表盘。

生产检查清单

  • 使用有小连接上限的专用非超级用户数据库账户
  • 配置明确的 pg_hba.conf 规则与网络来源限制
  • 使用 .pgpass 或密钥文件,不在命令参数中放密码
  • 远程数据库连接使用 sslmode=verify-full 与可信 CA
  • 9630 端口只监听回环/私网,或受防火墙限制
  • HTTP 跨越信任边界时启用 TLS/认证
  • 将管理端点视为敏感接口
  • 审查自定义 SQL 的权限、超时、TTL 与标签基数
  • 验证密钥/证书轮换不会在日志或进程列表泄露值

服务示例参见生产部署,TLS、凭据与端点失败的定位方法参见故障排查