【数据安全】SOPS综合指南:像一个有远见的人而不是一个在职人员一样管理你的秘密

视频号

微信公众号

知识星球

Chinese, Simplified

你听说过SOP吗?如果你已经处于需要与队友分享敏感信息的情况,这是为你准备的。

1.SOP简介

1.1什么是SOP?

首先,让我们切入正题,直接进入房间里的大象:什么是SOP?

SOPS,Secrets OPerationS的缩写,是一个开源的文本文件编辑器,可以自动加密/解密文件。

强调文本编辑器、加密和自动化。

通常,当您想要加密文本文件时,您可以执行以下操作:

  • 使用您喜爱的编辑器编写、编辑和操作文本数据,并将其另存为文件。
  • 使用加密/解密工具对整个文件进行加密。

当您需要读取加密文件时:

  • 首先,您需要使用加密/解密工具对文件进行解密。
  • 使用您选择的文本编辑器打开解密的文件(现在它是一个常规文本文件)。

这种“正常”过程的缺点是显而易见的:一个作业需要两个工具(一个编辑器和一个加密/解密工具)。

进入SOPS。

安装SOPS最简单的方法是通过brew:

brew install sops

对于其他操作系统用户,请参阅official GitHub repo of SOPS.

💡

注意:你绝对可以使用其他具有SOPS的文本编辑器。对于VSCode,您甚至有一个名为VSCode sop的扩展,它将使您能够使用简单的基于项目的配置自动解密/加密VSCode中的文件。请记住,此扩展仍处于早期开发阶段,可能包含错误。

即使你不想安装扩展,你仍然可以使用VSCode来编辑文件:将$EDITOR环境变量设置为code–wait(在你的~/.bashrc或~/.zshrc中),VSCode将在调用sops my-file.yaml时打开文件。

1.2它是如何工作的?

简言之,SOPS在一个包中提供加密/解密和文本编辑,工作流程完全自动化。这就是它的闪光点:

  • 当您写入文件时,SOPS首先使用您选择的指定加密方法对文件进行加密,然后再将其保存到磁盘。这是自动完成的,不需要任何人工干预。当然,如果你用SOPS以外的另一个文本编辑器打开文件,你就无法读取内容,因为它是加密的。
  • 当你用SOPS读取加密的文件时,它首先解密文件,打开它,并向你显示它。虽然这听起来像是两步走的工作,但SOPS会自动完成,所以对最终用户来说,这看起来只是一步。

1.3亮点:灵活性

SOPS支持各种加密方法,如:

  • GPG(如果你不知道它是什么,请继续阅读)
  • AWS KMS
  • GCP KMS
  • HashiCorp Vault
  • 等等

这使得管理和编辑敏感文件变得简单而灵活。

如果我想使用本地GPG键编辑文本文件,没有问题;如果我想编辑一个ENV文件,并希望它由HashiCorp Vault加密,SOPS也为我提供了帮助。我不必对您的所有文件使用单一的加密方法,因为SOPS是高度可定制的。

好吧,说得够多了;让我们试一试,亲身体验一下吧。

2. SOPS with PGP Keys

2.1 PGP与GPG

PGP,GPG,令人困惑。。。我知道,对吧?

简而言之,GPG是一个实现PGP的CLI工具:

  • PGP(Pretty Good Privacy)是一个加密程序,为数据通信提供加密隐私和身份验证。它可以用于对文本、电子邮件、文件、目录和整个磁盘分区进行签名、加密和解密,并提高电子邮件通信的安全性。
  • 另一方面,GPG代表GnuPG,它是OpenPGP标准RFC4880的免费实现(命令行工具)。GPG允许您对数据和通信进行加密和签名;它具有通用的密钥管理系统和用于各种公钥目录的访问模块。

现在我们已经解决了令人困惑的命名法,让我们使用GPG CLI工具创建一个PGP密钥;然后,我们可以测试SOPS是如何工作的。

