使用 MinIO 和 HashiCorp Vault 简化密钥管理

Secrets Made Easy with MinIO and HashiCorp Vault

企业需要安全措施来保护系统,主要关注静态数据和传输中的数据。一个可行的安全计划包含许多方面,这篇博文重点介绍加密密钥管理。加密和相关的密钥是保障数据安全的关键。例如,网站需要在客户端和服务器之间进行证书握手(在本例中,为浏览器和 Web/应用程序服务器)。在后端,管理多种环境和多语言架构中的众多微服务需要有效地管理凭据。存储在对象存储解决方案中的数据可能需要满足合规性要求并受到保护,每个对象都需要加密和存储,并在需要时解密。出于这些原因,基础设施和安全团队需要一个可靠的密钥保管解决方案。

产品/应用程序需要加密数据:产品/应用程序无需在其实现中加入复杂的加密逻辑,可以直接依赖 HashiCorp 的 Vault 来提供此功能。Vault 专注于数据的签名和验证,而不是存储数据。将 MinIO 等应用程序与 Vault 结合使用,可以确保满足静态数据安全要求。

保护数据库和 Web 服务凭据:使用多语言数据库和与多个 Web 服务或微服务集成的微服务架构已成为常态。此外,始终存在多个环境。使用基础设施即代码和自动化,管理凭据和访问密钥变得至关重要,因此需要一个高性能的密钥管理和存储解决方案,例如 Vault 和 KES。

传输中数据的证书:无论是从浏览器访问的网站,还是应用程序与数据库之间的通信,从应用程序到 Web 服务或微服务之间的通信,每个通信通道都必须进行加密。Vault 可以生成 PKI 证书,用于保护这些通道中传输的数据的安全。

为了提供围绕安全锁定和擦除的监管合规性功能,MinIO 对对象进行加密,在存储层使用服务器端加密 (SSE) 来保护写入操作期间的对象。MinIO 以极高的效率执行此操作——基准测试表明,MinIO 能够以接近线速的速度进行加密/解密。

MinIO 如何实现这种级别的效率和性能?

MinIO 使用的秘诀是单指令多数据 (SIMD)。通常,您一次只能发送一条 CPU 指令,并在收到响应后再发送下一条指令。这效率非常低下,尤其是在每秒执行数千甚至数百万条加密和解密指令时。MinIO 利用 SIMD,因此它可以在单个请求中发送多条指令,由 CPU 处理。我们使用 GoLang 中的汇编语言编写了此功能,因此我们尽可能接近硬件层,以充分利用通常未被充分利用的 CPU 能力,从而大规模执行加密操作。

HashiCorp 的 Vault 与 MinIO 共享许多相同的思维过程和设计理念,从而产生了既强大又易于使用的互补软件。例如,Vault 几乎可以在任何环境中运行。它是云无关的,这意味着它可以在 AWS、GCP、Azure 甚至裸机上运行。Vault 只是一个单一的二进制文件,因此非常易于启动和运行。如果您在笔记本电脑上进行开发,可以在开发模式下运行它,当您准备好迁移到生产环境时,可以将其扩展到多个节点以形成集群。

Vault 也非常通用,有多种用例。其中一个用例是管理 LUKS(Linux 统一密钥设置)的密钥,LUKS 通常将密钥存储在执行加密和解密操作的同一卷上。显然,这是一个巨大的安全隐患,因为密钥与数据一起存储。相反,我们可以在启动时查询 Vault 服务以获取 LUKS 执行加密操作所需的密钥。这样,即使数据受到损害,密钥也不会位于卷上,因此无法解密数据,除非利用 Vault 本身。

MinIO 的密钥加密服务 (KES) 将所有这些整合在一起。SSE 使用 KES 和 Vault 执行加密操作。KES 服务本身是无状态的,充当中间层,因为它将其数据存储在 Vault 中。使用 MinIO,您可以设置各种粒度和可自定义的加密级别。您可以始终选择对每个对象进行加密,但是我们**强烈**建议在存储桶上自动设置 SSE-KMS 加密,以便所有对象默认情况下都进行加密。加密是使用存储在 Vault 中的特定外部密钥 (EK) 完成的,可以在每个对象的依据上使用唯一密钥进行覆盖。

