相当长一段时间以来,我一直在寻找一种简单的解决方案来加密配置文件中的密码/秘密(即 Web 应用程序的配置文件中的 mySQL 密码)。 当这些文件分散在工作站文件系统或(希望是私有的)git 存储库中时,这将大大提高实际安全性,其中通常仅以加密形式存在这些秘密就足够了。 完全解密的配置文件通常仅在部署应用程序的服务器上需要。
当然,有许多解决方案可以通过外部服务器或服务(Hashicorp Vault、AWS secrets Manager等)和特定于平台/工具的解决方案(Ansible、Kubernetes、gitlab、Docker(Swarm)等中的机密管理)来正确处理机密。但它们要么增加了依赖外部服务器/服务的复杂性,要么过于特定于域。
我最近偶然发现了Mozilla的sops工具。
“sops 是加密文件的编辑器,支持 YAML、JSON、ENV、INI 和 BINARY 格式,并使用 AWS KMS、GCP KMS、Azure Key Vault 和 PGP 进行加密.”
(sops on github)
所以它的目的是加密/解密配置文件中的敏感值。 虽然它似乎主要是为了与主要云提供商的密钥管理服务集成,但它也可以使用本地安装的 PGP 来完全运行。 因此,本地安装的 sops(这是一个用 Go 编写的独立命令行工具,编译为“只是”单个二进制文件)和 GnuPG 的组合确实可以实现使任何配置文件的行为有点像密码的密码容器的愿景 像keepass这样的管理器:你必须解锁它们才能以明文形式揭示其中包含的秘密。
使用sop的简单工作流程
让我们用sop设置一个最简单的工作流程,对配置文件中的特定机密值进行加密。
Here we have a yaml file with two sensitive keys in clear text: password
and pin
.
$ cat test.yaml username: jonathan.archer password: StarfleetAcademy2184 pin: 1234 description: my login to LCARS
Let’s try to encrypt/decrypt these fields with sops
.
- install gnupg (installers/packages for all relevant platforms are here)
- install the sops command line tool (it’s a single binary file, we can download it from the project’s github releases page and copy it to a
PATH
location, i.e./usr/local/bin
orc:\windows\system32
). - generate a pgp key pair (for this example with no passphrase and no expiration date):
$ gpg --batch --generate-key <<EOF %no-protection Key-Type: default Subkey-Type: default Name-Real: MyApp Config 1 Name-Email: myapp-config-1@mydomain.local Expire-Date: 0 EOF
3. find the public fingerprint for the newly generated key:
$ gpg --list-keys "myapp-config-1@mydomain.local" | grep pub -A 1 | grep -v pub68BC5F69E1F773157BA324C7ECF51418A7705AC9
4. now let’s use sops
to encrypt the sensitive fields in the yaml file:
$ sops --encrypt --in-place --encrypted-regex 'password|pin' --pgp 68BC5F69E1F773157BA324C7ECF51418A7705AC9 test.yaml
or alternatively in a bit more lazy way (without having to copy and paste the fingerprint):
$ sops --encrypt --in-place --encrypted-regex 'password|pin' --pgp `gpg --fingerprint "myapp-config-1@mydomain.local" | grep pub -A 1 | grep -v pub | sed s/\ //g` test.yaml
note: if we would leave out --encrypted-regex
(it’s optional), the values of all keys in the yaml file would get encrypted.
The yaml file now looks like:
$ cat test.yaml username: jonathan.archer password: ENC[AES256_GCM,data:PFzX2Q8mBsBfEDNJlgbTePYQcFM=,iv:FFls0uZktGsD4ueL1FFxXn6PnbqUpyJ5IkKn0FBtwbM=,tag:vIxYtwh/Vf09Omg0yOGRlA==,type:str] pin: ENC[AES256_GCM,data:LfljTQ==,iv:AtEKzJwO2SpZO4xA9KXEAmVuSOCkteSU5knc50SK7Uw=,tag:p9dZ7MMi+FyR72HQqmUKgg==,type:int] description: my login to LCARS sops: ...
To decrypt it to STDOUT (cat
-like) on the same machine/as the same user, we could run:
$ sops --decrypt test.yaml username: jonathan.archer password: StarfleetAcademy2184 pin: 1234 description: my login
As the private key is stored in the user’s keystore (in $HOME/.gnupg
) and doesn’t require a passphrase the decryption happens fully unattended. The decryption could therefore get incorporated in scripts (i.e. in an install script for our app).
5. Now what if we would need to be able to decrypt the secrets in the yaml file on another machine (i.e. to decrypt it on an app server as part of our app’s installation/upgrade procedure or on a CI runner for running tests)?
For this we could export the pgp private key from our current machine to the other machine.
On the current machine (workstation):
$ gpg --export -a "myapp-config-1@mydomain.local" > public.key $ gpg --export-secret-key -a "myapp-config-1@mydomain.local" > private.key
And on the new machine (server), under the relevant user:
gpg --import public.key gpg --allow-secret-key-import --import private.key
Now it should be possible to run sops --decrypt test.yaml
unattended on our server machine as well.
一个小小的免责声明
这个工作流程(我相信)使用和入门相对简单(因此很实用),同时比在配置文件中使用纯文本密码有了很大的改进。 但它可能存在某些缺陷。 因此,它可能适合也可能不适合特定用例的安全要求,并且可能有更好的选择(即使使用 sops,它具有更强大的功能)。 正如圣堂武士所说:你必须选择,但要明智地选择。
最新内容
- 8 hours ago
- 11 hours ago
- 11 hours ago
- 3 days ago
- 3 days 9 hours ago
- 3 days 10 hours ago
- 3 days 10 hours ago
- 3 days 10 hours ago
- 1 week ago
- 1 week ago