2.2使用GPG创建PGP密钥

安装GnuPG最简单的方法是通过brew,macOS的软件包管理器:

brew install gnupg

如果您正在使用另一个操作系统,例如Linux,则可以使用相应的软件包管理器。最有可能的是,这将起作用:

sudo apt-get install gnupg

使用GnuPG,创建密钥非常简单,如下所示(请记住将您的名称作为key_name的值):

export KEY_NAME="Tiexin Guo"
export KEY_COMMENT="test key for sops"

gpg --batch --full-generate-key <<EOF
%no-protection
Key-Type: 1
Key-Length: 4096
Subkey-Type: 1
Subkey-Length: 4096
Expire-Date: 0
Name-Comment: ${KEY_COMMENT}
Name-Real: ${KEY_NAME}
EOF

现在,如果您运行gpg --list-keys,您将看到生成的密钥:

$ gpg --list-keys
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
/Users/tiexin/.gnupg/pubring.kbx
--------------------------------
pub   rsa4096 2022-09-15 [SCEA]
      A2B73FB4DA0891B38EECD35B47991CD146C9C4BC
uid           [ultimate] Tiexin Guo (test key for sops)
sub   rsa4096 2022-09-15 [SEA]

在输出的“pub”部分,您可以获得GPG密钥指纹。或者,您可以运行 gpg --list-secret-keys "${KEY_NAME}" 来获取它。

存储密钥指纹以备将来参考。

2.3 SOPS配置

我们需要一个简单的配置,让SOPS知道我们将使用之前生成的PGP密钥进行加密/解密。为此,请在$HOME目录下创建一个名为.sops.yaml的文件,其中包含以下内容:

creation_rules:
    - pgp: >-
        A2B73FB4DA0891B38EECD35B47991CD146C9C4BC

请记住替换在上一步中生成的密钥指纹。

好了,现在我们结束了。

2.4带文本文件的SOPS

运行以下命令创建一个名为a-text-file.txt的新文件:

cd 
sops a-text-file.txt

开始编辑内容(例如,我输入“hello world”),然后保存。

现在,如果我们尝试对文件进行cat操作,我们将无法获取内容:

