Helm 插件之 helm-secrets(利用 PGP 加密你的 Values 文件 | IDCF)

在使用 Helm 部署应用程序时,我们经常会遇到需要为所要部署的应用程序设定敏感信息值的情况,如:为应用程序自身设定登陆名和密码信息,或设定应用程序连接数据库时所需的信息等等。
若将这些包含了敏感信息的值直接以明文的方式存储在自定义的 Values 文件中,尤其是当使用如 Git 等代码版本控制工具追踪 Values 文件时,将会带来非常大的安全隐患。
因此,我们通常不会将这些包含有敏感信息的值保存在 Values 文件中,而是在部署的过程中,通过 HELM 命令的 --set 参数,以命令行的形式为这些变量设定值。
但使用这种方式同样也有它自身的局限性:首先,如果要设定的敏感字段过多,则在命令行中需要指定的参数就越多,这将使得命令行过于冗长且容易出错,同时部署人员需要记住的部署参数也变得复杂起来;其次,通过查看系统执行过的命令历史记录,同样能够获取到在执行 HELM 命令时所有指定的敏感信息参数,这在一定程度上同样存在安全隐患。
而本文将介绍另一种相对来说比较完美的解决方案:利用 Helm 的 secrets 插件,将这些包含了敏感信息的值通过某种加密手段加密之后,在保存到 Values 文件中去。
HELM SECRETS 插件简介 helm-secrets 插件可以帮助我们将定义在 values.yaml 文件中的值进行加密之后重新存储到 Values 文件中,被加密后的 Values 文件可以被随意分发、存储到代码版本管理工具中而不用担心敏感信息被暴露。下面是一个加密后的 Values 文件示例:

#ENC[AES256_GCM,data:IHAqGPYHlUdD2+xSn5ZcYCo=,iv:1KKx8l1zl41LuNYcKw3biXm0vx+vjAeA7wdnNHYjQ6Y=,tag:MmWG4SIeXPt0o0HOHGtJeQ==,type:comment] registry: url: ENC[AES256_GCM,data:sYON9+wBDq9jcmhy8iUaITpIjApLbys=,iv:z/ITKkJp2rS/jMyvxghweA+7W0QlZ98PR+4gDGhX+WI=,tag:TLbCkMcIfW30/80FpaozoA==,type:str] username: ENC[AES256_GCM,data:5Ju2bxk=,iv:hxRUoi0lViW7chOQTiyZyt4nGMS5V5YZyFNf19LmvpA=,tag:lb830A5pnZ4bI0HUosyc7Q==,type:str] password: ENC[AES256_GCM,data:1WmPZCSlzGbSn2LqMc7DmHjQKTjsaPUdn9nMKvbl+KIJ451EPkV0s3dqF+NVZ5E+T6reYN/lY7Ok3VmGvboVAbFs1IYzn7KenbGLMGgCT+JhUFaYz16TeGGsyWDk6YcIIw/XzR6lTjilpHF+DuZuepOyiAnCO0Q5k4aux2lICQh6P8mOezt8flP9/blnFGVZhaaE5r5vT6hsaQbsy7Rnk2lP926xT8NWcaXR85AleRvevQ/zwFIFjjk=,iv:ivA6U20LCHOoR9WGSmuvlJdhnYx/ZC8Pw9czMjNrrlI=,tag:wX3SiiBv8OjSZkpbCznDZw==,type:str]jenkins: master: JCasC: configScripts: credentials-config: ENC[AES256_GCM,data:3dN7KBW...Ov/rsUA=,tag:qlfV/0x0vr45JxMYM1UdMQ==,type:str] sops: kms: [] gcp_kms: [] lastmodified: '2019-07-10T06:21:36Z' mac: ENC[AES256_GCM,data:sKsL25V5yci+oD1PpfA5fU6zE7YCc6Sxg7myE4eqoDcA+guG8gUg4Hcj5yAB4APBq3+KtPIXoF0hNHVYZOOYqZXQrMpO0jASjWHmLAFTUb6FE6xOtb4mP3FBk8W6Km7TfNz3Te8WW4nsb/+c0WmFSQnIolaeXgbbZhZ23x+V9g=1,iv:Oha7rwD2y3xCc+UnI+xXwrnFByMhNJkF84TiYq4/LsWI=,tag:W3e9ox2G9QL5jQEV0VwGA==,type:str] pgp: -created_at: '2019-07-10T06:21:34Z' enc: | -----BEGIN PGP MESSAGE-----hQEMA9Q2nDmrg55qAQf/aXiC7EXZlP5OZDrH3clCb0I9uqP8eNhVgAzqyfSaajGB ... =h7fE -----END PGP MESSAGE----- fp: AD331C18082B4669992805DDCB8EA0C7BC44A464 unencrypted_suffix: _unencrypted version: 3.0.3

