安全模型

注意在深入探讨以下技术细节之前,我们想强调,Prometheus 作为一个监控系统,收集并提供其监控系统的信息。因此,Prometheus 组件提供的 HTTP 端点不应暴露在公共网络(如互联网)上(除非您清楚自己在做什么并已采取适当措施)。这包括(但不限于)已插桩二进制文件的 /metrics 端点、服务器组件的各种 API 端点以及用 Go 实现的服务器组件的 /pprof 端点。此外,很容易通过向这些端点发送请求来使服务器过载,并最终导致拒绝服务(DoS)。

Prometheus 是一个复杂的系统,包含许多组件,并与许多其他系统集成。它可以部署在各种受信任和不受信任的环境中。

本页描述了 Prometheus 的一般安全假设以及某些配置可能启用的攻击向量。

与任何复杂系统一样,几乎可以肯定会发现错误,其中一些与安全相关。

对于已公开披露(例如通过公开 CVE)且修复不仅仅是升级依赖版本的*安全漏洞*,请在 漏洞报告 中提交,包含所有相关细节,除非已经有人提交过了。

如果您发现尚未公开披露的*安全漏洞*,请私下向相关仓库 MAINTAINERS 文件中列出的维护者报告,并抄送至 [email protected]。我们将尽快修复问题,并与您协调发布日期。您可以选择是否公开您的贡献,以及是否希望被提名。

大多数依赖版本更新是自动处理的。但是,如果一个*安全漏洞*修复只需要更新依赖版本而我们的自动化错过了它,请随时直接提交更新。

自动化安全扫描器

安全扫描器用户的特别提示:请谨慎对待生成的报告。大多数扫描器是通用的,会产生大量误报。我们收到的报告越来越多,仔细审查所有报告并以您期望的谨慎态度回复需要大量工作。这个问题在 Go 和 NPM 依赖扫描器中尤其严重。

为了尊重我们和我们的时间,我们恳请您不要提交原始报告。相反,请提交经过分析的报告,并概述哪些具体结果适用于我们以及为什么。

此外请注意,作为一个开源项目,我们通常无法访问商业扫描工具,并且发现它们的输出常常具有误导性或完全错误。对于 Go 代码,如果您的报告无法通过开源的 govulncheck 工具在您认为受影响版本的*源代码*上(而不是二进制文件,因为那无法进行完整分析)重现,我们请您再次检查您的发现(包括该代码是否真的在 Prometheus 代码库中可达)。

Prometheus 由志愿者维护,而非公司。因此,修复安全问题是尽力而为的。我们力求在 7 天内为以下项目发布安全修复:Prometheus、Alertmanager、Node Exporter、Blackbox Exporter 和 Pushgateway。

Prometheus

假设不受信任的用户可以访问 Prometheus HTTP 端点和日志。他们可以访问数据库中包含的所有时间序列信息,以及各种操作/调试信息。

同时假设只有受信任的用户能够更改 Prometheus 和其他组件的命令行、配置文件、规则文件以及运行时环境的其他方面。

Prometheus 抓取哪些目标、抓取频率以及其他设置完全由配置文件决定。管理员可以决定使用来自服务发现系统的信息,结合重标签,这可能会将部分控制权授予任何能够修改该服务发现系统中数据的人。

被抓取的目标可能由不受信任的用户运行。默认情况下,目标不应能够暴露冒充其他目标的数据。`honor_labels` 选项移除了这一保护,某些重标签设置也可能如此。

自 Prometheus 2.0 起,`--web.enable-admin-api` 标志控制对管理性 HTTP API 的访问,其中包括删除时间序列等功能。该功能默认禁用。如果启用,管理和修改功能将在 `/api/*/admin/` 路径下可访问。`--web.enable-lifecycle` 标志控制 Prometheus 的 HTTP 重载和关闭。该功能也默认禁用。如果启用,它们将在 `/-/reload` 和 `/-/quit` 路径下可访问。

在 Prometheus 1.x 中,任何有权访问 HTTP API 的人都可以访问 `/-/reload` 并对 `/api/v1/series` 使用 `DELETE`。`/-/quit` 端点默认禁用,但可以通过 `-web.enable-remote-shutdown` 标志启用。

远程读取功能允许任何有 HTTP 访问权限的人向远程读取端点发送查询。例如,如果 PromQL 查询最终直接在关系数据库上运行,那么任何能够向 Prometheus 发送查询的人(例如通过 Grafana)都可以在该数据库上运行任意 SQL。

Alertmanager

任何有权访问 Alertmanager HTTP 端点的用户都可以访问其数据。他们可以创建和解决告警。他们可以创建、修改和删除静默规则。

通知的发送目的地由配置文件决定。在某些模板设置下,通知可能会发送到告警定义的目的地。例如,如果通知使用告警标签作为目标电子邮件地址,那么任何能够向 Alertmanager 发送告警的人都可以向任何电子邮件地址发送通知。如果告警定义的目的地是一个可模板化的密钥字段,那么任何有权访问 Prometheus 或 Alertmanager 的人都将能够查看这些密钥。

任何可模板化的密钥字段都旨在用于上述用例中的路由通知。它们并非旨在通过模板文件功能将密钥与配置文件分离开来。任何存储在模板文件中的密钥都可能被任何能够配置 Alertmanager 配置文件中接收器的人泄露。例如,在大型设置中,每个团队可能有一个他们完全控制的 Alertmanager 配置文件片段,然后这些片段会合并到最终的完整配置文件中。

Pushgateway

任何有权访问 Pushgateway HTTP 端点的用户都可以创建、修改和删除其中包含的指标。由于 Pushgateway 通常在启用 `honor_labels` 的情况下被抓取,这意味着任何有权访问 Pushgateway 的人都可以在 Prometheus 中创建任何时间序列。

