# 🔒 安全方案文档 ## 概述 本项目实现了一套完整的敏感信息保护方案,确保密码、证书、Token 等敏感数据在存储和传输过程中的安全性。 ## 🎯 解决的安全问题 ### 1. 硬编码敏感信息 **问题**:代码中硬编码了 Harbor 密码、K8s 证书等敏感信息 **解决方案**:全部移至环境变量,通过 `.env` 文件配置 ### 2. 明文存储密码和证书 **问题**:数据库中以明文存储敏感数据 **解决方案**:使用 AES-256-GCM 加密存储 ### 3. API 响应泄露敏感信息 **问题**:API 返回完整的密码和证书数据 **解决方案**:自动脱敏,仅返回掩码(`••••••••`) ### 4. 前端显示敏感信息 **问题**:前端表单可能显示原始密码 **解决方案**:显示掩码,修改时仅支持覆盖 ## 🏗️ 架构设计 ``` ┌─────────────────────────────────────────────────────────────┐ │ 前端 (Frontend) │ │ • 显示脱敏数据(••••••••) │ │ • 修改时仅支持覆盖,不能查看原值 │ └─────────────────────────────────────────────────────────────┘ │ HTTPS ▼ ┌─────────────────────────────────────────────────────────────┐ │ REST API (Handler 层) │ │ • 接收请求中的明文敏感数据 │ │ • 响应时自动脱敏(调用 ToRegistryResponse/ToClusterResponse) │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Service 层(业务逻辑) │ │ • 处理业务逻辑 │ │ • 不关心加密/解密细节 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Repository 层(数据持久化) │ │ • Create/Update: 自动加密敏感数据后存储 │ │ • GetByID/List: 自动解密敏感数据后返回 │ │ • 使用 AES-256-GCM 加密算法 │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Database(加密存储) │ │ • 密码:加密存储(Base64 编码的密文) │ │ • 证书:加密存储(Base64 编码的密文) │ │ • Token:加密存储(Base64 编码的密文) │ └─────────────────────────────────────────────────────────────┘ ``` ## 🔐 加密实现 ### 加密算法 - **算法**:AES-256-GCM (Galois/Counter Mode) - **密钥长度**:256 bits (由用户提供的密钥通过 SHA256 派生) - **认证加密**:提供数据机密性和完整性 - **随机 Nonce**:每次加密使用随机 nonce,同样的明文产生不同的密文 ### 加密流程 ```go // 1. 用户配置加密密钥 encryptor := crypto.NewAESEncryptor(config.EncryptionKey) // 2. Repository 创建时注入加密器 clusterRepo := mock.NewClusterRepositoryMock(encryptor) registryRepo := mock.NewRegistryRepositoryMock(encryptor) // 3. 存储时自动加密 func (r *RegistryRepositoryMock) Create(ctx context.Context, registry *entity.Registry) error { encrypted := r.encryptRegistry(registry) // 加密敏感字段 r.registries[registry.ID] = encrypted return nil } // 4. 读取时自动解密 func (r *RegistryRepositoryMock) GetByID(ctx context.Context, id string) (*entity.Registry, error) { registry := r.registries[id] return r.decryptRegistry(registry), nil // 解密敏感字段 } ``` ### 加密的字段 #### Registry(镜像仓库) - ✅ `Password` - Harbor/镜像仓库密码 #### Cluster(Kubernetes 集群) - ✅ `CAData` - CA 证书 - ✅ `CertData` - 客户端证书 - ✅ `KeyData` - 客户端密钥 - ✅ `Token` - Bearer Token ## 🎭 脱敏显示 ### DTO 转换 ```go // Registry 响应 - 自动脱敏 func ToRegistryResponse(registry *entity.Registry) *RegistryResponse { response := &RegistryResponse{ Username: registry.Username, // 用户名不脱敏 Password: crypto.MaskSensitiveData(registry.Password), // 密码脱敏 HasPassword: registry.Password != "", } return response } // Cluster 响应 - 自动脱敏 func ToClusterResponse(cluster *entity.Cluster) *ClusterResponse { response := &ClusterResponse{ CAData: crypto.MaskSensitiveData(cluster.CAData), // •••••••• CertData: crypto.MaskSensitiveData(cluster.CertData), // •••••••• KeyData: crypto.MaskSensitiveData(cluster.KeyData), // •••••••• Token: crypto.MaskSensitiveData(cluster.Token), // •••••••• HasCAData: cluster.CAData != "", HasCertData: cluster.CertData != "", } return response } ``` ### API 响应示例 ```json { "id": "registry-123", "name": "Harbor Production", "url": "https://harbor.example.com", "username": "admin", "password": "••••••••", "has_password": true } ``` ## 🔧 配置指南 ### 1. 生成加密密钥 ```bash # 生成强加密密钥 openssl rand -base64 32 # 生成 JWT 密钥 openssl rand -base64 32 ``` ### 2. 创建 .env 文件 ```bash # 复制模板 cp backend/.env.example backend/.env # 编辑配置 nano backend/.env ``` ### 3. 必填配置项 ```bash # 生产环境必须修改这些配置! ENCRYPTION_KEY= JWT_SECRET= ``` ### 4. 可选:配置默认资源 ```bash # 默认用户 DEFAULT_USER_USERNAME=admin DEFAULT_USER_PASSWORD=your-secure-password DEFAULT_USER_EMAIL=admin@example.com # 默认集群 DEFAULT_CLUSTER_NAME=Production K8s DEFAULT_CLUSTER_HOST=https://k8s.example.com:6443 DEFAULT_CLUSTER_CA_DATA= DEFAULT_CLUSTER_CERT_DATA= DEFAULT_CLUSTER_KEY_DATA= # 默认镜像仓库 DEFAULT_REGISTRY_NAME=Harbor Production DEFAULT_REGISTRY_URL=https://harbor.example.com DEFAULT_REGISTRY_USERNAME=admin DEFAULT_REGISTRY_PASSWORD=your-harbor-password ``` ## 🚀 使用指南 ### 启动应用 ```bash cd backend # 开发模式(使用 Mock 存储) make run-mock # 生产模式(使用实际数据库) ADAPTER_MODE=prod DATABASE_URL="postgresql://..." make run-prod ``` ### 验证加密 ```bash # 1. 创建一个 Registry curl -X POST http://localhost:8080/api/v1/registries \ -H "Content-Type: application/json" \ -d '{ "name": "Test Registry", "url": "https://registry.example.com", "username": "admin", "password": "MySecretPassword123" }' # 2. 获取 Registry(密码已脱敏) curl http://localhost:8080/api/v1/registries/ # 响应示例: # { # "password": "••••••••", // 已脱敏 # "has_password": true # } ``` ## 📝 前端集成 ### 显示脱敏数据 ```typescript // Registry 表单 setPassword(e.target.value)} /> // 说明文字 {registry.has_password && (

