Telegraf HashiCorp Vault Secret Store 插件:从配置到源码的完整实战指南
【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf
Telegraf 的secretstores.vault插件允许 Telegraf 通过 Vault API 读取 HashiCorp Vault(以及兼容的 OpenBao)服务器中保存的密钥,并支持 Token 与 AppRole 两种认证方式。它解决的核心痛点是:把数据库口令、API Key 等敏感信息从 Telegraf 配置文件中剥离出来,集中托管在 Vault 中统一治理。读完本文,你将掌握该插件的完整配置、认证机制、在插件中引用密钥的语法,以及其底层源码实现原理与集成测试验证方式。
插件概述
secretstores.vault是 Telegraf 的 Secret Store(密钥存储)类插件,通过 Vault API 从 HashiCorp Vault 服务器获取密钥。其特性可以概括为:
- 只读为主的数据面:插件面向"读取密钥"设计,将密钥安全地下发到支持 Secret Store 的 Telegraf 插件中;
- 两种认证方式:使用预先获取的 Token,或通过
AppRole方法动态登录并自动续期; - 两类 KV 引擎:同时支持 Vault 的
kv-v1与kv-v2密钥引擎; - 版本与平台:由 README 中的元数据可知,该插件自Telegraf v1.37.0起提供,类别为
web,支持all平台。
插件本体位于 plugins/secretstores/vault 目录,包含vault.go(实现)、vault_test.go(测试)、sample.conf(示例配置)与testdata/policy.hcl(测试用 Vault 策略)。插件在init()中通过secretstores.Add("vault", ...)注册(见 vault.go),因此配置段名为[[secretstores.vault]]。
配置详解
以下为插件提供的完整示例配置(与仓库内 sample.conf 一一对应):
# Retrieve Hashicorp Vault secrets [[secretstores.vault]] ## Unique identifier for the secret store. ## This id can later be used in plugins to reference the secrets ## in this secret store via @{<id>:<secret_key>} (mandatory) id = "vault_secretstore" ## Address of the Vault server address = "localhost:8200" ## Mount path of the KV secrets engine. ## This is the path where the KV secrets engine is enabled. For example, if ## your full secret path in the Vault CLI is "secret/data/myapp/database", ## then mount_path = "secret". mount_path = "" ## Path to the secret within the KV secrets engine. ## This is the path to your specific secret under the mount point. For example, ## if your full secret path is "secret/data/myapp/database", then ## secret_path = "myapp/database". Note that the "/data/" segment in KV v2 ## paths is handled automatically and should not be included. secret_path = "" ## Namespace of the secrets; no namespace is used when empty ## Ignored if the server does not support namespaces such as Vault Community # namespace = "" ## Secret store engine to use. ## Supports 'kv-v1' and 'kv-v2' engines. ## By default will use the kv-v2 engine. # engine = "kv-v2" ## Authentication ## Exactly one of "token" or "approle" must be configured. Use "token" to ## pass an already-obtained Vault token (directly or via another ## secret store, e.g. @{other_store:vault_token}). Use "approle" to have ## Telegraf authenticate via the AppRole method and manage token renewal. ## Vault token used to authenticate with the server # token = "" # [secretstores.vault.approle] # ## The Role ID for AppRole Authentication, a UUID string # role_id = "" # # ## Whether the Secret ID is configured to be response wrapped or not # # response_wrapped = false # # ## The Secret ID for AppRole Authentication # secret = ""参数速查表
| 参数 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
id | 是 | string | 无 | 该密钥存储的唯一标识,供插件以@{<id>:<secret_key>}方式引用 |
address | 是 | string | 无 | Vault 服务器地址,如localhost:8200(生产环境建议https://...) |
mount_path | 是 | string | 无 | KV 密钥引擎的挂载路径,如 Vault CLI 中完整路径secret/data/myapp/database的secret部分 |
secret_path | 是 | string | 无 | 挂载点下具体密钥的路径,如myapp/database;KV v2 的/data/段由插件自动处理 |
namespace | 否 | string | 空 | Vault 命名空间;服务器不支持命名空间(如 Vault Community 版)时忽略 |
engine | 否 | string | kv-v2 | 密钥引擎类型,支持kv-v1与kv-v2 |
token | 二选一 | string | 空 | 已获取的 Vault Token |
approle | 二选一 | 子表 | 无 | AppRole 认证参数(见下表) |
approle子表参数:
| 参数 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
role_id | 是 | string | 无 | AppRole 认证的 Role ID,UUID 字符串 |
response_wrapped | 否 | bool | false | Secret ID 是否为 response-wrapped(响应包装)模式 |
secret | 是 | string | 无 | AppRole 认证的 Secret ID |
必填项校验与默认值(源码佐证)
插件在Init()中对配置做了严格校验,见 vault.go:
engine仅接受kv-v1/kv-v2,为空时默认kv-v2,其它值直接报错unsupported engine;token与approle必须恰好配置一个:两者都未配置报authentication method missing,同时配置报only one authentication method may be set;id、address、mount_path、secret_path均为必填,缺失时分别返回对应错误。
上述校验逻辑在 vault_test.go 的TestInitFail中有单元测试覆盖。
认证方式
Token 认证
使用token时,Token 可以直接写在配置中,也可以链式引用其他 Secret Store 提供的值,例如@{other_store:vault_token}。这意味着你可以通过任意一个 Telegraf Secret Store(如 OAuth2、文件、环境变量等)产出的机制获取 Token,再交给本插件使用。
需要特别注意:使用 Token 认证时,Token 的续期责任在提供方。也就是说,如果 Token 来自另一个 Secret Store,那么到期续期由那个源头负责;本插件只负责把它设置到 Vault 客户端上。从源码看,authenticate()中 Token 分支仅是v.Token.Get()后调用client.SetToken(...)(见 vault.go),不做任何续期逻辑。
AppRole 认证
使用approle时,插件用配置的 Role ID 与 Secret ID 向 Vault 登录,成功后启动一个lifetime watcher(生命周期监听器)持续维持 Token 的有效性,实现自动续期。
对应源码逻辑(见 vault.go)为:
- 读取 Secret ID,构造
approle.SecretID{FromString: ...}; - 若
response_wrapped = true,通过approle.WithWrappingToken()追加登录选项; - 调用
approle.NewAppRoleAuth(roleID, secretID, opts...)初始化认证方式; client.Auth().Login(...)完成登录;client.NewLifetimeWatcher(...)创建监听器并以go watcher.Start()异步启动,持续续期。
这套流程与官方 Vault Go 客户端库github.com/hashicorp/vault/api/auth/approle的标准用法一致。
在插件中引用 Vault 密钥
引用语法
Secret Store 定义的密钥通过@{<store-id>:<secret_key>}语法在 Telegraf 配置中引用(见 docs/includes/secret_usage.md)。例如,配置了id = "vault_secretstore"后,引用其中名为password的密钥就写作@{vault_secretstore:password}。
哪些插件支持
并非所有插件与选项都支持 Secret Store。判断方法是查看目标插件 README 是否包含Secret store support章节,该章节会列出支持密钥引用的具体选项。例如 plugins/outputs/influxdb/README.md 明确说明username与password选项支持从 Secret Store 获取,并指向 docs/CONFIGURATION.md 中的 Secret Store 章节。典型用法如下:
[[outputs.influxdb]] urls = ["http://localhost:8086"] username = "@{vault_secretstore:influxdb_username}" password = "@{vault_secretstore:influxdb_password}"底层接口
Telegraf 通过 secretstore.go 中的SecretStore接口抽象所有密钥存储,核心方法包括Get(key)、List()与GetResolver(key)。其中GetResolver返回一个ResolveFunc,其布尔返回值表示密钥是否为动态(true 表示随时间变化,需每次重新解析)。Vault 插件的GetResolver实现每次调用都重新读取 Vault(见 vault.go),因此 Vault 中密钥更新后,Telegraf 侧能感知变化。
KV 引擎与路径映射
插件支持 Vault 的两种 KV 密钥引擎,二者的核心差异在于路径结构:
- KV v1:密钥直接挂在挂载路径下,如
secret/myapp/database; - KV v2:密钥实际存储在
secret/data/myapp/database,多出/data/段。
配置时遵循"挂载路径 + 相对路径"的拆分原则。以完整路径secret/data/myapp/database为例:
mount_path = "secret" secret_path = "myapp/database"/data/段由插件自动处理,不要写进secret_path。若使用 KV v1,则同样把secret/data/...中的/data/去掉再拆分。源码中的getSecret()会根据engine选择KVv1(...).Get()或KVv2(...).Get()(见 vault.go)。
命名空间支持
企业版 Vault 支持命名空间(Namespace)用于多租户隔离。通过namespace参数可以指定要读取的命名空间,留空则使用默认命名空间。源码中在创建客户端后调用client.SetNamespace(v.Namespace)(见 vault.go)。
需要注意:Vault Community(社区版)不支持命名空间,该参数会被忽略。集成测试TestIntegrationOpenBAONamespace(见 vault_test.go)使用 OpenBao 容器验证了namespaceA/namespaceB两个命名空间下各自读取到不同密钥值,证明命名空间隔离读取行为正确。
数据读取语义(Get / List)
Get(key):读取指定secret_path下某个键的值。若密钥路径存在但该键不存在(或所有值已被删除),返回空字节数组而非错误(见 vault.go);List():返回该路径下全部键名(见 vault.go)。
值得注意的是,README 声明本插件"只支持读取密钥,不能创建或修改"。但从当前源码结构看,Vault已实现telegraf.SecretStoreEditor接口的Set/Remove方法(见 vault.go 与 secretstore.go 的接口定义),这意味着源码层面已具备写入能力。其实现采用了"读改写"策略:
Set会先读取路径下已有全部键再覆盖目标键,避免 Vault 的Put整路径替换行为误删兄弟键;Remove同理,先读回全部键、剔除目标键后写回;当删除最后一个键时,会直接删除整个路径的密钥(kv-v1 因引擎本身拒绝写入空数据,删除行为与 kv-v2 保持一致)。
集成测试与验证方式
插件的正确性由一套基于容器(Testcontainers)的集成测试保障,覆盖场景非常全面(见 vault_test.go):
| 测试 | 覆盖场景 |
|---|---|
TestInitFail | 认证缺失、双认证同时配置等配置错误校验 |
TestIntegration | Vault 1.x / 2.x × kv-v1 / kv-v2 共 4 种组合下的密钥读取 |
TestIntegrationAppRoleSecretWrapped | AppRole + response-wrapped Secret ID 登录并读取 |
TestIntegrationSetKeepsSiblings | Set 新键不覆盖已有兄弟键 |
TestIntegrationRemove | 删除键、删除不存在键报错、删除末键清空路径 |
TestIntegrationSetCreatesNewPath | 在空路径上 Set 创建新密钥 |
TestIntegrationOpenBAONamespace | OpenBao 多命名空间隔离读取 |
测试中用于准备 Vault 的脚本命令也很有参考价值,展示了服务端侧需要做的前置配置:
# 启用 AppRole 认证并写入策略与角色 vault auth enable approle vault policy write my-policy /tmp/policy.hcl vault write auth/approle/role/my-role policies=my-policy # 启用 KV 引擎并写入密钥(mount 路径与 secret 路径分别对应配置项) vault secrets enable -path=my-mount-path kv-v2 vault kv put -mount=my-mount-path my-secret-path secret-some-name=secret-some-value对应的最小权限策略样例见 testdata/policy.hcl:
path "my-mount-path/*" { capabilities = ["create", "read", "update", "patch", "delete", "list", "recover"] }安全与使用建议
- 敏感配置项不落明文:
token与approle.secret在 Telegraf 内部以受保护的config.Secret类型承载,底层使用 memguard 加密内存围栏(enclave)保管并支持显式销毁(参见 config/secret_protected.go),读取后调用Destroy()及时擦除; - 生产环境启用 TLS:
address应使用 HTTPS 地址,避免明文传输 Token 与密钥; - 认证方式选型:长期运行的服务优先使用
approle,让插件接管 Token 续期;若 Token 由外部系统供给,则用token并确保供给方负责续期; - 最小权限策略:按 testdata 中的思路,为 Telegraf 专门创建仅覆盖所需挂载路径的 Vault 策略,避免授予过宽权限。
小结
secretstores.vault插件为 Telegraf 提供了接入 HashiCorp Vault 生态的标准化能力:通过@{<id>:<key>}语法把敏感信息从配置中解耦,支持 Token 与 AppRole 两种认证、kv-v1/kv-v2 两种引擎以及命名空间隔离,并借助 lifetime watcher 实现 AppRole Token 的自动续期。结合仓库内的源码与容器化集成测试,你可以放心地将该插件纳入生产配置,实现密钥的统一托管与最小化暴露。
【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考