3ce31d3178
ci/woodpecker/push/woodpecker Pipeline failed
- 创建轻量级工具镜像(novalon/tools:1.0.0)避免重复安装工具 - 修复Docker TLS handshake timeout问题 - 更新CI配置使用registry.f.novalon.cn/novalon/tools:1.0.0 - 添加自动清理脚本用于磁盘和镜像管理
260 lines
7.4 KiB
Bash
260 lines
7.4 KiB
Bash
#!/bin/bash
|
||
|
||
# 生产环境安全配置验证脚本
|
||
# 作者:张翔
|
||
# 日期:2026-03-31
|
||
|
||
echo "🔍 开始执行安全配置验证..."
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
NC='\033[0m'
|
||
|
||
PROD_DIR="/home/novalon/docker-app"
|
||
NGINX_DIR="$PROD_DIR/novalon-nginx"
|
||
PASS_COUNT=0
|
||
FAIL_COUNT=0
|
||
|
||
# 检查函数
|
||
check_pass() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
((PASS_COUNT++))
|
||
}
|
||
|
||
check_fail() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
((FAIL_COUNT++))
|
||
}
|
||
|
||
check_warn() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "1. Nginx配置验证"
|
||
echo "=========================================="
|
||
|
||
# 检查nginx.conf是否存在
|
||
if [ -f "$NGINX_DIR/nginx.conf" ]; then
|
||
check_pass "Nginx配置文件存在"
|
||
|
||
# 检查安全头配置
|
||
if grep -q "X-Frame-Options" "$NGINX_DIR/nginx.conf"; then
|
||
check_pass "X-Frame-Options安全头已配置"
|
||
else
|
||
check_fail "X-Frame-Options安全头未配置"
|
||
fi
|
||
|
||
if grep -q "X-Content-Type-Options" "$NGINX_DIR/nginx.conf"; then
|
||
check_pass "X-Content-Type-Options安全头已配置"
|
||
else
|
||
check_fail "X-Content-Type-Options安全头未配置"
|
||
fi
|
||
|
||
if grep -q "Content-Security-Policy" "$NGINX_DIR/nginx.conf"; then
|
||
check_pass "Content-Security-Policy安全头已配置"
|
||
else
|
||
check_fail "Content-Security-Policy安全头未配置"
|
||
fi
|
||
|
||
if grep -q "Strict-Transport-Security" "$NGINX_DIR/nginx.conf"; then
|
||
check_pass "Strict-Transport-Security安全头已配置"
|
||
else
|
||
check_fail "Strict-Transport-Security安全头未配置"
|
||
fi
|
||
|
||
# 检查server_tokens
|
||
if grep -q "server_tokens off" "$NGINX_DIR/nginx.conf"; then
|
||
check_pass "Nginx版本号已隐藏"
|
||
else
|
||
check_fail "Nginx版本号未隐藏"
|
||
fi
|
||
|
||
# 检查SSL配置
|
||
if grep -q "ssl_certificate" "$NGINX_DIR/nginx.conf"; then
|
||
check_pass "SSL证书配置已存在"
|
||
else
|
||
check_fail "SSL证书配置缺失"
|
||
fi
|
||
|
||
# 检查DDoS防护
|
||
if grep -q "limit_req_zone" "$NGINX_DIR/nginx.conf"; then
|
||
check_pass "请求频率限制已配置"
|
||
else
|
||
check_fail "请求频率限制未配置"
|
||
fi
|
||
|
||
if grep -q "limit_conn_zone" "$NGINX_DIR/nginx.conf"; then
|
||
check_pass "连接数限制已配置"
|
||
else
|
||
check_fail "连接数限制未配置"
|
||
fi
|
||
else
|
||
check_fail "Nginx配置文件不存在"
|
||
fi
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "2. SSL配置验证"
|
||
echo "=========================================="
|
||
|
||
# 检查SSL目录
|
||
if [ -d "$NGINX_DIR/ssl" ]; then
|
||
check_pass "SSL目录存在"
|
||
|
||
# 检查证书文件
|
||
if [ -f "$NGINX_DIR/ssl/fullchain.pem" ] && [ -f "$NGINX_DIR/ssl/privkey.pem" ]; then
|
||
check_pass "SSL证书文件存在"
|
||
|
||
# 检查证书有效期
|
||
if command -v openssl &> /dev/null; then
|
||
EXPIRY=$(openssl x509 -in "$NGINX_DIR/ssl/fullchain.pem" -noout -enddate 2>/dev/null)
|
||
if [ -n "$EXPIRY" ]; then
|
||
check_pass "SSL证书有效:$EXPIRY"
|
||
else
|
||
check_fail "SSL证书无效或已过期"
|
||
fi
|
||
fi
|
||
else
|
||
check_fail "SSL证书文件缺失"
|
||
check_warn "请配置SSL证书以启用HTTPS"
|
||
fi
|
||
else
|
||
check_fail "SSL目录不存在"
|
||
fi
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "3. Docker配置验证"
|
||
echo "=========================================="
|
||
|
||
# 检查docker-compose.yml
|
||
if [ -f "$NGINX_DIR/docker-compose.yml" ]; then
|
||
check_pass "Docker Compose配置文件存在"
|
||
|
||
# 检查资源限制
|
||
if grep -q "deploy:" "$NGINX_DIR/docker-compose.yml"; then
|
||
check_pass "容器资源限制已配置"
|
||
else
|
||
check_fail "容器资源限制未配置"
|
||
fi
|
||
else
|
||
check_fail "Docker Compose配置文件不存在"
|
||
fi
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "4. 服务状态验证"
|
||
echo "=========================================="
|
||
|
||
# 检查Docker服务
|
||
if command -v docker &> /dev/null; then
|
||
check_pass "Docker已安装"
|
||
|
||
# 检查Nginx容器
|
||
if docker ps --filter "name=novalon-nginx" --format "{{.Names}}" | grep -q "novalon-nginx"; then
|
||
check_pass "Nginx容器运行中"
|
||
else
|
||
check_fail "Nginx容器未运行"
|
||
fi
|
||
|
||
# 检查应用容器
|
||
if docker ps --filter "name=novalon-website" --format "{{.Names}}" | grep -q "novalon-website"; then
|
||
check_pass "应用容器运行中"
|
||
else
|
||
check_fail "应用容器未运行"
|
||
fi
|
||
else
|
||
check_fail "Docker未安装"
|
||
fi
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "5. 端口配置验证"
|
||
echo "=========================================="
|
||
|
||
# 检查80端口
|
||
if command -v curl &> /dev/null; then
|
||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:80 2>/dev/null)
|
||
if [ "$HTTP_CODE" = "301" ]; then
|
||
check_pass "80端口HTTP重定向正常($HTTP_CODE)"
|
||
elif [ "$HTTP_CODE" = "200" ]; then
|
||
check_warn "80端口返回200,请确认是否需要重定向到HTTPS"
|
||
else
|
||
check_fail "80端口异常($HTTP_CODE)"
|
||
fi
|
||
|
||
# 检查443端口
|
||
HTTPS_CODE=$(curl -s -o /dev/null -w "%{http_code}" -k https://localhost:443 2>/dev/null)
|
||
if [ "$HTTPS_CODE" = "200" ]; then
|
||
check_pass "443端口HTTPS正常($HTTPS_CODE)"
|
||
elif [ "$HTTPS_CODE" = "301" ] || [ "$HTTPS_CODE" = "302" ]; then
|
||
check_pass "443端口HTTPS重定向正常($HTTPS_CODE)"
|
||
else
|
||
check_warn "443端口可能未配置($HTTPS_CODE)"
|
||
fi
|
||
else
|
||
check_fail "curl未安装,无法验证端口"
|
||
fi
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "6. 安全头验证"
|
||
echo "=========================================="
|
||
|
||
if command -v curl &> /dev/null; then
|
||
HEADERS=$(curl -I -k https://localhost:443 2>/dev/null)
|
||
|
||
if echo "$HEADERS" | grep -qi "x-frame-options"; then
|
||
check_pass "X-Frame-Options响应头存在"
|
||
else
|
||
check_fail "X-Frame-Options响应头缺失"
|
||
fi
|
||
|
||
if echo "$HEADERS" | grep -qi "x-content-type-options"; then
|
||
check_pass "X-Content-Type-Options响应头存在"
|
||
else
|
||
check_fail "X-Content-Type-Options响应头缺失"
|
||
fi
|
||
|
||
if echo "$HEADERS" | grep -qi "strict-transport-security"; then
|
||
check_pass "Strict-Transport-Security响应头存在"
|
||
else
|
||
check_fail "Strict-Transport-Security响应头缺失"
|
||
fi
|
||
|
||
if echo "$HEADERS" | grep -qi "content-security-policy"; then
|
||
check_pass "Content-Security-Policy响应头存在"
|
||
else
|
||
check_fail "Content-Security-Policy响应头缺失"
|
||
fi
|
||
else
|
||
check_fail "curl未安装,无法验证安全头"
|
||
fi
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "📊 验证结果汇总"
|
||
echo "=========================================="
|
||
echo ""
|
||
echo -e "${GREEN}通过:$PASS_COUNT${NC}"
|
||
echo -e "${RED}失败:$FAIL_COUNT${NC}"
|
||
echo ""
|
||
|
||
if [ $FAIL_COUNT -eq 0 ]; then
|
||
echo -e "${GREEN}✅ 所有安全配置验证通过!${NC}"
|
||
echo "您的生产环境安全配置符合最佳实践。"
|
||
else
|
||
echo -e "${RED}❌ 存在安全配置问题,请根据上述建议进行修复。${NC}"
|
||
fi
|
||
|
||
echo ""
|
||
echo "💡 建议:"
|
||
echo " 1. 确保SSL证书已配置并有效"
|
||
echo " 2. 定期更新Nginx和Docker"
|
||
echo " 3. 启用安全监控告警"
|
||
echo " 4. 定期进行安全审计"
|
||
echo "" |