可以看到,加密操作仅仅是针对 YAML 文件中所有 Key 对应的值进行的,而保留了 Key 本真。相对于那种针对整个 YAML 文件进行整体加密的方式来说,通过这种加密方式加密后的文件,仍然保留了很强的可读性,这使得我们对加密后的 YAML 文件进行维护变的可能。
而当我们部署应用程序时,直接将加密后的 Values 文件传递给 HELM 命令,helm-secrets 插件则会自动负责为我们对加密的值进行解密操作,整个过程无需任何人为干预。
安装 helm-secrets 插件 在使用 helm-secrets 插件之前,首先确保该插件被安装到了本地 HELM 中,安装 HELM 插件非常简单,使用下面命令直接进行安装即可:
$ helm plugin install https://github.com/futuresimple/helm-secrets

安装完成后,可通过 HELM 的 list 命令查看插件是否安装成功:
$ helm plugin list NAMEVERSIONDESCRIPTION secrets2.0.2This plugin provides secrets values encryption for Helm charts secure storing

SOPS 命令简介
事实上,helm-secrets 插件本身并没有任何加密与解密的能力,也没有提供任何只针对于 YAML 文件的 Key 值进行加密和解密的工作方式,而它所有的工作,都是通过调用 SOPS 命令来帮助它完成的。
SOPS 是由 Mozilla 开发的一款开源的文本编辑工具,它支持对 YAML, JSON, ENV, INI 和 BINARY 文本格式的文件进行编辑,并利用 AWS KMS, GCP KMS, Azure Key Vault 或 PGP 等加密方式对编辑的文件进行加密和解密。
我们会在后面的小节中对 SOPS 做进一步的介绍。此时,你只需知道 SOPS 命令是确保 helm-secrets 插件可以正常工作的必不可少的依赖,因此,我们必须要确保系统中正确安装了 SOPS 命令。
幸运的是,helm-secrets 插件会自动检测并安装 sops 命令到我们的系统中,因此在插件安装完成后,你还应该可以运行 sops 相关命令,如获取 sops 的版本信息:
$ sops -v

当然,你也可以通过手动方式选择自行安装 sops 工具,如使用 brew install sops 命令为 Mac 系统安装 SOPS,或直接下载 SOPS 的可执行文件,更多信息请查看 SOPS 文档。
如果以上命令全部执行成功,那么恭喜你,你已经成功安装了 helm-secrets 插件及其相关依赖。但在真正介绍如何使用该插件之前,我们还需要了解一些加密解密相关的基础知识和命令。
PGP 简介
正如前面所讲,helm-secrets 插件是通过调用 SOPS 命令来对我们的 Values 文件进行加密和解密的,而 SOPS 本身又支持多种加密方式,如 AWS 云的 KMS,Google 云的 MKS,微软 Azure 云的 Key Vault,以及 PGP 等加密方式。本文将着重介绍如何利用 PGP 对我们的 Values 文件进行加密和解密。
PGP 与 GPG 在了解 PGP 加密之前,我们首先要区分好两个名词概念:PGP 与 GPG。
Pretty Good Privacy,也就是我们平时所说的 PGP,实际上通常指的是 OpenPGP。OpenPGP 只是一系列协议或标准,而并非某个特定的工具或命令,它规定了如何使用特定的方式和算法对文件或内容进行加密和解密,任何实现了 OpenPGP 协议的工具都拥有加密和解密的能力。而本文接下来所要使用的 gpg 命令,正是这样一个实现了 OpenPGP 协议的工具,或者说命令,利用 gpg 命令,我们可以实现 PGP 加密方式。为了避免混淆,后文将一律使用 GPG 代替。
安装 GPG GPG,全名 GNU Privacy Guard,是隶属于 GNU 项目下的一款开源免费的加密工具。目前绝大部分 Linux 发行版本都默认安装了 GPG,直接运行下面命令查看你当前所在系统中是否已经正确安装了 GPG:
$ gpg --version

你也可以尝试使用下面命令手动安装 GPG 到你的系统中:
# Ubuntu,Debian 用户 $ sudo apt install gnupg# CentOS,Fedora,RHEL 用户 $ sudo yum install gnupg# MacOS 用户 $ brew install gnupg