$ cat a-text-file.txt
{
    "data": "ENC[AES256_GCM,data:U1j0eOC7URJZsNb+Iqs=,iv:4F3Bw1YOIE2xxdag+PbrMLGcqAjG48qVDeiu+xTfnro=,tag:2tX0jUssBYeI0IF7Lxmy+A==,type:str]",
    "sops": {
        "kms": null,
        "gcp_kms": null,
        "azure_kv": null,
        "hc_vault": null,
        "age": null,
        "lastmodified": "2022-09-15T04:38:19Z",
        "mac": "ENC[AES256_GCM,data:w1HJ/A7t0DxD1KObLeLQVzSWVrobIAF/lUg/8DRH9khba8/cDGVjhrkheki09uWDfHo4vb+odrPsBBW6vtRemqd4Y+HTAH37l8e9IltbH1eUzgoKyOh0uNULLnxbpDTnxykTOCychgiHmPS0ggpetagHLxi0jOLGFe4FxOfbCdY=,iv:qMOCu7AtT7HnnQn22L3VsJ7JY/Wb5C0RLEfdl8g5OG4=,tag:PAb7sKHQZB65TBPts71s2g==,type:str]",
        "pgp": [
            {
                "created_at": "2022-09-15T04:38:09Z",
                "enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAxuQA5jWgsG6AQ/9HE0Xk8zM/oLJOqx4SaxKFKNmncYvRWSdADlXC341qYUG\n353VeMIbfl1u8Mg3iZxoUvD4SrkAEl63DOunhATWTtY2phtjoVxpoFhxOnu170zw\nKawewc9qzzjcAG5Oq/EqZeo0ip81VdZdfk9h05rSvH7y1vJ8YLgt6/3t6ZYlLdKA\nOF5jkjEqSyY9iaSZiFxVarT2PLygaIeG3zp9+mWcUjIaR9dzGILXDfwhNooFYlMN\no8GoEoMZUQVLLb4oFmWvnP/dG92ksimxp9ba4L0YWcd+HUJNGIxx8a1w5njGduqI\nDI67rVH8t94CwD30WGJq6d4yeo99JkN/gx88GdgLzuNzdclrMVbtR2f+ifqW0+KX\nza0e/AMCaCFHOUVZ8OGPJPZbBAB11hS/cRb9+JA/+OVolB9eGu6YkGhhAPS2xYVD\n4WC6vaNBgRwbu0YUxEiMWng2KM2QVeZlnFDJzUN/WNDwnmP9vY3keOqLJAAkkNtp\nyGCzA2PG2LvrMEPxoFj1uEtR8vxVcs56vp9Q6JdtA1wh+w61Mt1mnFbY6/6fsFQK\nC40L0UpukNNGsl1rl6jvlJEUoyjqxG9eWPMX3VKyXIrwEFYcEQ2pvEnsTHLx9pZa\nfxN4oiEW7leMPYzS5bEbx2pUxSrp94Om6T1fVRtBhWBGb2QaWPZCYR2p2cQRW1zU\naAEJAhAV9CcPDhhrHpYn06QbJf4kvM1SNXT5vRkeeC/fxS7HkqM3ukNzHkgrUijz\nj5k9vB7prn+2fGkpNxYSLOOW0Zgn0INpEkaBoRpdcfvFeE+kVv+rmUL9jsPWJpOA\nygzUZnejMwOn\n=v3OP\n-----END PGP MESSAGE-----\n",
                "fp": "A2B73FB4DA0891B38EECD35B47991CD146C9C4BC"
            }
        ],
        "unencrypted_suffix": "_unencrypted",
        "version": "3.7.3"
    }
}

但根据产出,我们可以得出结论:

  • 整个文件都是加密的(请参阅上面输出的数据部分)。
  • 加密方法(GPG,密钥指纹)作为文件的一部分存储在同一个文件中。

要读取文件,请执行以下操作:

sops a-text-file.txt

我们找回了原来的内容!

请注意,在读取文件时,我们不需要指定使用哪种加密/解密方法来读取加密文件,因为当我们首先创建该文件时,加密/解密方式已经通过SOPS作为文件的一部分存储。

2.5结构化数据的SOPS

自动加密文本文件的全部内容是SOPS的一个显著优势,但如果文件包含结构化数据,例如:

  • YAML
  • JSON
  • *.ini
  • ENV

SOPS可以做得更好!

让我们试试:

sops a-yaml-file.yaml

我放了以下内容:

username: tiexin
password: test

如果我们用常规文本编辑器打开文件,比如说,我们将其编辑为cat:

$cat a-yaml-file.yaml

$ cat a-yaml-file.yaml
username: ENC[AES256_GCM,data:h/BVd2tf,iv:IjzYAQQErVeWhwIIuMMfq/pjFr9YJVDNSl6ceRPv+6Q=,tag:2+xJOR89rsOMIQMWHNSEqw==,type:str]
password: ENC[AES256_GCM,data:zaz1Jw==,iv:VZ81YN4FRQf14g4olKwb6A8W00BIFT/OgWSEqkrO29s=,tag:tRJHVU7ANvGSw0tOjqGKiQ==,type:str]

...(omitted)

似乎只有“值”是加密的,而不是“密钥”!

这是一个巨大的优势,因为如果我们用常规文本编辑器打开这个文件,我们仍然可以获得数据的结构,只是我们无法读取加密的内容。

我想你知道我为什么对这个功能感到兴奋,因为我刚刚想到了一个很棒的应用程序:加密Kubernetes机密YAML文件!加密后,我们仍然可以清楚地看到内容和密钥,但不能看到值,从而可以安全地将文件存储在某个地方并与他人共享。

