Ansible Vault: 加密 Ansible 仓库里的密钥

解决什么问题 Ansible 仓库里迟早会出现密钥:数据库密码、API token、TLS 私钥。playbook 和变量文件要进 git,密钥如果跟着明文进去,所有能克隆仓库的人和程序就都拿到了它,而且会永远留在历史里。 Ansible Vault 是 Ansible 自带的加密功能(命令是 ansible-vault,不用另外安装)。它解决的是一件事:让密钥以密文的形式和 playbook 放在同一个仓库里,运行 playbook 时自动解密。 它和 HashiCorp Vault 没有关系,只是名字像。HashiCorp Vault(以及它的 fork OpenBao)是一个常驻的密钥服务;Ansible Vault 只是一个文件加密工具,没有服务端。 原理 加密后的文件是这样的: $ANSIBLE_VAULT;1.1;AES256 62313365396662343061393464336163383764373764613633653634306231386433626436623361 6134333665353966363534333632666535333761666131620a663537646436643839616531643561 ... 第一行是头部:格式版本 1.1,算法 AES256。用了 vault ID(见下文)时版本是 1.2,头部末尾多一个标签。 加密过程:从 vault 密码用 PBKDF2-SHA256 加随机盐派生出密钥,用 AES-256(CTR 模式)加密内容,再用 HMAC-SHA256 防篡改,最后转成十六进制文本。 整个仓库通常只用一个 vault 密码。谁有这个密码,谁就能解开所有加密文件。 两种加密粒度 加密整个文件 # Create a new encrypted file and open it in $EDITOR ansible-vault create group_vars/prod/vault.yml # Encrypt an existing plaintext file in place ansible-vault encrypt group_vars/prod/vault.yml # Edit / view without leaving a plaintext copy on disk ansible-vault edit group_vars/prod/vault.yml ansible-vault view group_vars/prod/vault.yml # Change the password ansible-vault rekey group_vars/prod/vault.yml 只加密单个变量 ansible-vault encrypt_string 's3cr3t' --name 'db_password' 输出可以直接贴进普通的变量文件,文件其他部分仍是明文: ...

Created 20206-10-20 · Updated 20206-10-20 · 2 min · 301 words · -

Homelab Secrets Management: Bitwarden、rbw 与 OpenBao

我在整理 homelab 的配置仓库时发现,有不少密钥以明文形式进了 git:数据库密码、云服务的 API token、K8s Secret 的 manifest。还有一些放在 ~/.zshrc.local 里,作为环境变量。这篇文章记录我比较几种方案之后选定的思路,以及其中涉及的概念。 最后选的组合是:Bitwarden + rbw 管人在场的场景,OpenBao 管集群里的自动化,没有用 SOPS。 先分清「存放」和「使用」 讨论密钥放在哪里时,容易把两件事混在一起: 存放(数据源,长期) 使用(临时) git 里的密文 / Bitwarden / OpenBao → 环境变量、内存、临时文件 使用的那一刻必然是明文,任何方案都绕不开,程序总得拿到真实值。能做的是让它短暂、范围小:只在一个子进程里,不长期落盘。 真正可以选择的是存放在哪里,而且不一定要是 git。 对照这个划分,原来的两个问题分别是: 做法 问题 明文进 git(即使是私有仓库) 协作者授权、第三方 App 授权、CI 克隆、哪天转 public,都会把全部历史一起交出去 放在 ~/.zshrc.local 磁盘上是明文;shell 启动的所有子进程一直都能读到,包括各种 CLI、npm postinstall 脚本、AI agent 分类原则:谁在用,有没有人在场 场景 存在哪里 怎么取 是否需要人在场 本地开发和运维(tofu、Ansible、脚本) Bitwarden rbw get,只注入单条命令 需要 集群自举密钥(集群启动时就必须存在的少数几个) Bitwarden 重建集群时,由人执行脚本创建 需要,只在重建时 集群里应用运行时用的密钥 OpenBao 程序用自己的身份去取;数据库用动态凭据 不需要 核心思路:人在场就从 Bitwarden 取;没有人在场,就交给一个在线服务(OpenBao),程序用自己的身份去取。 ...

Created 12126-10-12 · Updated 12126-10-12 · 3 min · 638 words · -

SOPS: Secrets OPerationS 简介

SOPS 是什么 SOPS(Secrets OPerationS)是一个命令行工具,用 Go 写的。它最初由 Mozilla 开发,2023 年迁到 getsops/sops,现在是 CNCF 项目。 它只做一件事:加密和解密结构化文件,支持 YAML、JSON、ENV(dotenv)、INI 和二进制文件。典型用法是把密钥加密后提交到 git,这样 git 里只有密文。 它不是常驻服务,也不负责存储。密文就是普通文件,解密由你在需要的时候显式调用。 原理 信封加密 每个文件随机生成一把 data key,用 AES256-GCM 加密文件里的值。 再用一把或多把 master key 加密这把 data key,结果写进文件末尾的 sops: 元数据段。 master key 可以是 age、PGP、AWS/GCP/Azure 的 KMS、HashiCorp Vault(或 OpenBao)的 Transit 等。同一个文件可以同时加密给多把 master key,任意一把都能解开。 只加密值,不加密键 stringData: POSTGRES_PASSWORD: ENC[AES256_GCM,data:3mZ0...,iv:...,tag:...,type:str] sops: age: - recipient: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p enc: | -----BEGIN AGE ENCRYPTED FILE----- ... mac: ENC[AES256_GCM,data:...,type:str] git diff 能看出改的是哪个字段,review 时不用解密也能看懂结构。 非敏感字段(比如 K8s 的 metadata)可以保持明文。 文件带 MAC,密文被篡改时解密会报错。 age age 是一个小巧的文件加密工具,可以看作 PGP 的现代替代品,SOPS 官方也建议优先用它。 ...

Created 12126-10-12 · Updated 12126-10-12 · 2 min · 270 words · -