生成 GPG 密钥对 如果你使用过 SSH,那么你一定熟悉公钥和私钥的概念,GPG 同样也使用了公钥和私钥的概念实现了非对称加密算法。简单来说:公钥用于加密,拥有公钥的人可以且仅仅可以进行加密操作,它可以分发给任何组织或个人;而私钥则用于解密,且仅能用于解密那些由该私钥与之配对的公钥加密的信息,任何拥有私钥的人都可以进行解密操作,因此,确保私钥不被泄漏对安全性起着至关重要的作用。
在使用 gpg 命令进行加密解密之前,首先需要生成 GPG 公钥和私钥。你可以使用命令 gpg --gen-key 来交互式地生成密钥对,之所以说交互式,是因为在生成密钥对时会要求用户交互式的输入一些相关信息,如如用户名、邮箱等等。你也可以使用下面命令直接生成出密钥对,注意,在执行命令之前,请注意修改下方 name、email 等字段信息为你自己相应的信息:
$ gpg --batch --generate-key <

该命令将会为我们生成一对长度为 4096 且永不过期的 RSA 密钥对,gpg 命令支持使用更多的参数来控制生成密钥对,如为生成的密钥对设定使用密码等等,更多关于 GPG 命令的使用参数,请参考官方文档。
当生成 GPG 密钥对以后,我们就可通过 gpg 的 --list-keys--list-secret-keys 命令分别列出当前系统中的公钥和私钥信息了:
$ gpg --list-keypubrsa4096 2020-04-24 [SCEA] 13D525EEF0A5FA38F4E78F7900E0160999E3C663 uid[ultimate] HELM Secret (Used for HELM Secret Plugin) subrsa4096 2020-04-24 [SEA]

上面命令列出了当前系统中的公钥信息,其中 13D525EEF0A5FA38F4E78F7900E0160999E3C663 或者后十六位 00E0160999E3C663 为公钥的 ID。
我们也可以通过传递密钥的用户名、邮箱或 ID 来查看某个特定的密钥信息:
$ gpg --list-key "HELM Secret" # 或 $ gpg --list-key "helm-secret@email.com" # 或 $ gpg --list-key 00E0160999E3C663

在生成了密钥对之后,就可以利用它们来为我们的文件进行加密和解密操作了。
使用 GPG 加密和解密文件 为了更好地理解 help-secrets(或 SOPS 命令)的优势,我们首先尝试直接使用 gpg 命令来加密我们的文件:
首先创建一个名为 secrets.values.yaml 的文件,并写入以下内容:
App: username: login-user password: login-pwd

使用 gpg 命令对该文件进行加密:
$ gpg -e -r 00E0160999E3C663 secrets.values.yaml

  • -e 参数指定本次为加密操作
  • -r 参数指定了加密时所要使用的公钥信息,这里直接通过公钥 ID 来指定,我们也可以使用密钥的用户名和邮箱等信息,如 HELM Secrethelm-secret@email.com
当加密完成后,GPG 命令会在 secrets.values.yaml 文件所在的目录下创建一个与它同名,且以 .gpg 结尾的新文件 secrets.values.yaml.gpg
该文件包含了加密后的内容,如果你尝试查看该文件内容,会发现整个文件内容将会以乱码的形式展现出来,而这正式 GPG 的工作方式。
当然,我们也可以使用 gpg 命令对某个加密过的文件进行解密操作:
$ gpg -d secrets.values.yaml.gpg gpg: encrypted with 4096-bit RSA key, ID C79B2F32F9EE1A8E, created 2020-04-24 "HELM Secret (Used for HELM Secret Plugin) " App: username: login-user password: login-pwd

-d参数用指定 GPG 命令执行的是解密操作。与加密操作不同,我们并没有指定解密时要使用的私钥 ID,这是因为 GPG 在加密的同时,将解密时所需的私钥信息一并写入到了加密后的文件中去。当然,你仍然可以使用 -r C8EABE3FAE86D256 参数明确指定解密时使用的私钥 ID。你可能已经注意到了,其实私钥 ID 与公钥 ID 完全相同。
当解密操作成功后,GPG 命令会将解密后的内容直接打印到屏幕上。
至此,我们成功地使用了 GPG 命令对文件进行了加密和解密操作,但不难看出,GPG 的加密操作是针对整个文件进行的,而加密后的文件内容也将变得完全无法维护。
接下来,就让我们简单看一下,如何使用 SOPS 命令对这种 Key-Value 类型的文件进行加密和解密,并同时保证加密后的文件的可读性和可维护性的。
SOPS 的简单使用
为了更好地理解 helm-secrets 插件,先让我们简单看一下如何通过 SOPS 命令使用我们刚刚生成的 GPG 密钥对来对 YAML 文件进行加密和解密操作:
依然使用我们前面创建好的 secrets.values.yaml 文件,并确保写入了以下内容:
App: username: login-user password: login-pwd