值得一提的是,对于YAML文件,SOPS还加密注释,这是另一个很好的功能:敏感值字段可能在注释部分也有一些敏感的描述。

到目前为止,我们已经用标准文本文件和结构化文件演示了SOPS的基本功能。但是,我们已经使用PGP密钥完成了所有操作,它可能不太常见,不适合在生产环境中使用。接下来,让我们使用HashiCorp Vault和AWS KMS这两个最著名的秘密/密钥管理器来尝试SOPS。

3个带HashiCorp Vault的SOP

3.1 Vault简介

如果你不了解HashiCorp Vault,它的核心是一个秘密管理器,但它可以做更多的事情,包括加密管理。典型的用例包括机密管理、加密服务、密钥管理等。这是一个开源项目,您可以在自己的基础设施中运行;HashiCorp还提供基于云的服务。

3.2建立本地保险库进行测试

对于SOPS教程,我们将设置一个本地Vault服务进行测试,最快的方法是使用Docker:

docker run -d -p8200:8200 vault:1.2.0 server -dev -dev-root-token-id=toor

请注意,这只是为了设置本地开发Vault服务器;不要在生产环境中执行此操作。关于生产用途,请查看官方文档。

在Docker容器中本地运行Vault后,运行以下命令进行验证:

$ export VAULT_ADDR=http://127.0.0.1:8200
$ export VAULT_TOKEN=toor
$ vault status
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    1
Threshold       1
Version         1.2.0
Cluster Name    vault-cluster-618cc902
Cluster ID      e532e461-e8f0-1352-8a41-fc7c11096908
HA Enabled      false

Vault启动并运行后,让我们创建一个供SOPS使用的密钥:

$ # enable a transit engine if not already done
$ # It is suggested to create a transit engine specifically for SOPS
$ vault secrets enable -path=sops transit
Success! Enabled the transit secrets engine at: sops/
$ # create a key
$ vault write sops/keys/firstkey type=rsa-4096
Success! Data written to: sops/keys/firstkey

3.3使用带SOPS的保险箱钥匙

接下来,让我们使用在Vault中创建的密钥编辑文件:

sops --hc-vault-transit $VAULT_ADDR/v1/sops/keys/firstkey another-yaml-file.yaml

以YAML格式编写一些键/值对,然后保存。

如果我们用另一个文本编辑器(例如vim)打开文件,我们可以看到Vault相关信息也作为文件的一部分保存。因此,当我们需要阅读它时,我们只需运行:

sops another-yaml-file.yaml

就是这样:这个过程与使用PGP密钥完全相同。

SOPS在其配置文件中支持精细范围的规则,因此它知道根据这些用户定义的规则对每个文件使用什么加密方法和哪个密钥。

4带AWS KMS的SOP

4.1 KMS简介

AWS KMS(密钥管理服务)是一种基于云的服务,可帮助创建和控制加密密钥。与HashiCorp Vault类似,它可以创建、存储和使用加密密钥;不同的是,HashiCorp Vault也是一个机密管理器,而AWS有一个单独的服务(AWS机密管理器)用于轮换、管理和提供机密。

4.2创建AWS KMS密钥

对于这一部分,我们将使用AWS CLI。

如果你还没有安装,请按照这里的官方文档操作。安装完成后,我们需要在使用之前对其进行正确配置。

在这里,我们假设您的AWS CLI已经可以正常工作,并且具有访问AWS KMS所需的权限。

使用AWS CLI在AWS KMS中创建密钥非常简单:

aws kms create-key \
    --tags TagKey=Purpose,TagValue=Test \
    --description "Test key"

从输出中复制ARN,我们可以将其保存为ENV变量(用您自己的值替换ARN):

export ARN=arn:aws:kms:ap-southeast-1:858104165444:key/620abad4-8043-4166-8712-2b4684378d3a

4.3将AWS KMS的密钥与SOPS一起使用