在这篇博文中,我们将向您展示如何快速使用 MinIO、KES 和 Vault 入门,以充分了解服务器端加密的功能。

设置基础设施

首先,在您的笔记本电脑或云端启动一个 Linux 虚拟机,以便我们在其中安装这些组件。SSH 登录到此虚拟机,并确保您以 root 用户或使用 sudo 执行所有操作。在本博文中,我们使用的是一个普通的 Ubuntu 虚拟机。

MinIO

我们将设置此配置以启动一个单节点单驱动器设置,以便我们更好地理解这些概念。您可以轻松地将本教程扩展到分布式设置。

下载并将 MinIO 二进制文件移动到可执行位置

# wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20221126224332.0.0_amd64.deb -O minio.deb

# dpkg -i minio.deb

安装 MinIO 客户端

# wget https://dl.min.io/client/mc/release/linux-amd64/mc
# chmod +x mc
# mv mc /usr/local/bin/mc

将软件包安装到虚拟机后,请勿立即启动 MinIO 服务。在启动它之前,我们需要设置几个额外的先决条件。

KES

KES 作为其自身的独立服务运行,是 MinIO 和 Vault 服务之间的中介。

在虚拟机上设置以下目录,以添加我们生成的证书。

# mkdir -p /opt/kes/certs
# mkdir -p /opt/kes/config
# mkdir -p /opt/minio/certs
# mkdir -p /opt/minio/config
# mkdir -p ~/minio

从 MinIO KES 仓库获取 KES 二进制文件

# wget https://github.com/minio/kes/releases/download/v0.22.1/kes-linux-amd64

更改 KES 二进制文件的权限并将其移动到 PATH 可执行位置

# chmod +x kes-linux-amd64
# mv kes-linux-amd64 /usr/local/bin/kes

# kes --version

再次强调,请勿立即启动 KES 服务器,在我们启动它之前,我们还需要配置一些内容。

Vault

KES 需要 Vault 运行并解除密封才能与其通信。

让我们按照以下步骤安装 Vault

打开一个新的 tmux 会话以运行 Vault 操作

# tmux new -s vault

安装 GPG 软件包以添加 apt 密钥

# apt update && apt install gpg

获取 Hashicorp apt 仓库密钥

# wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg >/dev/null

验证指纹

# gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint

添加 Hashicorp apt 仓库,以便我们可以安装 Vault 软件包

# echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list

最后但并非最不重要的是,安装 Vault 本身

# apt update && apt install vault

启动 Vault 服务器,它也会为我们解除密封

# vault server -dev

Vault 启动后,请记下 Vault 端点和 Vault 根令牌。稍后您需要这些值在 Vault 中执行操作。

$ export VAULT_ADDR='http://127.0.0.1:8200'

[TRUNCATED]

Root Token: hvs.rCFo4tdgIdiq5NTRo6VzbBGz

使用以下按键结束 tmux 会话

CTRL+B,然后按 D

配置基础设施


设置好基础设施后,我们需要配置各个组件

Vault

在 Vault TMUX 会话之外,设置以下环境变量

VAULT_ADDR

VAULT_TOKEN

这些值可以在 Vault 服务启动时的早期输出中找到。

# export VAULT_ADDR='http://127.0.0.1:8200'

# export VAULT_TOKEN="hvs.rCFo4tdgIdiq5NTRjrVzbBGz"

创建一个名为 kv/ 的 Vault 密钥引擎路径

# vault secrets enable -path=kv kv

Success! Enabled the kv secrets engine at: kv/

启用 Vault 应用程序角色以支持 KES。这用于 KES 通过分配必要的权限和检索 KES 的应用程序 ID 和密钥来对 Vault 应用程序进行身份验证。

# vault auth enable approle