使用 sops 命令对 secrets.values.yaml 文件进行加密:
$ sops --encrypt --in-place --pgp 00E0160999E3C663 secrets.values.yaml

  • --encrypt, -e 参数告诉 sops 进行加密操作;
  • --in-place, -i 参数指定将加密后的内容直接替换掉原文件内容,若不指定该参数,则加密后的内容将会被输出到屏幕上;
  • --pgp, -p 参数指定我们加密时所要使用的 PGP 公钥 ID。
查看加密后的 secrets.values.yaml 文件内容:
$ cat secrets.values.yamlApp: username: ENC[AES256_GCM,data:VwLJ94VxsEBMZg==,iv:Qeb6aNT1oryPplmtUx1ufIeiqwJ9APllLnorqvkdjRU=,tag:CuWtAlLEZeOuQFoW34FiEQ==,type:str] password: ENC[AES256_GCM,data:jo8lGGOFZuDY,iv:5Wwt/T0SskFxgWXNRjpoIPq+PIuTGILGIeN/dYOJ/Fg=,tag:ncC3t67xArsXvwwEjAGyLg==,type:str] sops: kms: [] gcp_kms: [] azure_kv: [] lastmodified: '2020-04-24T03:48:37Z' mac: ENC[AES256_GCM,data:uFdXa2qWDSYqaeVsOLZiQos5K611uZYW91ZhLT00MJRb32TxE190RlJjhvl8+/GUOClZcIaU8DejebDP1TVqVFl6wpFqjVM3TLwW0JDm+b+zpCzMje9e17dNjLp7W2awBTPmrF3AXUopLi8oHOuopW89q2gKgFIUW215zjmQET0=,iv:A85xzE6gEXpcwUE6rIvHwHNhqmaCmFOHoYX3Y4qjaGI=,tag:VSB9b9vKLRJg4/klwliJbQ==,type:str] pgp: -created_at: '2020-04-24T03:48:35Z' enc: | -----BEGIN PGP MESSAGE-----hQIMA8ebLzL57hqOAQ//fOzjkY5tW1/fGd/HWrxsgC02YxAjmHggI2ek5VacdhYP A9RUYhpipJpBt1LnwHq/B1rV1E4dkOu1lpyAmI9P0qIc+6o0+6jEhqEyjsDQSGn5 kh31oBNYfLq8XpHQg33jOIHpv6/BU7tqzsVMum3HjvnsSrhc3gRtBq5LZoLP/smA 3y36tRLHIGFGqOEwy3CdSiPmsyCKQBEYRK0+7mhXX+ulEMudYXKgXk4qCL1UAB0y X03K0UATNYp8fRkHqzcpf5nLDNzpCGI0BNbxBQYZdbcP3KFNyKGDFtDaNCcJq9jv d6yMnioNWYBCtDlrZXlQGzipheWKwZ7JnNa1nmYpCJ3uh6I3mbtkHjljD88QUm6Y czGAsTDYESJPl5y2wdKdMxHOyE++Ii5LvNr2UD3D+ePYvAIpK1TWjfokCe18ZvvD v4kHbqbJfffpLCmy0CRVFu/yLnGdZGqniPY/UPPRk28cnKF+fxpX7EmLvzCUgadC 4emIrR6nBUgGvU+fInZrNOccRhYU2S4So45CW2EXW5E4uNj8ayfUgtaUeRwW8pRE ZMGe1yna7a8UC0syiubC1rr8KHKs8nITfRrelV/BtEkfFDI9sm77AMcaWaAaaBz8 C1L3A1iPhnclDnt3USqOTioLnZs9CjysyNSeiTvehsTC1E3GqgmVbUGob+0Im2fS XgHaA9fXLtulXkRQGFYpaNEt6r0mkgdq0DXCCfba6EflHg9BvPfrK0dtXrchlCY/ K154U0LkPNHtLBXB0rNwz0Z9aA1CwBdRZ6r8V67SJS1nbsiIvyHfc4dq8n3qhVM= =HOrp -----END PGP MESSAGE----- fp: 00E0160999E3C663 unencrypted_suffix: _unencrypted version: 3.5.0

不难看出,SOPS 仅仅是对 YAML 文件中的值进行了加密,而保留了所有 Key 信息,这使得即使是加密后的文件仍然保留了很强的可读性。
此外,SOPS 还在文件中追加了一个新的 Key 值 sops,用于保存加密该文件时所使用的一些加密信息。
当然,我们还可以通过 sops 命令对加密后的文件进行解密操作:
$ sops --decrypt secrets.values.yamlApp: username: login-user password: login-pwd