同样简单明了:

sops --kms $ARN aws-kms-encryption-example.yaml

类似地,加密方法信息作为文件的一部分保存,使用SOPS读取文件不需要指定解密方法,就像使用GPG或Vault一样。

SOPS支持更多加密方法,如GCP KMS、Azure密钥库等。从SOPS的回购中了解更多!

5总结

5.1为什么需要SOP

在完成了整个教程并自己执行了许多命令之后,您一定有点累了。现在是放松的故事时间了:

几年前,我正在做一个与fin-tech相关的大型项目,整个基础设施的中心是一个OpenShift集群(可以把它想象成一个定制的Kubernetes)。

在集群中,我们使用名称空间来分隔不同的环境;我们使用OpenShift集群作为机密管理的唯一真相来源。

例如:如果我们需要更新机密的值,我们可以在OpenShift控制台中进行更新。如果我们需要在Jenkins中使用秘密,我们会在OpenShift中添加一个秘密,它会自动同步为Jenkins秘密。一切似乎都很好。

然而,如果我们想与另一个团队成员共享一个秘密,或者将该秘密迁移到另一个集群/环境中,这会很棘手:我们必须将秘密导出为K8s秘密YAML文件,然后共享该文件。

这既是一个安全问题,也是一个生产力问题:如果YAML被一个本不应该访问该秘密的人共享怎么办?如果OpenShift集群中的秘密发生了变化,但我们不知道,因为我们手头的YAML文件不可能自动与集群同步,该怎么办?

一般来说,使用K8s原生秘密作为唯一的真相来源并不是一种最佳实践,但从K8s环境之外的地方消费秘密并不简单。即使秘密只在集群中使用,您仍然需要创建硬编码的YAML副本:您将tho保存在哪里

5.2某些用例的替代方案

有两种类似的工具功能要差得多,但根据您的具体用例,它们可能同样有价值:

  • Git crypt实现了Git repo中文件的自动加密和解密。您选择保护的文件在提交时加密,在签出时解密。gitcrypt允许您自由共享包含公共和私有内容的混合存储库。如果你想在团队中分享秘密,这是一个很好的工具,但它只支持PGP密钥加密;你必须自己生成和管理那些PGP密钥。而且,如果你只想在不使用git的情况下自动进行一些加密/解密,那就没有意义了。
  • Ansible Vault对变量和文件进行加密,以保护密码或密钥等敏感内容,而不是将其作为明文显示在Ansible剧本或角色中。它的工作原理与SOPS类似,但显然,它只能在Ansible上下文中使用。当然,您也可以将SOPS与Ansible一起使用。

SOPS仍然是通用的王,尤其是如果你想对不同的文件使用不同的加密方法。

5.3 SOPS不是什么

需要明确的是:SOPS不是一个秘密管理者。是的,您可以将其作为一种快速而廉价的解决方案,将敏感数据存储在加密文件中。但是,随着用例的扩展,您很可能会碰壁。仅以文件格式保存机密有其局限性。例如,在某个时刻,您可能需要API访问您的秘密。SOPS并不是为这个而设计的,在它之上构建一个定制的解决方案充其量也只是笨拙的。

这正是秘密管理器(secrets managers )的用途:允许您灵活地处理所有秘密的格式、策略和访问方法(如文件、K8s本地YAML、应用程序、实际用户等)。现代秘密管理器与CLI、CI/CD系统、编排平台等有许多集成,因此很有可能在不加密文件的情况下满足您的所有需求。

最近,我在区块上发现并测试了一个新的孩子:Doppler,它可以自动将机密同步到K8s集群,从而无需将K8s机密存储在YAML文件中。它甚至可以在相关机密更新时重新启动pod。如果感兴趣,请在此处阅读更多信息。

本文地址
https://architect.pub
SEO Title
A Comprehensive Guide to SOPS: Managing Your Secrets Like A Visionary, Not a Functionary