364 lines
9.6 KiB
Bash
364 lines
9.6 KiB
Bash
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
# ============================================================================
|
||
# 环境变量验证脚本
|
||
# 功能:验证所有必需的环境变量已正确配置
|
||
# ============================================================================
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
|
||
# 颜色输出
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# ============================================================================
|
||
# 日志函数
|
||
# ============================================================================
|
||
|
||
info() {
|
||
echo -e "${BLUE}ℹ️ ${NC}$*"
|
||
}
|
||
|
||
success() {
|
||
echo -e "${GREEN}✅ ${NC}$*"
|
||
}
|
||
|
||
warning() {
|
||
echo -e "${YELLOW}⚠️ ${NC}$*"
|
||
}
|
||
|
||
error() {
|
||
echo -e "${RED}❌ ${NC}$*"
|
||
}
|
||
|
||
# ============================================================================
|
||
# 环境变量验证
|
||
# ============================================================================
|
||
|
||
# 声明关键变量的关联数组
|
||
declare -A REQUIRED_VARS=(
|
||
["GITEA_RUNNER_TOKEN"]="Gitea Runner 令牌"
|
||
["GITEA__server__ROOT_URL"]="Gitea 根 URL"
|
||
["LITELLM_MASTER_KEY"]="LiteLLM 主密钥"
|
||
["MINIO_ROOT_USER"]="MinIO 访问密钥"
|
||
["MINIO_ROOT_PASSWORD"]="MinIO 秘密密钥"
|
||
)
|
||
|
||
declare -A OPTIONAL_VARS=(
|
||
["OPENAI_API_KEY"]="OpenAI API 密钥 (可选)"
|
||
["OPENROUTER_API_KEY"]="OpenRouter API 密钥 (可选)"
|
||
["LANGFUSE_EXTERNAL_URL"]="Langfuse URL (可选)"
|
||
)
|
||
|
||
# ============================================================================
|
||
# 验证文件是否存在
|
||
# ============================================================================
|
||
|
||
check_env_files() {
|
||
local found_files=false
|
||
|
||
info "检查环境配置文件..."
|
||
|
||
if [[ -f "${PROJECT_ROOT}/secrets/.env.core" ]]; then
|
||
success "找到: ${PROJECT_ROOT}/secrets/.env.core"
|
||
found_files=true
|
||
else
|
||
warning "缺失: ${PROJECT_ROOT}/secrets/.env.core"
|
||
fi
|
||
|
||
if [[ -f "${PROJECT_ROOT}/secrets/.env.ai" ]]; then
|
||
success "找到: ${PROJECT_ROOT}/secrets/.env.ai"
|
||
found_files=true
|
||
else
|
||
warning "缺失: ${PROJECT_ROOT}/secrets/.env.ai"
|
||
fi
|
||
|
||
if [[ "$found_files" == false ]]; then
|
||
error "未找到任何环境配置文件!"
|
||
return 1
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# ============================================================================
|
||
# 验证必需变量
|
||
# ============================================================================
|
||
|
||
check_required_vars() {
|
||
info "验证必需的环境变量..."
|
||
|
||
local missing_vars=()
|
||
local invalid_vars=()
|
||
|
||
# 加载环境文件
|
||
if [[ -f "${PROJECT_ROOT}/secrets/.env.core" ]]; then
|
||
# shellcheck source=/dev/null
|
||
set +u
|
||
source "${PROJECT_ROOT}/secrets/.env.core"
|
||
set -u
|
||
fi
|
||
|
||
if [[ -f "${PROJECT_ROOT}/secrets/.env.ai" ]]; then
|
||
# shellcheck source=/dev/null
|
||
set +u
|
||
source "${PROJECT_ROOT}/secrets/.env.ai"
|
||
set -u
|
||
fi
|
||
|
||
# 检查必需变量
|
||
for var in "${!REQUIRED_VARS[@]}"; do
|
||
local description="${REQUIRED_VARS[$var]}"
|
||
local value="${!var:-}"
|
||
|
||
if [[ -z "$value" ]]; then
|
||
missing_vars+=("$var: $description")
|
||
elif [[ "$value" == "REPLACE_ME"* ]] || [[ "$value" == "change_me"* ]] || [[ "$value" == "your_"* ]]; then
|
||
invalid_vars+=("$var: 需要配置实际的值 (当前: $value)")
|
||
else
|
||
success "$var: ✓ 已配置"
|
||
fi
|
||
done
|
||
|
||
# 检查可选变量
|
||
for var in "${!OPTIONAL_VARS[@]}"; do
|
||
local description="${OPTIONAL_VARS[$var]}"
|
||
local value="${!var:-}"
|
||
|
||
if [[ -z "$value" ]] || [[ "$value" == "your_"* ]]; then
|
||
warning "$var: 未配置 ($description)"
|
||
else
|
||
success "$var: ✓ 已配置"
|
||
fi
|
||
done
|
||
|
||
# 报告缺失的变量
|
||
if [[ ${#missing_vars[@]} -gt 0 ]]; then
|
||
error "缺失必需的环境变量:"
|
||
for item in "${missing_vars[@]}"; do
|
||
echo " • $item"
|
||
done
|
||
fi
|
||
|
||
# 报告无效的变量
|
||
if [[ ${#invalid_vars[@]} -gt 0 ]]; then
|
||
error "环境变量值无效:"
|
||
for item in "${invalid_vars[@]}"; do
|
||
echo " • $item"
|
||
done
|
||
fi
|
||
|
||
if [[ ${#missing_vars[@]} -gt 0 ]] || [[ ${#invalid_vars[@]} -gt 0 ]]; then
|
||
return 1
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# ============================================================================
|
||
# 验证 URL 格式
|
||
# ============================================================================
|
||
|
||
check_url_formats() {
|
||
info "验证 URL 格式..."
|
||
|
||
# 简单的 URL 格式验证
|
||
if [[ -f "${PROJECT_ROOT}/secrets/.env.core" ]]; then
|
||
# shellcheck source=/dev/null
|
||
set +u
|
||
source "${PROJECT_ROOT}/secrets/.env.core"
|
||
set -u
|
||
|
||
if [[ -n "${GITEA__server__ROOT_URL:-}" ]]; then
|
||
if [[ "${GITEA__server__ROOT_URL}" =~ ^https?:// ]]; then
|
||
success "Gitea ROOT_URL 格式正确: ${GITEA__server__ROOT_URL}"
|
||
else
|
||
error "Gitea ROOT_URL 格式错误 (需要以 http:// 或 https:// 开头)"
|
||
return 1
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# ============================================================================
|
||
# 验证密码强度
|
||
# ============================================================================
|
||
|
||
check_password_strength() {
|
||
info "检查密码强度..."
|
||
|
||
local weak_passwords=false
|
||
|
||
if [[ -f "${PROJECT_ROOT}/secrets/.env.ai" ]]; then
|
||
# shellcheck source=/dev/null
|
||
set +u
|
||
source "${PROJECT_ROOT}/secrets/.env.ai"
|
||
set -u
|
||
|
||
# 检查 MinIO 密码
|
||
if [[ -n "${MINIO_ROOT_PASSWORD:-}" ]]; then
|
||
if [[ ${#MINIO_ROOT_PASSWORD} -lt 8 ]]; then
|
||
warning "MinIO 密码过短 (当前: ${#MINIO_ROOT_PASSWORD} 字符,建议: 16+)"
|
||
weak_passwords=true
|
||
elif [[ "$MINIO_ROOT_PASSWORD" == *"minioadmin"* ]]; then
|
||
warning "MinIO 密码使用了默认值,建议更改"
|
||
weak_passwords=true
|
||
else
|
||
success "MinIO 密码强度: ✓ 良好"
|
||
fi
|
||
fi
|
||
|
||
# 检查 PostgreSQL 密码
|
||
if [[ -n "${POSTGRES_PASSWORD:-}" ]]; then
|
||
if [[ ${#POSTGRES_PASSWORD} -lt 8 ]]; then
|
||
warning "PostgreSQL 密码过短 (当前: ${#POSTGRES_PASSWORD} 字符,建议: 16+)"
|
||
weak_passwords=true
|
||
elif [[ "$POSTGRES_PASSWORD" == "langfuse" ]]; then
|
||
warning "PostgreSQL 密码使用了默认值,建议更改"
|
||
weak_passwords=true
|
||
else
|
||
success "PostgreSQL 密码强度: ✓ 良好"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
if [[ "$weak_passwords" == true ]]; then
|
||
warning "检测到弱密码,建议在生产环境中加强"
|
||
return 0 # 返回成功,但给出警告
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# ============================================================================
|
||
# 生成环境配置报告
|
||
# ============================================================================
|
||
|
||
generate_report() {
|
||
info "生成配置报告..."
|
||
|
||
local report_file="${PROJECT_ROOT}/ENV_VALIDATION_REPORT.md"
|
||
|
||
cat > "$report_file" << 'EOF'
|
||
# 环境配置验证报告
|
||
|
||
## 概述
|
||
|
||
本报告总结了 DevOps AI Stack 的环境配置验证结果。
|
||
|
||
## 检查项目
|
||
|
||
- [x] 环境文件存在性
|
||
- [x] 必需变量验证
|
||
- [x] 可选变量检查
|
||
- [x] URL 格式验证
|
||
- [x] 密码强度检查
|
||
|
||
## 配置文件位置
|
||
|
||
- 核心服务配置: `secrets/.env.core`
|
||
- AI 服务配置: `secrets/.env.ai`
|
||
|
||
## 建议
|
||
|
||
1. **生产环境部署**
|
||
- 更改所有默认密码为强密码 (最少16个字符)
|
||
- 生成新的密钥和令牌
|
||
- 启用 TLS 证书 (使用 Let's Encrypt)
|
||
- 配置备份和恢复策略
|
||
|
||
2. **安全加固**
|
||
- 启用网络隔离
|
||
- 配置认证和授权
|
||
- 启用审计日志
|
||
- 定期更新依赖项
|
||
|
||
3. **监控和告警**
|
||
- 配置 Prometheus 告警规则
|
||
- 设置日志收集和分析
|
||
- 配置性能基准
|
||
|
||
## 后续步骤
|
||
|
||
1. 审查并更新所有环境变量
|
||
2. 运行初始化脚本: `./infra/scripts/init-dev.sh`
|
||
3. 验证服务运行状态
|
||
4. 导入监控仪表板
|
||
5. 配置 CI/CD 流水线
|
||
|
||
---
|
||
生成时间: $(date)
|
||
EOF
|
||
|
||
success "配置报告已生成: $report_file"
|
||
}
|
||
|
||
# ============================================================================
|
||
# 主函数
|
||
# ============================================================================
|
||
|
||
main() {
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "🔍 环境配置验证工具"
|
||
echo "=========================================="
|
||
echo ""
|
||
|
||
local failed=false
|
||
|
||
if ! check_env_files; then
|
||
failed=true
|
||
fi
|
||
|
||
echo ""
|
||
|
||
if ! check_required_vars; then
|
||
failed=true
|
||
fi
|
||
|
||
echo ""
|
||
|
||
if ! check_url_formats; then
|
||
failed=true
|
||
fi
|
||
|
||
echo ""
|
||
|
||
if ! check_password_strength; then
|
||
failed=true
|
||
fi
|
||
|
||
echo ""
|
||
|
||
# 生成报告
|
||
generate_report
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
if [[ "$failed" == true ]]; then
|
||
error "验证失败!请修复上述问题后重试"
|
||
echo "=========================================="
|
||
return 1
|
||
else
|
||
success "✅ 所有验证通过!"
|
||
echo "=========================================="
|
||
echo ""
|
||
echo "💡 后续步骤:"
|
||
echo " 1. 启动服务: ./infra/scripts/init-dev.sh"
|
||
echo " 2. 查看报告: cat ENV_VALIDATION_REPORT.md"
|
||
echo " 3. 监控日志: tail -f logs/init-dev-*.log"
|
||
echo ""
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
main "$@"
|