--decrypt, -d 参数指定我们要对文件进行解密操作。当然,你也可以通过 -p 参数将解密时的私钥 ID 传递给 SOPS 命令,但这通常是不必要但,因为与 GPG 一样,SOPS 在加密文件时会自动解密时需要的私钥 ID 记录在内。
通过上面的操作,我们成功地使用 SOPS 命令对 YAML 文件进行了加密和解密操作,而这也正是 helm-secrets 插件背后的工作流程。在了解了 SOPS 工作模式之后,接下来,让我们开始正式步入 helm-secrets 插件的学习中去。
开始使用 helm-secrets 插件
在掌握了 GPG 和 SOPS 的一些基本原理和操作后,学习使用 helm-secrets 插件就将变得特别简单起来。
helm-secrets 插件会为 HELM 命令创建一个新的子命令: secrets,所有关于该插件的子命令,都是通过 helm secrets 格式所调用的。首先让我们通过 -h 参数打印出 helm-secrets 插件的帮助文档信息:
$ helm secrets -hGnuPG secrets encryption in Helm ChartsThis plugin provides ability to encrypt/decrypt secrets files to store in less secure places, before they are installed using Helm.To decrypt/encrypt/edit you need to initialize/first encrypt secrets with sops - https://github.com/mozilla/sopsAvailable Commands: encEncrypt secrets file decDecrypt secrets file viewPrint secrets decrypted editEdit secrets file and encrypt afterwards cleanRemove all decrypted files in specified directory (recursively) installwrapper that decrypts secrets[.*].yaml files before running helm install templatewrapper that decrypts secrets[.*].yaml files before running helm template upgradewrapper that decrypts secrets[.*].yaml files before running helm upgrade lintwrapper that decrypts secrets[.*].yaml files before running helm lint diffwrapper that decrypts secrets[.*].yaml files before running helm diff (diff is a helm plugin)

帮助文档信息列出了 helm-secrets 插件支持的所有子命令,而这些子命令又可以被划分为两类:
  • 一类是由该插件提供的子命令,如 encdecviewedit 以及 clean 等,这些子命令由该插件所创建,而在 HEML 中并不存在;
  • 另一类则是在 HELM 中已经存在的子命令,如 encdecviewedit 以及 clean 等。对于这些本就存在于 HELM 中的子命令来说,helm-secrets 插件仅仅是对这些子命令做了一层封装操作,而背后真正调用的仍然是 HELM 自身的这些子命令,因此通过 helm-secrets 插件调用这些子命令时的用法与直接通过 HELM 调用的用法完全一致。
提示:你还可以为某个特定的子命令使用 -h 参数,来获取该子命令的帮助文档信息,如 helm secrets dec -h
下面让我们通过部署一个实际的例子,来演示 helm-secrets 插件是如何工作的。
PostgreSQL PostgreSQL 是由伯克利大学开发的一款有着 30 多年历史的开源关系型数据库,如今仍被大量的公司和企业所使用。HELM 官方 Chart 仓库也提供了稳定版的 PostgreSQL Chart,来帮助我们在 Kubernetes 平台上快速部署 PostgreSQL 集群。接下来,就让我们尝试使用 helm-secret 插件部署一个 PostgreSQL 数据库集群到我们的 Kubernetes 平台上,来看看它是如何帮助我们保护我们的敏感信息不被泄漏的。
默认情况下,PostgreSQL Chart 会为部署的 PostgreSQL 实例创建一个名为 postgres 的管理员账号,并生成一个包含 10 位字符的随机字符串作为它的密码。我们可以通过为 Chart 设定 postgresqlUsernamepostgresqlPassword 的值,来手动指定管理员的用户名和密码信息。
首先创建一个包含如下内容的 secrets.yaml 文件:
postgresqlDatabase: my-database postgresqlUsername: admin postgresqlPassword: admin

该文件指定了为部署的 PostgreSQL 实例创建一个名为 admin 的管理员账号,同时设定它的密码为 admin。
尝试直接使用 HELM 命令通过该 Values 文件做一次测试部署:
$ helm install postgresql stable/postgresql -f secrets.yaml --dry-run --debug

上面的命令中由于我们使用了 --dry-run 参数,因此它只会将所有将要部署到 Kubernetes 平台上到资源全部以 YAML 的格式输出到屏幕上,而不会做真正的部署。
如果你仔细查看输出的 YAML 信息,会发现该 Chart 会创建一个包含了一个名为 postgresql-password Key 的 Kubernetes Secret 资源,其值为 “YWRtaW4=”,使用命令 echo "YWRtaW4=" | base64 -d - 将该值进行 base64 转译之后输出到屏幕上,我们会得到 “admin”,这说明我们在 secrets.yaml 文件中的配置已经生效。
加密 secrets.yaml 文件 正如你所看到的那样,PostgreSQL 的管理员用户名和密码都以明文的方式存储在了 secrets.yaml 文件中。接下来,就让我们使用 helm-secrets 插件的 enc 子命令对该文件进行加密:
$ helm secrets enc secrets.yaml

