Telegraf 集成 systemd 凭据存储(systemd-creds)实现安全的明文凭据注入
【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf
导读
Telegraf 的systemd密钥存储插件(Secret Store Plugin)让 Telegraf 能够直接消费由 systemd 注入服务单元(service unit)的凭据(credentials),并在配置中以@{systemd:secret_key}的方式引用它们。本文基于plugins/secretstores/systemd/README.md,结合仓库中的源码与测试,系统讲解 systemd 凭据机制的运行原理、systemd-creds的加密/解密操作、Telegraf 侧的配置方法、多密钥存储链式解锁(chaining)实战,以及常见故障排查手段,帮助读者在 Telegraf 中安全地管理用户名、密码、Token 等敏感信息,避免将明文凭据写入配置文件。
插件概述与适用条件
plugins/secretstores/systemd是一个只读的密钥存储插件:它只负责读取 systemd 为服务注入的凭据文件,不能创建或修改这些凭据。凭据由 systemd 以明文文件形式呈递给受信服务,但在宿主系统上以加密形态存储;在硬件支持的情况下,加密还可使用 TPM2 芯片进行保护。
使用该插件需要注意两个版本门槛:
- 插件要求 systemd 250+。仓库源码
plugins/secretstores/systemd/systemd.go中以常量systemdMinimumVersion = 250硬编码了最低版本,插件在Init()阶段通过 systemd D-Bus 查询Version属性(见getSystemdMajorVersion),低于 250 会直接报错systemd version %d below minimum version %d。 - 若使用默认服务文件中的
ImportCredential,则需要 systemd 254+。scripts/telegraf.service中第 12 行即为ImportCredential=telegraf.*;更低版本只能改用LoadCredentialEncrypted在 service-override 中显式声明凭据。
该插件仅在 Linux 上构建,plugins/secretstores/systemd/systemd_nonlinux.go在非 Linux 平台为空实现,且插件注册代码secretstores.Add("systemd", ...)位于 Linux 构建标签的systemd.go中。
使用方式:@{<store-id>:<secret_key>}引用语法
密钥存储的使用方式与 Telegraf 全局的 secret 机制一致,参见 docs/includes/secret_usage.md:在 Telegraf 配置中,用@{<store-id>:<secret_key>}引用某个密钥存储中的密钥。
需要注意:
- 只有声明了
Secret store support章节的插件和选项才支持密钥存储。例如 plugins/outputs/influxdb/README.md 就明确写明username和password两个选项支持从密钥存储取密钥。 secretstores.systemd插件的密钥是静态的:只在 Telegraf 启动时解析一次,之后不会刷新。因此,修改或重新加密凭据后需要重启 Telegraf 服务才能生效。
配置参数
完整的配置示例如下(内容同步自plugins/secretstores/systemd/sample.conf):
# Reading systemd credentials [[secretstores.systemd]] ## 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 = "systemd" ## Path to systemd credentials directory ## This should not be required as systemd indicates this directory ## via the CREDENTIALS_DIRECTORY environment variable. # path = "${CREDENTIALS_DIRECTORY}" ## Prefix to remove from systemd credential-filenames to derive secret names # prefix = "telegraf."参数说明:
id(必填):该密钥存储的唯一标识符,用于在插件中通过@{<id>:<secret_key>}引用其中的密钥。path(可选):systemd 凭据目录的路径。正常情况下无需配置——systemd 会通过CREDENTIALS_DIRECTORY环境变量告知服务该目录位置。从源码Init()看,若CREDENTIALS_DIRECTORY未定义且未显式配置path,插件会直接报错'path' required without CREDENTIALS_DIRECTORY。同时Init()会把路径转换为绝对路径,并校验目录可访问(os.Stat),否则报accessing credentials directory %q failed。prefix(可选,默认telegraf.):从 systemd 凭据文件名中剥离的前缀,用于推导密钥名。默认前缀在注册代码中设定:secretstores.Add("systemd", func(_ string) telegraf.SecretStore { return &Systemd{Prefix: "telegraf."} })。List()实现里通过strings.TrimPrefix(entry.Name(), s.Prefix)去掉前缀后作为密钥名,Get(key)则通过filepath.Join(s.Path, s.Prefix+key)还原真实文件路径。若你使用了其他前缀或没有前缀,必须同步调整本项。
在服务进程内部,每个由 systemd 提供的密钥都以${CREDENTIALS_DIRECTORY}/<secret-name>文件形式呈现。普通(非 telegraf)用户看不到这些文件;其他 systemd 服务能否看到这些凭据,由其 service unit 中的User=与PrivateMounts=指令决定(详见 systemd.exec 手册)。值得注意的是,源码中Get()还对拼接后的路径做了目录校验:若filepath.Dir(secretFile) != s.Path会返回invalid directory detected,用于防止路径逃逸。
凭据管理(Credential management)
插件本身不能创建凭据,创建与管理交给systemd-creds完成。下文步骤浓缩自 systemd-creds 手册,命令的具体选项和动词可能随你使用的 systemd 版本而不同,请以对应手册为准。
示例中统一使用/etc/credstore.encrypted作为加密凭据的存储目录,并假设 Telegraf 通过包管理器安装(如需其他安装方式,可能需要自行创建该目录);同时假设密钥存储 ID 已设为systemd。
环境初始化(Setup)
如果打算用系统 TPM2 芯片保护凭据,先确认其可用性:
sudo systemd-creds has-tpm2输出形如:
partial -firmware +driver +system +subsystem若 TPM2 可用,凭据可通过 TPM2 sealing 与当前设备绑定。注意:一旦使用 TPM2 sealing,凭据只能在创建它的同一台机器上创建和使用,无法复制到其他机器——所需的解密密钥存放在 TPM2 中。
随后创建根密钥(root key)以完成凭据系统初始化:
sudo systemd-creds setup若生成密钥落在未加密磁盘上,命令可能给出警告——官方不建议将密钥存放在未加密磁盘。
创建凭据
创建加密凭据的基本命令:
echo -n "john-doe-jr" | sudo systemd-creds encrypt - /etc/credstore.encrypted/telegraf.http_user该命令会生成加密文件telegraf.http_user,其文件名即密钥存储提供密钥时的 key。为了避免明文凭据进入 shell 历史或显示在屏幕上,推荐用systemd-ask-password交互式输入:
systemd-ask-password -n | sudo systemd-creds encrypt - /etc/credstore.encrypted/telegraf.http_password关于命名有两处易错点:
- Telegraf 期望凭据文件以
telegraf.为前缀,且不要使用--name自定义名称。默认情况下 Telegraf 会剥离telegraf.前缀。 - 若使用其他前缀或完全没有前缀,必须调整密钥存储的
prefix配置。
关键限制:由于凭据来自 systemd 注入,本插件只在 Telegraf 作为 systemd 服务启动时才可用;命令行手动启动 Telegraf 时找不到任何凭据。因此,不要对该插件使用 Telegraf 的secrets管理命令(如telegraf secrets get/set/...)。
在 Telegraf 配置中使用凭据
先在配置中实例化systemd密钥存储:
[[secretstores.systemd]] id = "systemd"假设已有http_user与http_password两个凭据,即可在插件中这样引用:
[[inputs.http]] urls = ["http://localhost/metrics"] username = "@{systemd:http_user}" password = "@{systemd:http_password}"链式解锁(Chaining)实现无人值守启动
当凭据数量很多、或需要跨主机共享凭据时,把所有凭据一一列在 service 文件中既繁琐,也难以在命令行下手动测试配置(因为systemd密钥存储只在服务方式下可用)。此时可以借助密钥存储链:用一个密钥存储(这里是secretstores.systemd)解锁另一个密钥存储(示例为secretstores.jose)。
[[secretstores.systemd]] id = "systemd" [[secretstores.jose]] id = "mysecrets" path = "/etc/telegraf/secrets" password = "@{systemd:initial}"此处假设initial凭据经由 service 文件注入,它被用来解锁jose密钥存储;后者由加密文件承载、可以提供大量不同密钥。随后输入/输出插件即可通过@{mysecrets:...}引用jose提供的密钥,填充用户名、密码或 Token 等敏感数据。这既规避了 service 文件中堆砌大量凭据的问题,也让共享/分发密钥更灵活。
源码实现要点
从源码层面可以更清晰地理解插件行为(plugins/secretstores/systemd/systemd.go):
Init():检测 systemd 版本(低于 250 报错)→ 读取CREDENTIALS_DIRECTORY环境变量作为默认路径 → 解析绝对路径并校验目录存在与可访问。List():读取凭据目录下的所有文件,剥掉prefix前缀后返回密钥名列表。Get(key):按path + prefix + key拼出文件路径,做目录防逃逸校验后读取文件内容返回。GetResolver(key):返回一个解析函数,其中动态标记恒为false,印证了“密钥是静态的、启动后不刷新”的特性。- 接口契约:
secretstore.go中定义的telegraf.SecretStore接口要求实现Init、SampleConfig、Get、List、GetResolver;可读写的密钥存储还要实现可选的SecretStoreEditor接口(Set/Remove)。systemd 插件不实现SecretStoreEditor,源码注释也明确这是“只读源”。 - 注册机制:
plugins/secretstores/registry.go维护全局SecretStores注册表,init()中通过secretstores.Add("systemd", ...)完成注册。
测试文件plugins/secretstores/systemd/systemd_test.go与testdata/目录(内含secret-file-1、secretFile、secret_file_2三个模拟凭据文件)覆盖了版本下限校验、缺少CREDENTIALS_DIRECTORY时的报错、目录不可访问、List/Get/GetResolver及不存在的密钥报错等场景,可作为理解插件行为的参考。
故障排查(Troubleshooting)
排查前,先确认 systemd 版本满足要求(250+,ImportCredential需 254+)。
- 服务无法启动:检查服务日志。常见原因是使用了
--name选项——它和 systemd 的ImportCredential设置不兼容。同时核对systemd-creds encrypt时写入的名称与LoadCredentialEncrypted语句中使用的名称是否一致。 - Telegraf 中引用不到凭据:可以用下面的命令查看当前可用凭据(
CREDENTIALS_DIRECTORY指向加密凭据目录):
CREDENTIALS_DIRECTORY=/etc/credstore.encrypted sudo systemd-creds list对应前文的示例,输出类似:
NAME SECURE SIZE PATH ------------------------------------------------------------------- telegraf.http_password insecure 146B /etc/credstore.encrypted/telegraf.http_password telegraf.http_user insecure 142B /etc/credstore.encrypted/telegraf.http_user注意:NAME列中的名称还要去掉密钥存储中配置的prefix(默认telegraf.),才能得到密钥的key。
- 查看凭据实际值:
sudo systemd-creds decrypt /etc/credstore.encrypted/telegraf.http_password -⚠️ 上述命令会泄露凭据的明文值,请务必谨慎使用!
补充说明
- 本插件只支持读取密钥,无法创建或修改它们;创建/修改请使用
systemd-creds。 - 默认的 Telegraf systemd 服务文件
scripts/telegraf.service已配置ImportCredential=telegraf.*与User=telegraf、PrivateMounts=true,安装 Telegraf 后基本可开箱即用;使用低于 254 的 systemd 时需改用LoadCredentialEncrypted覆盖声明。 - 有关 Telegraf 密钥存储的全局配置方式与更多插件支持情况,可查阅 docs/CONFIGURATION.md 中 secret store 相关章节,以及各插件 README 的
Secret store support部分。
【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考