当前已设置密码(加密存储)。输入新密码以覆盖。

)} ``` ### 修改策略 - **查看时**:显示掩码 `••••••••`,不显示实际值 - **修改时**: - 输入新值 → 覆盖原值 - 留空 → 保持原值不变 - 无法查看原值 ## 🔒 安全最佳实践 ### ✅ DO(应该做) 1. **生产环境必须使用强密钥** ```bash ENCRYPTION_KEY=$(openssl rand -base64 32) JWT_SECRET=$(openssl rand -base64 32) ``` 2. **妥善保管 .env 文件** - 不要提交到 Git(已加入 `.gitignore`) - 使用密钥管理服务(如 AWS Secrets Manager, HashiCorp Vault) - 定期轮换密钥 3. **使用 HTTPS** - 生产环境必须启用 TLS/SSL - 使用有效的 SSL 证书 4. **定期审计** - 定期检查访问日志 - 监控异常访问 ### ❌ DON'T(不应该做) 1. ❌ 不要在代码中硬编码敏感信息 2. ❌ 不要将 `.env` 文件提交到版本控制 3. ❌ 不要在日志中打印敏感数据 4. ❌ 不要在前端缓存敏感信息 5. ❌ 不要使用默认密钥用于生产环境 ## 🧪 测试 ### 加密/解密测试 ```bash cd backend go test ./internal/pkg/crypto -v ``` ### 集成测试 ```bash # 运行所有测试 make test # 测试加密存储 go test ./internal/adapter/output/persistence/mock -v ``` ## 📊 性能考虑 - **加密开销**:AES-GCM 加密非常快,对性能影响可忽略 - **内存使用**:每次读取时解密,不在内存中缓存明文 - **并发安全**:Repository 使用 RWMutex 保护并发访问 ## 🆘 故障排查 ### 问题:解密失败 **原因**:`ENCRYPTION_KEY` 发生变化 **解决方案**: 1. 确保使用相同的加密密钥 2. 如果密钥丢失,需要重新创建所有敏感数据 ### 问题:API 返回空密码 **原因**:密码未设置或解密失败 **解决方案**: 1. 检查 `has_password` 字段 2. 查看后端日志确认是否有解密错误 ## 📚 相关文档 - [AES-GCM 加密算法](https://en.wikipedia.org/wiki/Galois/Counter_Mode) - [Go crypto 包文档](https://pkg.go.dev/crypto) - [OWASP 安全编码实践](https://owasp.org/www-project-secure-coding-practices-quick-reference-guide/) ## 🤝 贡献 如果发现安全问题,请: 1. 不要公开披露 2. 通过私密渠道联系维护者 3. 提供详细的复现步骤 ## 📄 许可证 本项目的安全方案遵循项目主许可证。