欢迎光临
我们一直在努力

别把密码写在镜像里:详解 Secret 对象的加密存储与挂载使用安全规范

在容器化和微服务架构中,敏感数据(如数据库密码、API Key、TLS证书等)的管理是一个核心的安全挑战。将这些信息直接写入Dockerfile或容器镜像中是一种非常危险的做法,因为一旦镜像泄露,所有机密信息也将暴露无遗,且通过简单的docker history命令即可追溯。

Kubernetes提供了原生的解决方案:Secret对象。本文将详细介绍如何利用Secret安全地存储敏感数据,并将其以最小权限的方式挂载到Pod中。

1. 为什么不能把密码写在镜像里?

将密码写入镜像有以下主要风险:

  1. 层可见性: 容器镜像由多层构建而成。即使用户在后续层删除了密码文件,该文件在历史层中仍然存在,可通过工具提取。
  2. 源码暴露: 如果密码硬编码在源代码中,则代码仓库泄露直接导致密码泄露。
  3. 缺乏动态性: 更改密码需要重建和推送整个镜像,运维成本高且易出错。

2. 理解 Kubernetes Secret 对象

Secret对象专门用于存储敏感数据。它将数据存储在集群的Etcd数据库中,默认情况下,这些数据是Base64编码的,而不是加密的。注意:Base64编码并非加密,它只是一种传输编码,用于处理二进制数据。 真正的安全依赖于Etcd的访问控制和可选的Etcd静态加密。

2.1 创建 Secret:Base64编码

我们首先需要将数据转换为Base64格式(虽然kubectl工具可以代劳,但了解手动编码是重要的)。

假设我们要存储的用户名是 app_user,密码是 S3cureP@ssw0rd

# 编码用户名
echo -n 'app_user' | base64
# 输出: YXBwX3VzZXI=

# 编码密码
echo -n 'S3cureP@ssw0rd' | base64
# 输出: SzNjdXJlUEBzc3cwcmQ=

2.2 使用 YAML 定义 Secret

创建 db-secret.yaml 文件:

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  username: YXBwX3VzZXI=
  password: SzNjdXJlUEBzc3cwcmQ=

应用 Secret:

kubectl apply -f db-secret.yaml

# 快捷创建方式(不推荐在生产环境直接使用,因为命令历史可能暴露秘密)
# kubectl create secret generic db-credentials --from-literal=username=app_user --from-literal=password='S3cureP@ssw0rd'

3. 安全地将 Secret 挂载到 Pod 中

将 Secret 挂载到 Pod 的最安全方式是作为卷文件,而不是环境变量。环境变量容易通过简单的ps命令或者应用日志泄露。

当Secret作为卷挂载时,Kubernetes会在Pod的文件系统中创建一个tmpfs(内存文件系统)卷,将Secret的每个键/值对映射为一个文件。应用可以直接读取这些文件。

3.1 Pod 定义与 Secret 挂载

创建 secure-app-pod.yaml 文件:

apiVersion: v1
kind: Pod
metadata:
  name: secure-db-app
spec:
  containers:
  - name: my-db-client
    image: busybox:latest
    command: ["sh", "-c", "sleep 3600"]
    volumeMounts:
    # 将Secret挂载到 /mnt/secrets 目录下
    - name: db-secret-volume
      mountPath: "/mnt/secrets"
      readOnly: true # 确保容器无法修改密钥
  volumes:
  - name: db-secret-volume
    secret:
      secretName: db-credentials
      defaultMode: 0440 # 设定文件权限为只读,确保只有属主和属组可以访问

应用 Pod:

kubectl apply -f secure-app-pod.yaml

3.2 容器内验证与访问

进入运行中的 Pod 检查文件系统:

kubectl exec -it secure-db-app -- sh

# 查看挂载路径,注意权限是 0440
/ # ls -l /mnt/secrets
total 0
-r--r-----    1 root     root            16 Apr  1 12:00 password
-r--r-----    1 root     root             8 Apr  1 12:00 username

# 直接读取文件内容,Kubernetes已自动Base64解码
/ # cat /mnt/secrets/username
app_user
/ # cat /mnt/secrets/password
S3cureP@ssw0rd

4. 最佳实践总结

  1. 避免环境变量: 优先将 Secret 作为卷文件挂载,避免敏感信息出现在进程列表或日志中。
  2. 最小权限: 使用 readOnly: truedefaultMode 确保 Pod 对敏感文件只有读取权限,并限制权限为最低需求(如 0440)。
  3. Etcd 加密: 确保 Kubernetes 集群的 Etcd 存储启用了静态加密(Encryption at Rest),这是防止攻击者访问 Etcd 数据库后直接读取 Base64 数据的关键步骤。
  4. 使用外部 KMS/Secret Manager: 对于极高安全要求或多云环境,应考虑使用 HashiCorp Vault、AWS Secrets Manager 或 Azure Key Vault 等外部密钥管理系统,并结合 K8s CSI Secrets Store Driver 进行集成。
【本站文章皆为原创,未经允许不得转载】:汤不热吧 » 别把密码写在镜像里:详解 Secret 对象的加密存储与挂载使用安全规范
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址