Success! Enabled approle auth method at: approle/

创建一个名为 kes-policy.hcl 的文件,其中包含以下内容,以便为我们之前创建的 kv/ 引擎提供必要的访问权限。

path "kv/data/*" {
capabilities = [ "create", "read"]
}

path "kv/metadata/*" {
capabilities = [ "list", "delete"]
}

应用上述文件在 Vault 中创建策略

# vault policy write kes-policy kes-policy.hcl

Success! Uploaded policy: kes-policy

创建一个名为 kes-role 的应用程序角色,并为其分配我们在上一步中创建的策略

# vault write    auth/approle/role/kes-role token_num_uses=0 secret_id_num_uses=0 period=5m
Success! Data written to: auth/approle/role/kes-role

# vault write    auth/approle/role/kes-role policies=kes-policy
Success! Data written to: auth/approle/role/kes-role

KES

为 KES 创建 TLS 证书,以确保 KES 与 Vault 部署之间的通信安全

# kes identity new kes_server \
--key  /opt/kes/certs/kes-server.key  \
--cert /opt/kes/certs/kes-server.cert  \
--ip   "127.0.0.1"  \
--dns  localhost

接下来,我们将为 MinIO 设置 TLS 证书,以执行对 KES 的 mTLS 身份验证

# kes identity new minio_server \
--key  /opt/minio/certs/minio-kes.key  \
--cert /opt/minio/certs/minio-kes.cert  \
--ip   "127.0.0.1"  \
--dns  localhost

使用以下内容创建 KES 配置文件 /opt/kes/config/kes-config.yaml。我们将解释如何获取必要的信息以填写配置。

address: 0.0.0.0:7373

admin:
  identity: disabled

tls:
  key:  /opt/kes/certs/kes-server.key
  cert: /opt/kes/certs/kes-server.cert