如果你直接执行上面命令,有可能会和我一样得到下面的错误信息:
Encrypting secrets.yaml config file not found and no keys provided through command line options Error: plugin "secrets" exited with error

该错误信息是由 SOPS 命令报错的,它提示我们说,当它尝试加密文件时,即没有在配置文件中找到加密时要使用的公钥信息,也没有在命令行中指定公钥信息。
换言之,就是 SOPS 不知道使用哪个 GPG 公钥对文件进行加密操作。通过前面的学习我们知道,可通过 --pgp, -p 参数将密钥对信息传递给 SOPS 命令,但由于这里是通过 helm-secrets 插件调用的 SOPS 命令,我们无法像使用 SOPS 命令本身那样通过参数的方式传递信息。
其实 SOPS 命令还提供另外两种设定 GPG 密钥对信息的方式:通过设定环境变量和配置文件的方式来指定 GPG 密钥对。
设定环境变量:
如果我们没有在命令行通过 --pgp, -p 参数为 SOPS 指定密钥信息,那么它则会尝试从 SOPS_PGP_FP 系统环境变量中获取该信息,因此我们可以将密钥对 ID 指定给该环境变量:
$ export SOPS_PGP_FP=00E0160999E3C663

SOPS 配置文件:
SOPS 还支持另一种更加灵活的方式来指定密钥信息 —— 配置文件。每当执行 SOPS 命令时,它都会在当前目录下查找名为 .sops.yaml 的文件作为它的配置文件,下面是一个最基本的 SOPS 配置文件:
creation_rules: - pgp: "13D525EEF0A5FA38F4E78F7900E0160999E3C663"

事实上,SOPS 的配置文件能做到的远远不止这些,我们可以在配置文件中设定多条规则,并为每条规则设定不同的密钥信息,以达到不同的文件使用不同的密钥进行加密和解密,更多关于 SOPS 配置信息,请参考 SOPS 文档。
当为 SOPS 配置好密钥信息后,再次执行 helm secrets enc secrets.yaml 命令重新为 secrets 文件加密。加密操作会讲加密后的内容将直接覆盖掉原 secrets.yaml 文件中的内容,查看加密后的 secrets.yaml 文件:
$ cat secrets.yamlpostgresqlDatabase: ENC[AES256_GCM,data:aZNFdHVIgJkWDiI=,iv:zsban/onWOllCou/lpgIUzZoIGlZAjTHcVmG+Xu+asI=,tag:lCbMEVCsR7Nhc+jBZTc1Ng==,type:str] postgresqlUsername: ENC[AES256_GCM,data:/9ciQtc=,iv:+csoC+vx7wfT8WHrzECktG1UU/sVq+Q44zdJZHMPDaU=,tag:DHiCF1x7hyHnYi7gMFm3Lg==,type:str] postgresqlPassword: ENC[AES256_GCM,data:9xAlAbg=,iv:EH+DmDZU9g/u6eCMkaNBDhxpPkDpX7HQrhcAFVPVqOw=,tag:snEhGpmkRAwjuVrxYHCOiA==,type:str] sops: kms: [] gcp_kms: [] azure_kv: [] lastmodified: '2020-04-24T04:56:24Z' mac: ENC[AES256_GCM,data:KQ5P2C55mdaUt1EFqV9411rXY7pi/dQlRQ/FcW6BqQe45u/ZqhCNR1VD8H2tZ4BRl1mQ4xOGzOYdzddKRc/D0vNHVyoEI4IRd2Jd+QnICINDwQ/Xq9kXysOSnV308DSV+EAabxreIDKdvV7RF3b5GGoEifXS8YDVhQmQjfGyhwU=,iv:sR2TI9W+1YAzfY5k82tnkrN4Q+vH3kxITGi9kzLOMq4=,tag:auUx5q6imy2nVfJLsBoGrg==,type:str] pgp: -created_at: '2020-04-24T04:56:22Z' enc: | -----BEGIN PGP MESSAGE-----hQIMA8ebLzL57hqOAQ/+Oq3bVKIx8T9EqI1EyvBeuW2lN95MDAjZD/+77ntTixW/ zNintG5dEPT9Uqi1mlwTCqZF9D1ptuQMgLgvddV/PPLG7afO60yy1kQW2+jGWons N0HuinVvESs7GCj+xMBd0cyKZ0iYqbafg4Mub60T0qX4/w9IuDV1o/vswceajmaC YkKF/ATMnLEV0UVVeXwzyVWFGrmworPWStyx9WgB3Vj0VEYGQPub6JzSRUyGdHVr 2JljSKlTzAzlAUbcEvKCxjWWBypkvNTMua9AhMtYtagbRlcJuSFdOIAgbIVHW6Qd C06b/HL5+B8umeweN36g5BSjUiD8HmtpFEKBT92WKuYfRFijkCSME3VhVGvHm4Zo fPPLQRswf5dRu8IXBFW52/W36/ZgzzA1kqf1cGCTETMMQghxeRSuQU9caZ4L0UFm ZbXdB+w92XZjiNVR5EpA1hDLbBQVKqUjZ92dpmNql5bzKoBObT+p/7hb8ixNLc66 EBgPbefbAdQBkwuelSdNIi2vfkSFVxMLDvsL5Zn8YLrEbjaresQ0rvugxIUj4190 moZ/I08HmsfyC02xGReK0ZCmbWR/+NcSJJOqofNAFrK0ritcT8hUPN86VuhVS6xp NaT1FTLBCae8vqsn1FIK09f+u64hxfQiOBmtMQ7JrTG2xDo5BiHn+sydAdD6/I3S XgGLdaDg1ZPsT4peB56Qy1G8H2DlwGSmM+Drazfgvus+zyW8FaVNfIUbrydu1u2X 79U4BXQhjhDDIXwf+ipttksfEEhpMN1JxzrLO7l9pYYe13/VRR1NmkI7p3eN+GM= =n0UG -----END PGP MESSAGE----- fp: 00E0160999E3C663 unencrypted_suffix: _unencrypted version: 3.5.0

