通过上篇《四》的学习,大家已经已经可以通过Helm chart将自己的应用程序成功的部署到Kubernetes集群中了,有安全意识的同学肯定会很疑惑,这好像根本没有解决敏感数据的问题呀,我们传给Heml处理引擎的数据是明文的,打开文件values-kubernetes-secrets就能看到内容。事实的确如此,接下来我们要做就是如何解决在Helm中如何管理敏感数据的问题。
安全问题不是从有了Kubernetes后才出现的,也不是有了数字化转型的场景后才有的,业界已经形成了相对成熟的安全准则和规范,因此安全道路千万条,遵守规范第一条。Helm和Kubernetes社区也在上下求索,试图解决我们部署hello-demo这个应用时遇到的问题,如何管理配置文件中的敏感数据。
经过各种尝试之后,Helm最终提供了一个叫Helm Secrets的插件,用来提供缺失的敏感数据管理功能,读者需要注意的是,插件在Helm中属于外部扩展,但是我们任然可以使用Helm的客户端命令行管理工具来访问。
Helm Secret默认使用来自mozilla的SOPS秘钥管理工具,具体来说SOPS就是用来对键值对类型的文件进行加密,比如YAML文件,并且提供了和主流云平台上的KMS套件(以及云下独立部署的KMS套件)集成的功能。
为了将SOPS和Helm Secret集成起来,我们还必须使用PGP(Pretty Good Privacy),一种用来对邮件内容进行加密的公钥加密算法。PGG在对数据进行加密处理的时候,需要输入一个随机的256bit的秘钥,用来对键值对数据进行加密。如下图展示了使用PGP对敏感数据进行加密,以及在Kubernetes平台上通过helm安装应用的具体过程。
如上图所示,我们先通过SOPS和PGP来将YAML文件中的数据进行加密,因为敏感数据在配置管理仓库,开发人员的电脑上都是以密文形式存在,即便是通过邮件或者聊天工具分享给其他人,非法接收者无法通过YAML文件识别具体的敏感信息。
当我们将包含敏感资源的应用部署到Kubernetes的时候,解密的过程会首先将YAML文件的数据通过SOPS和PGP进行解密,解密后的Values和模板进行merge,形成部署资源后apply到Kubernetes集群中。
有了上边的这些内容铺垫之后,接下来我们来准备本地环境。由于我们在使用PGP的时候,需要一对秘钥(公钥和私钥,也叫公钥加密,可以参考笔者安全概述系列文章),而GPG(GNU Privacy Guard)这套实现开源标准PGP的工具可以解决我们的问题,具体来说我们可以使用gpg工具来管理秘钥。如果读者用的macOS,可以直接运行brew install gpg来安装工具到自己的机器上。
gpg工具安装完成后,就可以使用命令gpg --generate-key来创建秘钥(一对公钥和私钥),创建的过程中需要输入我们的姓名和邮箱地址,当提示需要数据passphrase的时候,直接回车就行,我们先忽略这个信息。
注:上边把passphrase置空的做法只是为了本地测试用,如果你是给生产环境创建秘钥,不建议这样做。另外本地留空也降低了和其他工具集成的复杂度,但是笔者要再次强调,这是不安全的做法。
当gpg运行返回后,我们就可以使用gpg --list-keys命令来罗列生成的秘钥,如下图所示:
➜ source_code gpg --list-keys
(删除若干信息....)
----------------------------------
pub ed25519 2021-09-17 [SC] [expires: 2023-09-17]
D2E67F8037119B027256CAED81E7B4364F72C141
uid [ultimate] qigaopan
sub cv25519 2021-09-17 [E] [expires: 2023-09-17]
从上面的输出中,大家需要注意的是以“D2E"开头的一串字符,这串字符是我们生成的公钥的指纹(fingerprint),我们稍后会用来这个公钥的指纹信息来配置SOPS。
接下来我们继续安装helm的插件,通过运行命令:helm plugin install https://github.com/jkroepke/helm-secrets 来安装Helm的插件以及SOPS组件,安装完成后,在自己的环境上通过helm plugin list来验证插件是否安装成功:
➜ kubernetes helm plugin list
NAME VERSION DESCRIPTION
secrets 3.8.3 This plugin provides secrets values encryption for Helm charts secure storing
环境准备好后,接下来我们来实战一下如何通过这些工具来确保在Helm的安装包中,如何确保敏感配置信息的安全。
Helm Secrets插件管理的隐私文件被统一放在叫helm_var的文件夹中,这个文件夹和Chart.yaml文件平级。我们在hello-demo应用的对应位置,创建这个叫helm_vars的文件夹,更新后的应用文件夹结构如下所示:
➜ hello-demo tree
.
├── Chart.yaml
├── helm_vars
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── ingress.yaml
│ ├── secret.yaml
│ ├── service.yaml
│ └── serviceaccount.yaml
└── values.yaml
接着我们需要将Helm Secret插件和SOPS进行集成,来对原始的敏感数据进行加密。在helm_vars文件夹中创建一个叫.sops.yaml的文件,并按如下格式把我们前文创建的公钥指纹信息配置进去:
---
creation_rules:
- pgp: "D2E67F8037119B027256CAED81E7B4364F72C141"
---
接下来我们将values-kubenetes-secrets.yaml配置文件移动到helm_vars文件夹中,这样我们的敏感信息数据文件就和.sops.yaml文件被保存在相同的目录。 数据准备完成后,我们就可以使用命令:helm secrets enc helm_vars/values-kubernetes-secrets.yaml来对敏感数据进行加密。命令成功后,我们的敏感数据配置文件的内容就发生了变化,如下图所示:
从上图可以看出我们的配置文件被分成两个区域:1,秘钥的信息被保存在文件中,并且被加密存储;2,SOPS先关的元数据信息被保存在YAML文件中,目的是为数据解密提供输入。
接下来我们首先通过helm secrets edit来编辑配置文件:helm secrets edit helm_vars/values-kubernetes-secrets.yaml,文件将以敏文打开,然后进行修改保存。
接下来我们使用命令:helm secrets upgrade greeting-demo . -i -f helm_vars/values-kubernetes-secrets.yaml来更新软件部署包,运行之后配置文件中的信息就被更新了,然后我们重新删除POD之后,就会发现可以获取到最新的应用配置了。
➜ hello-demo helm secrets upgrade hello-demo . -i -f helm_vars/values-kubernetes-secrets.yaml
[helm-secrets] Decrypt: helm_vars/values-kubernetes-secrets.yaml
Release "hello-demo" has been upgraded. Happy Helming!
NAME: hello-demo
LAST DEPLOYED: Fri Sep 17 11:38:38 2021
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
注:Revision:2代表更新到版本2,因此可以看到helm帮我们已经进行了版本管理,另外我们的敏感信息以加密的形式存在,安全性得到了极大的提高。
在非功能性需求中,安全可以说是一个特殊的存在,安全和性能不一样,在很多系统中有一票否决权,因此很多企业在应用的安全体系构建上可以说是煞费苦心。然而无论我们如何设计,如何加固系统,想达到100%的系统安全就想空中楼阁一样,看得到,但是摸不着。
因此做安全的准则第一条,100%的安全不现实,我们能做的就是最大化的降低安全的风险。有了这个基本共识,人们发明了很多中降低安全风险的原则和方法,其中定期更换秘钥是落地实践比较多的一个。回到我们的现实生活中,比如定期更换自己工作电脑的密码已经是基本的安全手段了,但是在系统中落地定期更换并不是那么简单,因为使用密码的是机器,因此我们必须有特殊的手段和机制。
我们先来介绍在Sealed Scret中如何定期更更换秘钥。如我们在上篇文章中的介绍,Sealed Secret controller在启动的时候,如果不存在秘钥对(一对私钥和公钥),就创建新的秘钥对。我们可以force controller定期创建新的秘钥对:kubectl -n kube-system set env deployment/sealed-secrets-controller SEALED_SECRETS_KEY_CUTOFF_TIME="$(date -R)",运行这个命令之后有会创建一个新的controller,以及新的秘钥对。
对于SOPS方案来说,Helm Secret底层的秘钥管理工具提供对秘钥定期更换的支持。我们可以使用SOPS工具提供的-r参数来更换秘钥,在自己的机器上运行sops -r --in-place helm_vars/values-kubernetes-secrets.yaml命令,然后我们打开更新后的yaml文件后,就会发现文件被更新了。
另外我们也可以定期更换GPG秘钥来预防信息泄露,具体做法是生成一个新的GPG秘钥,然后执行:sops -r --in-place --add-pgp
好了,这篇文章就到此为止了,下篇文章我们来介绍最让人激动人心的内容,如何确保Kubernetes中的数据安全,因为默认情况下,这些数据以base64的形式编码存在,属于掩耳盗铃这样的场景,敬请期待!