--web.enable-admin-api 标志控制对管理性 HTTP API 的访问,其中包括清除所有现有指标组等功能。该功能默认禁用。如果启用,管理功能将在 /api/*/admin/ 路径下可访问。

导出器

导出器通常只与一个配置好的实例通信,使用一组预设的命令/请求,这些命令/请求无法通过它们的 HTTP 端点扩展。

还有一些导出器,如 SNMP 和 Blackbox 导出器,它们从 URL 参数中获取目标。因此,任何有权访问这些导出器 HTTP 的人都可以让它们向任意端点发送请求。由于它们还支持客户端认证,这可能导致密钥泄露,例如 HTTP 基本认证密码或 SNMP community 字符串。像 TLS 这样的挑战-响应认证机制不受此影响。

客户端库

客户端库旨在包含在用户的应用程序中。

如果使用客户端库提供的 HTTP 处理程序,恶意请求到达该处理程序时,不应造成超出额外负载和抓取失败所导致的问题。

身份验证、授权和加密

Prometheus 和大多数导出器都支持 TLS,包括通过 TLS 客户端证书进行客户端身份验证。有关配置 Prometheus 的详细信息,请参阅此处

Go 项目共享同一个 TLS 库,该库基于 Go 的 crypto/tls 库。我们默认最低版本为 TLS 1.2。我们对此的政策基于 Qualys SSL Labs 的建议,我们力求在默认配置和正确提供证书的情况下达到“A”级,同时尽可能贴近上游 Go 的默认设置。达到该等级可以在完美安全性和可用性之间取得平衡。

未来将为 Java 导出器添加 TLS。

如果您有特殊的 TLS 需求,比如不同的密码套件或更旧的 TLS 版本,您可以调整最低 TLS 版本和密码套件,只要该密码套件在 crypto/tls 库中没有被标记为不安全。如果这仍然不能满足您的需求,当前的 TLS 设置允许您在服务器和具有更特殊需求的反向代理之间建立安全隧道。

还支持 HTTP 基本身份验证。基本身份验证可以在没有 TLS 的情况下使用,但那样会在网络上以明文形式暴露用户名和密码。

在服务器端,基本身份验证密码使用 bcrypt 算法作为哈希存储。您有责任选择符合您安全标准的轮数。轮数越多,暴力破解就越复杂,但代价是需要更多的 CPU 资源和更长的身份验证时间。

各种 Prometheus 组件支持客户端身份验证和加密。如果提供 TLS 客户端支持,通常还会有一个名为 `insecure_skip_verify` 的选项,该选项会跳过 SSL 验证。

API 安全

由于管理性和修改性端点旨在通过 cURL 等简单工具访问,因此没有内置的 CSRF 保护,因为那会破坏此类用例。因此,在使用反向代理时,您可能希望阻止这些路径以防止 CSRF。

对于非修改性端点,您可能希望在反向代理中设置 CORS 头,例如 `Access-Control-Allow-Origin`,以防止 XSS

如果您正在编写包含来自不受信任用户输入的 PromQL 查询(例如,控制台模板的 URL 参数,或您自己构建的东西),而这些用户不应该能够运行任意 PromQL 查询,请确保任何不受信任的输入都经过适当转义,以防止注入攻击。例如,如果 <user_input> 是 `"} or some_metric{zzz="`,那么 `up{job="<user_input>"}` 将变成 `up{job=""} or some_metric{zzz=""}`。

对于使用 Grafana 的用户请注意,仪表板权限不是数据源权限,因此它们不会限制用户在代理模式下运行任意查询的能力。

密钥

非机密信息或字段可能通过 HTTP API 和/或日志可用。

在 Prometheus 中,从服务发现中检索的元数据不被视为机密。在整个 Prometheus 系统中,指标不被视为机密。

配置文件中包含密钥的字段(在文档中明确标记)不会在日志中或通过 HTTP API 暴露。密钥不应放在其他配置字段中,因为组件通常会通过其 HTTP 端点暴露其配置。用户有责任保护磁盘上的文件免受不必要的读写。

由依赖项使用的其他来源的密钥(例如,EC2 服务发现使用的 `AWS_SECRET_KEY` 环境变量)可能会因我们无法控制的代码或恰好暴露其存储位置的功能而暴露。

拒绝服务

对于过量负载或昂贵的查询,有一些缓解措施。但是,如果提供的查询/指标太多或太昂贵,组件将会崩溃。组件更有可能被受信任的用户意外关闭,而不是被恶意操作。

用户有责任确保为组件提供足够的资源,包括 CPU、RAM、磁盘空间、IOPS、文件描述符和带宽。

建议监控所有组件的故障,并在故障时自动重启。

本文档考虑的是从原始源代码构建的普通二进制文件。如果您修改 Prometheus 源代码,或在自己的代码中使用 Prometheus 内部组件(超出官方客户端库 API),此处提供的信息将不适用。

构建过程

Prometheus 的构建管道在第三方提供商上运行,许多 Prometheus 开发团队成员和这些提供商的员工都可以访问。如果您担心二进制文件的确切来源,建议您自己构建,而不是依赖项目提供的预构建二进制文件。

Prometheus-Community

Prometheus-Community 组织下的仓库由第三方维护者支持。

如果您在 Prometheus-Community 组织中发现*安全漏洞*,请私下向相关仓库的 MAINTAINERS 文件中列出的维护者报告,并抄送至 [email protected]

该组织下的某些仓库可能具有与本文档中介绍的不同安全模型。在这种情况下,请参阅这些仓库的文档。

外部审计

本页内容