不难发现,加密后的文件内容与我们之前使用 sops 命令加密的文件内容在格式上完全一致,这也正说明了 SOPS 是 helm-secret 插件背后真正的 “幕后使者”。
加密后的 secrets.yaml 文件将被用于部署我们的 Chart,且该文件也可以被自由分发、存储到 Git 中去,因为我们只要确保 PGP 私钥不被泄漏,就无需担心该文件会被他人解密,从而导致敏感信息被泄漏的问题。
同样,helm-secrets 插件也提供了用于解密的 dec 子命令:
$ helm secrets dec secrets.yaml

且与 SOPS 一样,解密后的内容将被存储到新创建的 secrets.yaml.dec 文件中去。
你还可以使用 helm-secrets 插件提供的 view 子命令直接查看解密后的文件内容:
$ helm secrets view secrets.yamlpostgresqlDatabase: my-database postgresqlUsername: admin postgresqlPassword: admin

当生成好加密后的 secrets.yaml 文件后,就可以通过 helm-secrets 插件使用该文件进行部署工作了。
部署 PostgreSQL
helm-secrets 插件提供的 install 子命令用于部署 HELM Chart,而正如我们前面所讲那样,它仅仅是对 helm install 命令进行了一层封装操作,因此用法与 helm install 命令完全一致:
$ helm secrets install postgresql stable/postgresql -f secrets.yaml

当执行以上命令时, helm-secrets 插件首先会对 secrets.yaml 文件中所有 Key 值进行解密操作,再将解密后的 YAML 文件传递给 helm install 命令进行部署。
你可以通过执行命令 kubectl get secret --namespace default postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode 来查看刚刚部署的 PostgreSQL 实例的管理员密码信息,来验证密码是否我们之前设定的 admin。
Values 文件名 不知你是否已经注意到,在部署 PostgreSQL Chart 时,我们将所有自定义变量值全部保存到了一个名为 secrets.yaml 的文件中,而在通常情况下,我们都习惯于将这些自定义变量值保存到名为 values.yaml 的文件中去。
事实上,这是有意而为之的,因为 helm-secrets 插件仅仅会对 secrets.yaml 文件,以及任何以 secrets.为前缀名的 YAML 进行解密,例如:
$ helm secrets install XXXX -f values.yaml -f secrets.yaml -f secrets.env.yaml

当使用上面命令部署时,helm-secrets 插件仅仅会对 secrets.yamlsecrets.env.yaml 文件中的所有 Key 值进行解密操作,而保留 values.yaml 中的 Key 值不变。
另外需要切记的一点是,虽然 .yaml.yml 都可作为 YAML 类型文件的后缀来使用,但 helm-secret 只支持 .yaml 后缀,使用 .yml 作为后缀的文件将无法被解密。
在其它节点执行部署操作
到目前为止,从创建 PGP 密钥对,到对 secrets.yaml 文件的加密,在到部署 PostgreSQL 等等所有这一系列操作全部都在同一台机器上完成。但当团队内有其它成员需要与你一起开发和部署 Helm Chart,或者你希望可以在其它机器上做开发部署时,则你还需要了解如何导入与导出 PGP 密钥对。
公钥的导入与导出 通过前面对 PGP 的讲解我们了解到,公钥用于加密,私钥用于解密。因此,你若希望其他人或在其它工作机器上也有能够加密 Values 文件的能力,那么,你只需将你的 PGP 公钥导入到他的工作电脑上即可。
导入 PGP 公钥有两种方式:一种是手动导出导入公钥;另一种是上传你的公钥到公钥服务器中,其他人则可以直接从公钥服务器中导入你的公钥。下面就让我们分别看一下如何通过这两种方式导入与导出你的公钥。
手动导入导出公钥
首先将公钥导入到文件中:
$ gpg --export --armor "helm-secret@email.com" > helm.pub

