这个想法源于我以前工作的地方处理应用程序秘密的方式。在我看来,这种管理方式很好,但需要一些改进。我将向你展示一个应用程序和一个工程师如何与应用程序的秘密互动。
正如我们现在所知道的,应用程序的秘密通常存在于应用程序的存储库中。它往往是一个.env 文件或纯文本形式的环境变量,由于明显的原因,这并不理想。在这个例子中,我们将受益于加密/解密,我将使用一个Golang应用程序。这比以前的方法更安全,因为入侵者必须窃取JSON文件、SSH文件、你的应用程序、找出相关环境变量的工作方式等等。要处理的事情太多,而且更难猜测。
优点
-
将应用程序的秘密保存在一个集中的服务中,有助于简化管理和维护。
-
应用程序变得无状态,并且没有配置文件。
-
秘密总是以加密的形式保存在我们的机器中。
-
不再有散落在应用程序库中的配置文件。
-
CI/CD管道不需要管理应用程序的秘密,因为当应用程序启动时,它将自己处理一切。
-
Docker镜像中不再有作为环境文件或数值的硬编码的秘密。
-
如果你需要引入更多的环境或新的键值对,可以轻松扩展。
-
每个环境的所有应用配置的结构/模式都完全相同。
它是如何工作的
用户将使用secret push ... 命令将新的秘密推送到远程存储,并使用secret pull ... 命令将秘密拉到本地环境。这里重要的一点是,拉取秘密只适用于local 环境,因为你不希望不断冲击远程服务,因为这将是缓慢的,而且成本高昂。然而,所有其他环境将只使用远程服务。
远程秘密存储是我们要存储秘密的地方。我们将使用AWS SSM服务,但它可以是任何其他服务,如Vault、Azure、GCP等。当用户提取秘密时,它们将被保存在本地机器的JSON文件中,使用SSH密钥来加密值。当应用程序运行时,该文件将被读取、解密并映射到结构中。
如前所述,"本地 "和 "其他 "环境的工作方式不同。本地 "是工程师在他们的PC上运行应用程序的地方,而 "其他 "是Kubernetes运行你的应用程序的地方(qa、staging、sandbox、prod...)。两者都有 "绿色 "和 "红色 "部分,如下所述。
本地
-
绿色--工程师使用
secret push ...命令将秘密推送到远程存储,并使用secret pull ...,将秘密拉到本地机器。**注意:**这些将几乎不被使用,因为我们并不总是与秘密互动。 -
红色--工程师运行应用程序,应用程序从本地文件系统中读取一次JSON秘密文件,并使用名为
secret的自定义结构标签映射到一个结构。
其他
结合绿色和红色,这只有一种工作方式,非常简单。当应用程序首次运行时,它会与远程存储对话,以提取机密文件并映射到结构中。
需要知道的事情
首先,我对一些数值进行了硬编码,使一些代码变得 "有主见",但你可以通过重构来改善它。原因是,我们在这里的重点不是要提供最漂亮的代码!而是要让你了解如何使用这些代码。它是关于给你一个如何处理秘密的想法。
-
当使用
push命令在终端输入时,出于安全原因,秘密值不会被打印到终端。 -
多行秘密值应作为单行值输入,使用
\n作为换行符。例如,SSH密钥。 -
目前,
push命令一次处理单个键值对。理想情况下,它应该处理多个。 -
本地存储的格式是:
User_Home_Directory/.Organisation_Name/secret/Service_Environment/Service_Name.json。例如:/Users/you/.inanzzz/secret/test/app.json
注意
如果你想让你的应用程序在本地环境下运行时总是从JSON文件中读取秘密,你可以修改secret.go 文件以摆脱意见代码。我建议你这样做,因为你不希望在本地环境下工作时依赖第三方服务。也许不适合生产秘密!
秘密存储库
├── aws
文件
aws.go
package aws
kms.go
package aws
crypto.go
package crypto
command.go
package secret
secret.go
package secret
主程序
package main
使用方法
运行$ go install github.com/you/secret@latest 命令,将二进制文件安装到你的机器上,这样你就可以在任何地方开始使用$ secret push/pull... 命令。
应用程序库
package main
如果你想在你的应用程序中简化使用,你可以在secret资源库中硬编码一些变量和依赖性。我把这个问题留给你,但你的最终代码将看起来像这样。
package main
测试
让我们假装我们正在处理 "prod "环境的秘密,而我们的应用程序被称为 "api"。
$ env | grep SERVICE_ENV
将秘密推送到AWS KMS。
// Value is 123123
验证它们的存在。
$ aws --profile localstack --endpoint-url http://localhost:4566 ssm get-parameters-by-path --path "/prod/api/"
鉴于我们的环境被设置为prod ,应用程序将运行,因为如前所述,只有 "本地 "环境从本地存储中读取。
api$ go run main.go
现在让我们把环境改为local ,然后运行应用程序。这将会失败。
api$ export SERVICE_ENV=local
为了使其工作,我们需要先推送秘密,然后拉出,再重试。我假设你已经推送了
$ secret pull --svc api
$ cat $HOME/.inanzzz/secret/local/api.json
api$ go run main.go