关于 GitLab Stack Secrets Manager
用于管理 GitLab stack 项目密钥的安全技能,面向需要将密钥接入 Docker secrets 的维护者。它涵盖密钥创建、迁移、验证、审计、轮换与泄露检查,并要求密钥不放入 .env 或 docker-compose.yml。
主要功能
- 01创建和生成密钥文件
- 02将环境变量迁移到 Docker secrets
- 03检查权限、所有权和 Git 排除
- 04审计密钥使用与潜在泄露
- 05轮换或移除现有密钥
- 06按需生成入口脚本
适用场景
- 01将 .env 中的敏感值迁移出去
- 02验证 Docker secrets 配置
- 03排查仓库中的密钥泄露
- 04审计未使用或权限不当的密钥
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rknall/ claude-skills --skill gitlab-stack-secrets-manager安装后在 Claude Code 中输入/gitlab-stack-secrets-manager确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdmigration-guide.mdsecrets-patterns.md详细介绍
GitLab Stack Secrets Manager
此技能用于管理 GitLab 堆栈项目的机密,确保机密得到安全存储、绝不暴露在配置文件中,并正确集成 Docker secrets。
何时使用此技能
当用户请求以下操作时,启用此技能:
- 创建或管理 Docker secrets
- 将环境变量迁移到 Docker secrets
- 验证机密配置和权限
- 审计机密使用情况并检测泄漏
- 确保机密不在 .env 或 docker-compose.yml 中
- 检查机密是否暴露在 git 中
- 生成安全的随机机密
- 轮换现有机密
- 修复与机密相关的安全问题
核心安全原则
关键规则——绝不可违反:
- .env 中不得包含机密:.env 文件中绝不能包含机密
- docker-compose.yml 中不得包含机密:环境变量中不得包含明文机密
- ./secrets 目录:所有机密都存放在 ./secrets 中,权限设为 700
- 机密文件:单个文件的权限设为 600
- Git 保护:在 .gitignore 中添加 ./secrets/*,绝不提交
- 正确的所有权:所有文件归 Docker 用户所有(而非 root)
- 仅使用 Docker Secrets:只使用 Docker secrets 机制
机密管理工作流
阶段 1:了解用户意图
步骤 1:确定操作
思考用户想要执行什么操作:
- 创建新机密?
- 将现有环境变量迁移到机密?
- 验证当前机密配置?
- 审计机密是否泄漏或存在问题?
- 更新或轮换现有机密?
- 移除机密?
步骤 2:收集上下文
-
检查当前项目状态:
- ./secrets 目录是否存在?
- docker-compose.yml 是否存在?
- .env 文件是否存在?
- 这是否属于 stack-validator 的检查结果?
-
检查 docker-compose.yml:
- 是否已定义任何机密?
- 是否有看起来像机密的环境变量?
- 哪些服务需要机密?
-
扫描安全问题:
- .env 中是否有机密?
- docker-compose.yml 环境变量中是否有机密?
- git 是否在跟踪机密?
阶段 2:创建机密
适用场景:用户想要创建新机密
步骤 1:验证前置条件
- 检查 ./secrets 目录是否存在:
ls -ld ./secrets - 如果不存在,则创建目录并设置正确的权限:
mkdir -p ./secrets chmod 700 ./secrets
步骤 2:确定机密详情
询问用户(或根据上下文推断):
- 机密名称(例如,db_password、api_key)
- 生成方式:
- 用户提供值
- 生成随机值
- 根据模式生成
- 格式要求(字母数字、十六进制、base64 等)
- 长度要求
步骤 3:创建机密文件
- 生成或接收机密值
- 在 ./secrets 中创建文件:
echo -n "secret-value" > ./secrets/secret_name - 设置正确的权限:
chmod 600 ./secrets/secret_name - 验证所有权(不应归 root 所有)
步骤 4:更新 docker-compose.yml
-
添加到顶层 secrets 部分:
secrets: secret_name: file: ./secrets/secret_name -
添加到相应服务:
services: myservice: secrets: - secret_name
步骤 5:验证 .gitignore
确保 ./secrets 已被排除:
/secrets/
/secrets/*
!secrets/.gitkeep
阶段 3:密钥验证
时机:用户想要验证密钥配置,或将其作为其他操作的一部分
步骤 1:目录结构验证
-
检查 ./secrets 是否存在:
[ -d ./secrets ] && echo "exists" || echo "missing" -
检查权限(应为 700):
stat -c "%a" ./secrets # Linux stat -f "%OLp" ./secrets # macOS -
检查所有权(不能是 root):
ls -ld ./secrets
步骤 2:密钥文件验证
-
列出所有密钥文件:
find ./secrets -type f ! -name .gitkeep -
对每个文件,检查:
- 权限(应为 600)
- 所有权(不能是 root)
- 文件非空
- 文件可读
步骤 3:docker-compose.yml 验证
-
解析 secrets 部分:
- 列出所有已定义的密钥
- 确认每个密钥对应的文件都存在
-
检查服务对密钥的引用:
- 所有引用的密钥都已定义
- 服务使用
secrets:键,而不是环境变量
-
严重:扫描环境变量中是否包含密钥:
- 查找以下模式:PASSWORD、SECRET、KEY、TOKEN、API
- 标记任何疑似密钥的内容
- 这些内容必须迁移
步骤 4:.env 文件验证
-
严重:扫描 .env 中是否包含密钥:
- 模式匹配:PASSWORD、SECRET、KEY、TOKEN、API
- 外观类似随机字符串的长字符串
- Base64 编码的值
- 任何应属于密钥的值
-
如果在 .env 中发现密钥:
- 这是一个严重的安全问题
- 列出所有检测到的密钥
- 建议立即迁移
步骤 5:Git 安全检查
-
确认 .gitignore 排除了 ./secrets:
grep -q "secrets" .gitignore -
检查是否有密钥已暂存:
git status --porcelain | grep secrets/ -
检查 Git 历史记录中是否包含密钥(如有要求):
git log --all --full-history -- ./secrets/
步骤 6:生成验证报告
🔐 Secrets Validation Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📁 Directory Structure
✅ ./secrets exists with 700 permissions
✅ Owned by user (1000:1000)
✅ ./secrets in .gitignore
📄 Secret Files (3)
✅ db_password - 600 permissions, 32 bytes
✅ api_key - 600 permissions, 64 bytes
⚠️ jwt_secret - 644 permissions (should be 600)
🐳 Docker Integration
✅ 3 secrets defined in docker-compose.yml
✅ All secret files exist
⚠️ Service 'worker' uses docker-entrypoint.sh
❌ CRITICAL SECURITY ISSUES
❌ .env contains secrets:
* DB_PASSWORD=supersecret123
* API_KEY=sk_live_abc123
** IMMEDIATE ACTION REQUIRED **
❌ docker-compose.yml environment variables contain secrets:
* Service 'app' - JWT_SECRET in environment
** MUST MIGRATE TO DOCKER SECRETS **
✅ Git Safety
✅ No secrets in git staging
✅ .gitignore properly configured
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Status: FAILED (2 critical issues)
🔧 IMMEDIATE ACTIONS REQUIRED
1. Migrate secrets from .env to Docker secrets
2. Remove secrets from docker-compose.yml environment
3. Fix permissions on jwt_secret file
阶段 4:密钥迁移
时机:在 .env 或 docker-compose.yml 环境变量中发现密钥时
严重:这是必须修复的安全问题
步骤 1:识别要迁移的密钥
-
扫描 .env 中是否存在符合密钥模式的内容:
grep -E "(PASSWORD|SECRET|KEY|TOKEN|API)" .env -
扫描 docker-compose.yml 的环境变量部分:
# Look for patterns in environment variables -
列出所有检测到的密钥及其以下信息:
- 变量名
- 当前位置(.env 或 compose)
- 当前值(用于迁移)
- 建议的密钥名称
步骤 2:与用户确认
展示检查结果并询问:
- 哪些变量应该迁移?
- 确认密钥名称
- 确认从 .env/compose 中删除是安全的
步骤 3:创建密钥文件
对于每个要迁移的密钥:
- 提取当前值
- 创建密钥文件:
echo -n "$value" > ./secrets/secret_name chmod 600 ./secrets/secret_name - 将其添加到 docker-compose.yml 的 secrets 部分
步骤 4:更新服务配置
对于每个使用该密钥的服务:
- 将其添加到服务的 secrets 列表
- 从环境变量中删除
- 如果容器支持
_FILE后缀:environment: DB_PASSWORD_FILE: /run/secrets/db_password - 如果容器不支持原生 secrets:
- 创建或更新 docker-entrypoint.sh
- 记录此要求
步骤 5:清理
- 从 .env 中删除密钥:
- 删除对应行
- 或添加迁移说明注释掉这些行
- 从 docker-compose.yml 的环境变量中删除
- 确认 .env.example 中没有密钥值
步骤 6:验证
- 测试服务能否正常启动
- 验证服务能否访问密钥
- 确认 .env 或 compose 中不再包含密钥
- 运行验证以确认
阶段 5:密钥生成
时机:需要生成安全的随机密钥时
步骤 1:确定格式要求
常见格式:
- 字母数字:字母和数字(默认)
- 十六进制:十六进制字符(0-9、a-f)
- Base64:Base64 编码
- 数字:仅数字
- UUID:UUID v4 格式
步骤 2:确定长度
标准长度:
- 数据库密码:32-64 个字符
- API 密钥:32-64 个字符
- JWT 密钥:64 个字符(或 32 字节的 Base64)
- 会话密钥:32 个字符
- 加密密钥:32 字节(256 位)
步骤 3:生成密钥
使用密码学安全的方法:
# Alphanumeric (32 chars)
openssl rand -base64 32 | tr -d '/+=' | head -c 32
# Hex (64 chars)
openssl rand -hex 32
# Base64 (32 bytes)
openssl rand -base64 32
# UUID
uuidgen
# Custom (e.g., 16 alphanumeric)
LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 16
步骤 4:安全存储
- 写入文件(末尾不带换行符):
echo -n "$secret" > ./secrets/secret_name - 设置权限:
chmod 600 ./secrets/secret_name
阶段 6:密钥审计
适用时机:用户希望审计密钥的使用情况、查找泄露或检查安全性
步骤 1:盘点密钥
列出所有密钥及其详细信息:
- 名称
- 文件路径
- 文件大小
- 权限
- 所有者
- 创建日期(如果可用)
- 最后修改时间
步骤 2:分析使用情况
针对每个密钥:
- 检查是否在 docker-compose.yml 中定义
- 列出使用该密钥的服务
- 检查文件是否存在
- 验证该密钥是否实际在使用
步骤 3:查找未使用的密钥
- 已定义但未被任何服务使用的密钥
- 未在 docker-compose.yml 中列出的密钥文件
- 建议删除或添加文档说明
步骤 4:检测泄露
检查常见的泄露位置:
-
.env 文件(严重):
grep -E "(PASSWORD|SECRET|KEY|TOKEN)" .env -
docker-compose.yml 环境变量(严重):
- 扫描所有环境变量部分
- 标记任何密钥
-
配置文件:
grep -r "password\|secret\|key" ./config/ -
Git 历史记录:
git log -p --all -S "secret-pattern" -
Docker 日志:
- 检查近期日志中是否暴露密钥
步骤 5:审计权限
-
检查 ./secrets 中的所有文件:
find ./secrets -type f -not -perm 600 -
检查目录权限:
[ "$(stat -c '%a' ./secrets)" = "700" ] -
检查所有权:
find ./secrets -user root
步骤 6:生成审计报告
包括:
- 密钥总数
- 使用情况统计
- 发现的安全问题
- 建议
- 风险评估
阶段 7:生成 docker-entrypoint.sh
适用时机:容器不支持原生 Docker secrets
步骤 1:确定是否必要
检查容器是否支持 secrets:
- PostgreSQL、MySQL、MariaDB:支持
_FILE后缀 ✅ - Redis:支持原生密钥 ✅
- MongoDB:支持原生密钥 ✅
- 大多数现代容器:查阅文档
仅在以下情况下创建 entrypoint:
- 容器仅接受环境变量
- 不支持
_FILE后缀 - 不支持原生读取 /run/secrets/
步骤 2:确定所需密钥
列出需要加载的密钥:
- 密钥名称(位于 ./secrets/ 中)
- 环境变量名称
- 服务名称
步骤 3:生成入口脚本
#!/bin/bash
set -e
# Function to load secrets from docker secrets into environment
load_secret() {
local secret_name=$1
local env_var=$2
local secret_file="/run/secrets/${secret_name}"
if [ -f "$secret_file" ]; then
export "${env_var}=$(cat "$secret_file")"
echo "Loaded secret: $secret_name -> $env_var"
else
echo "ERROR: Secret file $secret_file not found!" >&2
exit 1
fi
}
# Load all required secrets
load_secret "db_password" "DB_PASSWORD"
load_secret "api_key" "API_KEY"
load_secret "jwt_secret" "JWT_SECRET"
# Execute the main command
exec "$@"
步骤 4:设置权限
chmod +x docker-entrypoint.sh
步骤 5:更新 docker-compose.yml
services:
myservice:
entrypoint: /docker-entrypoint.sh
command: ["original-command"]
volumes:
- ./docker-entrypoint.sh:/docker-entrypoint.sh:ro
secrets:
- db_password
- api_key
步骤 6:添加说明
添加注释,说明为何需要入口脚本:
# docker-entrypoint.sh required because this container
# doesn't support Docker secrets natively
沟通风格
管理密钥时:
- 以安全为先:在每个步骤中强调安全性
- 清楚说明风险:解释为何将密钥放在 .env/compose 中很危险
- 紧急处理严重问题:不要淡化安全问题
- 提供帮助:给出修复问题的确切命令
- 全面检查:检查所有可能的泄露位置
- 注重科普:解释 Docker secrets 为何更安全
- 绝不显示密钥值:用“[REDACTED]”代替
关键验证项
以下安全标准必须通过:
- ✅ .env 文件中没有密钥
- ✅ docker-compose.yml 环境变量中没有密钥
- ✅ ./secrets 目录存在且权限为 700
- ✅ 所有密钥文件的权限均为 600
- ✅ ./secrets/* 已添加到 .gitignore
- ✅ Git 中没有受跟踪的密钥
- ✅ 没有归 root 所有的密钥文件
- ✅ 所有引用的密钥均存在
- ✅ 仅在确有必要时使用 docker-entrypoint.sh
与配套技能集成
stack-validator
- stack-validator 调用此技能验证密钥
- 验证密钥是否遵循正确模式
- 检测 .env 和 compose 文件中的密钥
stack-creator
- 创建并正确配置 ./secrets 目录
- 生成 .gitkeep 文件
- 正确设置 .gitignore
- 创建初始密钥占位符
config-generator
- 确保配置中不包含密钥
- 正确引用密钥
- 仅对非密钥使用环境变量
重要说明
- 只读访问密钥:绝不向用户显示实际密钥值
- 安全优先:始终将安全性置于便利性之上
- 必须迁移:.env/compose 中的密钥必须迁移
- 不走捷径:始终遵循安全最佳实践
- 全面验证:检查权限、所有权和 Git 状态
- 配套技能协作:与其他技能无缝配合
示例工作流:完成密钥设置
User: "Set up secrets for my database"
1. Check current state
- ./secrets missing → create it
- docker-compose.yml has DB_PASSWORD in environment → CRITICAL ISSUE
2. Report findings:
"I found a critical security issue: DB_PASSWORD is in docker-compose.yml
environment variables. I'll migrate this to Docker secrets."
3. Migration:
- Extract password value
- Create ./secrets/db_password
- chmod 600 ./secrets/db_password
- Update docker-compose.yml secrets section
- Update postgres service to use secrets
- Remove from environment
4. Verification:
- Run validation
- Confirm no secrets in compose
- Check .gitignore
- Verify permissions
5. Report:
"✅ Database password now secured with Docker secrets
✅ Removed from docker-compose.yml environment
✅ File permissions set correctly
✅ Added to .gitignore"
此技能可确保安全地管理密钥,避免其暴露在配置文件或版本控制中。