该命令将公钥导出到了名为 helm.pub 的文件中,将导出的公钥传递给他人。
通过 import 命令导入到自己机器中即可:
$ gpg --import helm.pub

通过公钥服务器导入与导出公钥
为了便于导入他人公钥,世界上存在许多公钥服务器,专门用于存储公钥信息。任何人都可以上传自己的公钥到这些服务器上,以便他人下载使用。
上传公钥非常简单,仅需指定要使用的服务器,以及要上传的公钥 ID 即可:
$ gpg --keyserver keyserver.ubuntu.com --send-key 00E0160999E3C663

该命令会将我们的公钥 00E0160999E3C663 上传到 keyserver.ubuntu.com 服务器上。
一旦将公钥上传到某个服务器之后,就可以从该服务器导入公钥到本地电脑中:
$ gpg --keyserver keyserver.ubuntu.com --recv 00E0160999E3C663gpg --keyserver keyserver.ubuntu.com --recv 00E0160999E3C663 gpg: key 00E0160999E3C663: public key "HELM Secret (Used for HELM Secret Plugin) " imported gpg: Total number processed: 1 gpg:imported: 1

无论使用哪种导入方式,在导入完成后,你都应该可以通过 gpg --list-keys 命令查看到刚刚导入都公钥信息。
提示:导入公钥仅仅使你拥有了加密的能力,因此你无法在只导入了公钥的机器上使用 helm-secrets 进行解密或部署操作。
私钥的导入与导出 与加密流程类似,若你希望其他人或在其它工作机器上能够解密你的 Values 文件,那么你则需要将你的私钥导入到其它的工作机器上。私钥的导入与导出只能通过手动方式完成:
$ gpg --export-secret-key -a "helm-secret@email.com" > helm

我们首先使用 --export-secret-key 命令将私钥导入到了 helm 文件中,将该文件通过安全的方式传递给需要的人之后,使用下面命令再次导入即可:
$ gpg --import helmgpg: key 00E0160999E3C663: "HELM Secret (Used for HELM Secret Plugin) " not changed gpg: key 00E0160999E3C663: secret key imported gpg: Total number processed: 1 gpg:unchanged: 1 gpg:secret keys read: 1 gpg:secret keys imported: 1

当私钥导入成功后,即可通过 gpg --list-secret-keys 命令查看当前系统中的私钥信息。
导入私钥,就意味着当前所在机器拥有了解密的能力,同样也就意味着拥有了部署的能力。
提示:私钥用于解密操作,因此你可以在导入了私钥的机器上使用 helm-secrets 进行部署。但是,你若想修改 Values 文件并加密,同样需要确保你正确地导入了公钥。
再次提醒,拥有私钥就等于拥有了解密的能力,因此,一定要确保私钥的安全而不被泄密。
结束语 源码中泄漏用户名密码等敏感信息的事件频频发送,工具只是手段,最重要的是时刻保持警惕的头脑。
最后的最后,你可以通过依次执行以下命令进行清理操作:
# 删除 PostgreSQL 部署 $ helm delete postgresql# 删除 PGP 密钥对 $ gpg --delete-secret-key 00E0160999E3C663 $ gpg --delete-key 00E0160999E3C663# 删除所有 Values 文件 $ rm -rf secrets*.yaml*

来源:DevSecOps SIG
作者:张泽亮
声明:文章获得作者授权在IDCF社区公众号(devopshub)转发。优质内容共享给思否平台的技术同伴,如原作者有其他考虑请联系小编删除,致谢。
Helm 插件之 helm-secrets(利用 PGP 加密你的 Values 文件 | IDCF)
文章图片

【Helm 插件之 helm-secrets(利用 PGP 加密你的 Values 文件 | IDCF)】6月每周四晚8点,【冬哥有话说】开心一“夏”。公众号留言“开心”可获取地址
  • 0603 无敌哥 《IDCF人才成长地图与5P》(《端到端DevOps持续交付(5P)精品课》第1课)
  • 0610 冬哥 《带你玩转创新设计思维》
  • 0617 无敌哥 《敏捷项目管理到底是个啥》
  • 0624 冬哥 《VUCA时代的敏捷领导力》

    推荐阅读