- 可观测性
- 时序数据库
- 后端
- 指标监控
【免费下载链接】cortex
A horizontally scalable, highly available, multi-tenant, long term Prometheus.
本篇指南围绕开源时序数据库 Cortex 的官方安全文档(docs/guides/security.md)展开,系统讲解在生产环境中部署 Cortex 时必须遵循的安全基线:如何以"最小权限"原则限制源码缺陷可能带来的暴露面、为何必须在 Cortex 外部完成认证与授权(docs/guides/authentication-and-authorisation.md)、以及发现安全漏洞后应遵循的披露流程(SECURITY.md)。读完本文,你将掌握X-Scope-OrgID多租户机制的真实工作原理、remote_write场景下的认证接入方式、-auth.enabled开关的取舍,以及通过 TLS 加固组件间通信的具体配置方法。
一、安全部署的总体原则
Cortex 官方安全文档明确指出:Cortex 的部署必须对系统配置保持足够谨慎,遵循"最小权限"(least privilege)等原则,以限制源码中潜在缺陷可能带来的任何暴露面。这是一个分布式、水平扩展的多租户系统,其安全性不仅取决于代码本身,更取决于部署拓扑、网络隔离、访问控制与密钥管理等一系列运维决策。
Cortex 自身并不内置认证与授权(authentication and authorisation)能力,官方文档明确要求:
你必须在 Cortex 外部配置认证与授权,参见 认证与授权指南。
这意味着认证层(如 OAuth2 代理、LDAP、反向代理鉴权)应作为独立组件前置在 Cortex 之前,而 Cortex 内部只负责"识别租户、隔离数据",不负责"验证你是谁、你是否有权访问"。
二、多租户模型与X-Scope-OrgID工作机制
2.1 租户 ID 从请求头注入
所有 Cortex 组件都从每个请求的 HTTP 头X-Scope-OrgID中获取租户 ID。租户(tenant,也称作"user"或"org")是一组写入并查询 Cortex 的时间序列数据的所有者。
在源码层面,这一机制由 pkg/util/fakeauth/fake_auth.go 中的认证中间件实现:当认证开启时,HTTP 请求经middleware.AuthenticateUser拦截,从请求头提取 OrgID 并注入请求上下文(context);gRPC 请求则通过ServerUserHeaderInterceptor等一元/流式拦截器完成同样的注入。
2.2 Cortex 完全信任该值——这正是风险所在
官方文档特别强调:所有 Cortex 组件对这个值完全信任。也就是说,如果你的 Cortex 部署需要防范意外或恶意的调用,就必须额外增加一层保护。
从 pkg/util/users/resolver.go 的代码可以看到,租户 ID 从请求上下文解析后,还需要通过 pkg/util/users/tenant.go 中的ValidTenantID做合法性校验——校验内容包括字符集、长度(最长 150 字节)以及是否为保留值(.、..、__markers__、user-index.json.gz)。但需要明确:这是格式合法性校验,而非身份真实性校验。任何人只要能在请求中伪造X-Scope-OrgID头,就能以该租户身份操作数据。
2.3 为何必须在外部增加认证层
典型做法是:在 Cortex 前面部署反向代理,确保所有调用方都提供能标识身份并确认其授权的凭据,包括:
- 通过
remote_write接口发送数据的机器(Prometheus、各种采集 Agent); - 通过 GUI(如 Grafana)发起查询的人类用户。
反向代理负责完成身份验证(你是谁)与授权判定(你能访问哪些租户),验证通过后再将合法的X-Scope-OrgID头转发给 Cortex。这样即便出现绕过认证直接访问 Cortex 端口的路径,也会因为缺少合法凭据而被拦截。
三、remote_write场景下的认证接入方式
3.1 用 Basic Auth / Bearer Token 承载租户 ID 与凭据
在 Prometheus 的remote_write配置中,HTTP Basic Auth 的user/password字段,或 Bearer token,可以用来同时承载租户 ID 和/或凭据。反向代理从中解析出租户 ID,再转换为X-Scope-OrgID转发给 Cortex:
remote_write: - url: http://<auth-proxy>/prometheus/api/v1/push basic_auth: username: <tenant-id> password: <secret>3.2 可信环境中直接发送X-Scope-OrgID
如果你运行在完全可信的内网环境,可以让 Prometheus 直接发送X-Scope-OrgID头。通过配置 Prometheusremote_write配置中的headers字段即可:
remote_write: - url: http://<cortex>/prometheus/api/v1/push headers: X-Scope-OrgID: <org>⚠️ 此方式将租户身份完全交给调用方决定,仅适合无恶意调用者的受信网络。一旦网络边界不可信,必须回到 3.1 的外部认证方案。
3.3 单租户模式:-auth.enabled=false
如果需要禁用多租户功能,可以给每个 Cortex 组件传入参数-auth.enabled=false。此时所有请求的 OrgID 都会被替换为字符串fake。
该参数在 pkg/cortex/cortex.go 中定义,默认值为true("Set to false to disable auth.")。在 pkg/cortex/cortex.go 中,fakeauth.SetupAuthMiddleware根据该开关决定使用真实认证中间件还是伪造认证中间件;后者(见 pkg/util/fakeauth/fake_auth.go 中的fakeHTTPAuthMiddleware)会把fake注入请求上下文,使下游逻辑保持多租户代码路径不变。对应的 YAML 配置项为auth_enabled,示例见 docs/configuration/single-process-config-blocks-tls.yaml:
# Disable the requirement that every request to Cortex has a # X-Scope-OrgID header. `fake` will be substituted in instead. auth_enabled: false注意:禁用认证后,所有数据都归属于同一个
fake租户,适用于本地开发、演示或明确的单租户生产场景,不适用于需要租户隔离的场景。
3.4 写入与查询的租户 ID 必须一致
文档明确提醒:用于向数据存储写入序列的租户 ID,必须与查询时使用的租户 ID 一致;如果不匹配,你将看不到任何数据。目前 Cortex 不支持跨租户查看序列(跨租户查询功能需单独启用 Tenant Federation 特性)。
3.5 租户 ID 命名规范
由于租户 ID 会直接出现在存储路径、请求头与各种标识中,其命名受到 租户 ID 命名规范 的约束:
- 支持的字符:字母数字(
0-9、a-z、A-Z)以及! - _ . * ' ( )等特殊字符; - 非法租户 ID:
.、..(路径穿越风险)、__markers__(内部标记目录)、user-index.json.gz(内部索引文件); - 长度限制:不超过 150 字节/字符。
这些限制与 pkg/util/users/tenant.go 中的ValidTenantID/CheckTenantIDIsSupported实现一一对应,目的之一是防止租户 ID 被用于路径遍历等安全攻击。
四、辅助方案:cortex-tenant 代理
官方文档还介绍了一种社区方案:cortex-tenant代理。它可以放置在 Prometheus 与 Cortex 之间,从 Prometheus 序列的标签中提取预定义的标签值,作为X-Scope-OrgID头在转发时序数据时注入请求。
这适合在受信环境中按某些标准(如团队、应用)将指标划分到不同命名空间:
Prometheus --> cortex-tenant(提取 label 值 -> X-Scope-OrgID)--> Cortex需要明确的是,cortex-tenant 是第三方社区项目,并非由 Cortex 团队维护,生产环境引入前需自行评估其安全性与维护状况。
五、传输安全:用 TLS 加固组件间通信
Cortex 是一个组件间通信量巨大的分布式系统。为了保障传输安全,Cortex 支持在所有组件之间启用 TLS,官方完整指南见 docs/guides/tls.md。要点如下:
5.1 生成证书
使用私有 CA 签发集群证书(CA 应仅由本组织私有持有,因为任何由其签发的证书都具备与集群通信的权限):
# keys openssl genrsa -out root.key openssl genrsa -out client.key openssl genrsa -out server.key # root cert / certifying authority openssl req -x509 -new -nodes -key root.key -subj "/C=US/ST=KY/O=Org/CN=root" -sha256 -days 100000 -out root.crt # csrs - certificate signing requests openssl req -new -sha256 -key client.key -subj "/C=US/ST=KY/O=Org/CN=client" -out client.csr openssl req -new -sha256 -key server.key -subj "/C=US/ST=KY/O=Org/CN=localhost" -out server.csr # certificates openssl x509 -req -in client.csr -CA root.crt -CAkey root.key -CAcreateserial -out client.crt -days 100000 -sha256 openssl x509 -req -in server.csr -CA root.crt -CAkey root.key -CAcreateserial -out server.crt -days 100000 -sha256上述脚本生成 100000 天有效的证书,可通过调整-days改变有效期;官方建议证书至少每 2 年更换一次。
5.2 服务端(HTTP/gRPC)TLS 配置
# HTTP Server -server.http-tls-cert-path=/path/to/server.crt -server.http-tls-key-path=/path/to/server.key -server.http-tls-client-auth="RequireAndVerifyClientCert" -server.http-tls-ca-path="/path/to/root.crt" # GRPC Server -server.grpc-tls-cert-path=/path/to/server.crt -server.grpc-tls-key-path=/path/to/server.key -server.grpc-tls-client-auth="RequireAndVerifyClientCert" -server.grpc-tls-ca-path="/path/to/root.crt"5.3 客户端 TLS 配置(组件相关)
例如 Alertmanager 的 HTTP 客户端:
-alertmanager.configs.tls-cert-path=/path/to/client.crt -alertmanager.configs.tls-key-path=/path/to/client.key -alertmanager.configs.tls-ca-path=/path/to/root.crtQuerier 的 gRPC 前端客户端:
-querier.frontend-client.tls-cert-path=/path/to/client.crt -querier.frontend-client.tls-key-path=/path/to/client.key -querier.frontend-client.tls-ca-path=/path/to/root.crtIngester 的 gRPC 客户端:
-ingester.client.tls-cert-path=/path/to/client.crt -ingester.client.tls-key-path=/path/to/client.key -ingester.client.tls-ca-path=/path/to/root.crtCortex 中其他 HTTP/gRPC 客户端均可按类似方式配置。完整的单进程 TLS 部署示例见 docs/configuration/single-process-config-blocks-tls.yaml:其中服务端通过server.grpc_tls_config配置cert_file/key_file/client_auth_type: "RequireAndVerifyClientCert"/client_ca_file,客户端(如ingester_client、frontend_worker)通过grpc_client_config下的tls_cert_path/tls_key_path/tls_ca_path完成双向认证。
六、安全漏洞披露与报告流程
与任何复杂系统一样,Cortex 也必然存在可能被发现的 bug,其中一部分与安全相关。官方披露流程记录在仓库根目录的 SECURITY.md,要点如下:
6.1 漏洞报告方式
如果你发现安全漏洞(security bug),请私下报告给相关仓库 MAINTAINERS 中列出的维护者,并抄送cortex-team@googlegroups.com。团队将尽快修复问题,并与你协调发布日期。你可以选择是否获得公开致谢以及是否被提及姓名。
6.2 公开披露时机
公开披露日期由 Cortex 团队与漏洞提交者协商确定。团队倾向于在修复或缓解措施可用后尽快完全披露;若漏洞或修复尚未被完全理解、或解决方案尚未达到测试标准,团队会请求延期。对于有直接缓解措施的漏洞,预计从报告到披露约为7 天量级。
6.3 私有厂商列表(Embargo Policy)
针对向用户提供 Cortex 的厂商,存在私有邮件列表cortex-vendors-announce@googlegroups.com,用于在公开披露前传递修复信息,并遵循严格的禁运(embargo)政策:
- 成员收到的信息在约定的公开披露时间前,不得公开、分享甚至暗示给非必要知悉人员;
- 信息分享给团队内修复所需成员前,对方须同意同样条款,并遵循 need-to-know 原则;
- 若发生信息泄露,必须立即向
cortex-team@googlegroups.com报告泄露内容与对象,团队将进行复盘。
加入该列表的资格标准包括:拥有受监控的安全邮件别名、提供公开托管的 Cortex 发行版、用户群不限于本组织、不是其他厂商的下游重建、积极参与社区、接受禁运政策并愿意贡献回馈(如评审/测试补丁、协助起草披露邮件与发布说明)。若厂商后续不再满足任一标准,将被取消订阅。
七、部署加固清单
综合官方文档与源码,生产环境部署 Cortex 建议按以下清单逐项核查:
| 检查项 | 说明 | 依据 |
|---|---|---|
| 最小权限 | 收紧系统配置、网络访问与数据面权限,缩小源码缺陷暴露面 | docs/guides/security.md |
| 外部认证授权 | 认证/授权必须在 Cortex 外部(反向代理)完成,不信任客户端直接上报的租户身份 | docs/guides/authentication-and-authorisation.md |
| remote_write 凭据 | Basic Auth / Bearer token 承载租户 ID 与凭据;仅受信环境才用headers直传X-Scope-OrgID | 同上 |
| 租户 ID 一致性 | 写入与查询使用同一租户 ID;遵循 命名规范 | 同上 |
| 传输加密 | 组件间启用双向 TLS(HTTP/gRPC 服务端与客户端证书、CA 校验) | docs/guides/tls.md |
| 漏洞响应 | 建立私密上报渠道与披露协调机制;参考 SECURITY.md | SECURITY.md |
值得再次强调:Cortex 的认证与授权边界在系统之外——多租户隔离依赖正确的部署与网络边界,租户 ID 校验(pkg/util/users/tenant.go)只防格式与路径类问题,不防伪造身份。将认证前置、将租户边界外置、将传输加密,是确保生产环境安全的三大支柱。
- 可观测性
- 时序数据库
- 后端
- 指标监控
【免费下载链接】cortex
A horizontally scalable, highly available, multi-tenant, long term Prometheus.
相关推荐
Zulip 安全漏洞披露机制与自建服务器安全加固实战指南
Zulip 安全漏洞披露机制与自建服务器安全加固实战指南 Zulip 是 100% 开源的企业级团队聊天服务器,其安全模型直接关系到每一个自建实例的用户数据。本
即时通讯后端前端WebSocketlamp-cloud 安全漏洞披露策略与安全加固实践:多租户 SaaS 平台的负责任报告指南
lamp cloud 安全漏洞披露策略与安全加固实践:多租户 SaaS 平台的负责任报告指南 导读 本文以 lamp cloud 仓库根目录的 SECURITY
后端微服务API网关认证鉴权代码生成DeepAudit 安全指南:AI 代码审计的隐私保护、部署加固与漏洞披露机制全解析
DeepAudit 安全指南:AI 代码审计的隐私保护、部署加固与漏洞披露机制全解析 DeepAudit 是一款调用第三方 LLM 服务商 API 进行代码漏洞
人工智能大模型AI Agent应用安全SASTRAG后端前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考