policy:
  minio:
    allow:
    - /v1/key/create/*   
    - /v1/key/generate/* # e.g. '/minio-'
    - /v1/key/decrypt/*
    identities:
    - MINIO_IDENTITY_HASH
keystore:
  vault:
    endpoint: http://localhost:8200
    engine: "kv/" # Replace with the path to the K/V Engine
    version: "v2" # Specify v1 or v2 depending on the version of the K/V Engine
    approle:
      id: "VAULTAPPID"     # Hashicorp Vault AppRole ID
      secret: "VAULTAPPSECRET" # Hashicorp Vault AppRole Secret ID
      retry: 15s
    status:
      ping: 10s

以下是获取必要信息的方法。

使用以下命令获取 MINIO_IDENTITY_HASH

# kes identity of /opt/minio/certs/minio-kes.cert

使用以下命令获取 VAULTAPPIDVAULTAPPSECRET

我们输出中的密钥看起来像这样

# vault read     auth/approle/role/kes-role/role-id

Key        Value
---        -----
role_id    6924d20f-31b3-xxxx-6182-5fce1fd52d37

# vault write -f auth/approle/role/kes-role/secret-id

Key                   Value
---                   -----
secret_id             0d6d8576-6a74-8f7f-xxx-785a5ec6fb3d
secret_id_accessor    16442cd9-8ba6-e730-042a-6ff756f2947f
secret_id_num_uses    0
secret_id_ttl         0s

MinIO

最后但并非最不重要的是,配置 MinIO

/opt/minio/config/minio 中添加以下配置

MINIO_KMS_KES_ENDPOINT=https://localhost:7373
MINIO_KMS_KES_CERT_FILE=/opt/minio/certs/minio-kes.cert
MINIO_KMS_KES_KEY_FILE=/opt/minio/certs/minio-kes.key

MINIO_KMS_KES_CAPATH=/opt/kes/certs/kes-server.cert

MINIO_KMS_KES_KEY_NAME=minio-backend-default-key

打开一个新的 tmux 会话以启动 KES 服务

# tmux new -s kes

使用我们之前创建的 kes-config.yaml 文件启动 KES 服务

# setcap cap_ipc_lock=+ep $(readlink -f $(which kes))

# kes server --auth=off --config=/opt/kes/config/kes-config.yaml

使用以下按键从 tmux 会话中分离

CTRL+B,然后按 D

现在我们已经有了 KES 所需的所有其他服务,让我们启动 MinIO 服务。

打开一个新的 tmux 会话,使用我们之前创建的配置文件启动 MinIO 服务

# tmux new -s minio
# export MINIO_CONFIG_ENV_FILE=/opt/minio/config/minio
# minio server ~/minio --console-address :9001

MinIO 启动后,使用以下按键从 tmux 会话中分离

CTRL+B,然后按 D

测试 MinIO、KES 和 Vault

此时,您应该拥有使 SSE 正常运行所需的组件。让我们做个好网民,对它进行测试。

生成一个新的加密存储桶密钥

# export KES_SERVER=https://127.0.0.1:7373
# export KES_CLIENT_KEY=/opt/minio/certs/minio-kes.key
# export KES_CLIENT_CERT=/opt/minio/certs/minio-kes.cert

# kes key create -k encrypted-bucket-key

在 MinIO 中创建一个存储桶,并默认情况下为添加到存储桶的每个对象启用自动加密。

# mc alias set local http://127.0.0.1:9000 minioadmin minioadmin

# mc mb local/encryptedbucket

Bucket created successfully `local/encryptedbucket`.

# mc encrypt set SSE-KMS encrypted-bucket-key local/encryptedbucket

Auto encryption configuration has been set successfully for local/encryptedbucket

使用 cp 将对象添加到存储桶

# mc cp file.txt local/encryptedbucket/file.txt

/root/file.txt:  5 B / 5 B ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 161 B/s 0s

最后,压轴戏。验证我们刚刚添加的对象是否已加密。我们可以使用 stat 命令来完成此操作。

# mc stat local/encryptedbucket/file.txt

Name      : file.txt
Date      : 2022-11-28 19:30:05 UTC
Size      : 5 B
ETag      : add93d98cf5931d7642118efded8aa20
Type      : file
Metadata  :
Content-Type: text/plain
Encrypted :
X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id: arn:aws:kms:encrypted-bucket-key
X-Amz-Server-Side-Encryption               : aws:kms

您还可以通过列出kv/引擎中的所有 Vault 密钥来进行验证。

# vault kv list kv/data

Keys
----
encrypted-bucket-key
minio-backend-default-key

如果您看到类似于上述的输出,则表示您已成功配置 SSE。是不是很简单?现在您知道为什么以及如何在 MinIO 中加密存储的数据了。

总结

这篇博文重点介绍了服务器端加密 (SSE)、密钥加密服务 (KES) 和密钥管理系统 (KMS,使用 Vault)。我们向您展示了使用 SSE 入门有多简单,以及加密带来的好处远远超过设置额外组件所需的工作量 (LOE)。您现在可以“左移”,并在开发和规划过程中尽早实施安全最佳实践;安全和数据保护永远不应该被视为事后才考虑的事情。通过关注 SSE 及其易用性和易理解性,我们希望您能够将其作为所有 MinIO 部署的标准。

您刚刚完成的是 MinIO-KES-Vault 的入门介绍。为了将您的学习环境发展为生产环境,您必须确保遵循 TLS 最佳实践,方法是使用来自受信任 CA(例如 LetsEncrypt)的有效证书。使用不同的证书来保护 MinIO -> KES 和 KES -> Vault 之间的通信安全。类似于 MinIO 在 多服务器多驱动器 设置中的配置,KES 也应该在多个节点上使用 此处说明 进行设置。Vault 也适用相同原则,您应该使用行业最佳实践来设置一个生产分布式设置,该设置不与 MinIO 基础架构的其余部分位于同一节点上,因为 Vault 也可能与其他服务一起使用。

我们希望您发现这篇教程博文对理解这个重要主题很有帮助。像往常一样,如果您有任何问题,请随时在 Slack 上联系我们!