fix: complete test suite fixes - achieve 99.8% pass rate
- Add missing lucide-react icons (Users, Target, MessageCircle, Layers, CreditCard) - Fix admin/page.test.tsx ESLint errors (add displayName) - Fix api/contact/route.test.ts ESLint errors (remove any types, use import) - Add RESEND_API_KEY environment variable for API tests - All 122 test suites now passing - Test pass rate: 99.8% (1499/1502 passed, 3 skipped)
This commit is contained in:
@@ -0,0 +1,590 @@
|
||||
# Jenkins安全加固完整指南
|
||||
|
||||
**作者:** 张翔
|
||||
**日期:** 2026-04-07
|
||||
**版本:** 1.0
|
||||
**风险等级:** 🔴 严重
|
||||
|
||||
---
|
||||
|
||||
## 📋 目录
|
||||
|
||||
1. [风险概述](#风险概述)
|
||||
2. [快速响应](#快速响应)
|
||||
3. [详细加固步骤](#详细加固步骤)
|
||||
4. [验证检查清单](#验证检查清单)
|
||||
5. [应急响应流程](#应急响应流程)
|
||||
6. [长期维护建议](#长期维护建议)
|
||||
|
||||
---
|
||||
|
||||
## 🚨 风险概述
|
||||
|
||||
### 当前风险
|
||||
|
||||
| 风险项 | 严重程度 | 影响 | 状态 |
|
||||
|--------|----------|------|------|
|
||||
| Jenkins暴露在公网8080端口 | 🔴 严重 | 勒索攻击、数据加密 | 待修复 |
|
||||
| Webhook Token硬编码 | 🔴 严重 | 供应链攻击 | 待修复 |
|
||||
| 缺少访问认证 | 🔴 严重 | 未授权访问 | 待修复 |
|
||||
| 无网络隔离 | 🟡 高危 | 直接攻击 | 待修复 |
|
||||
| 缺少审计日志 | 🟡 高危 | 无法追溯 | 待修复 |
|
||||
|
||||
### 攻击场景
|
||||
|
||||
1. **勒索软件攻击**
|
||||
- 黑客利用Jenkins已知漏洞(如CVE-2024-XXXX)
|
||||
- 加密Jenkins主目录和构建产物
|
||||
- 勒索赎金
|
||||
|
||||
2. **供应链攻击**
|
||||
- 利用暴露的Webhook Token
|
||||
- 恶意触发构建
|
||||
- 注入恶意代码到生产环境
|
||||
|
||||
3. **凭证泄露**
|
||||
- 获取Jenkins存储的密钥
|
||||
- 访问生产服务器、数据库
|
||||
- 全面接管系统
|
||||
|
||||
---
|
||||
|
||||
## ⚡ 快速响应
|
||||
|
||||
### 立即执行(15分钟内)
|
||||
|
||||
```bash
|
||||
# 1. 检查Jenkins是否已被攻击
|
||||
sudo journalctl -u jenkins --since "1 hour ago" | grep -i "failed\|error\|attack"
|
||||
|
||||
# 2. 临时阻止外部访问8080端口
|
||||
sudo ufw deny 8080/tcp
|
||||
# 或
|
||||
sudo firewall-cmd --permanent --remove-port=8080/tcp
|
||||
sudo firewall-cmd --reload
|
||||
|
||||
# 3. 检查是否有可疑进程
|
||||
ps aux | grep -E "jenkins|java" | grep -v grep
|
||||
|
||||
# 4. 备份当前配置
|
||||
sudo tar -czf /tmp/jenkins-emergency-backup-$(date +%Y%m%d_%H%M%S).tar.gz \
|
||||
/var/lib/jenkins /etc/default/jenkins
|
||||
|
||||
# 5. 修改Jenkins监听地址(临时)
|
||||
sudo sed -i 's|httpPort=8080|httpPort=8080 --httpListenAddress=127.0.0.1|' \
|
||||
/etc/default/jenkins
|
||||
sudo systemctl restart jenkins
|
||||
```
|
||||
|
||||
### 1小时内执行
|
||||
|
||||
```bash
|
||||
# 运行完整的安全加固脚本
|
||||
cd /path/to/novalon-website/scripts/security
|
||||
chmod +x jenkins-security-hardening.sh
|
||||
sudo ./jenkins-security-hardening.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 详细加固步骤
|
||||
|
||||
### 步骤1:网络层隔离
|
||||
|
||||
#### 1.1 修改Jenkins监听地址
|
||||
|
||||
**目标:** Jenkins仅监听127.0.0.1,外部无法直接访问
|
||||
|
||||
**操作:**
|
||||
|
||||
```bash
|
||||
# Debian/Ubuntu
|
||||
sudo vim /etc/default/jenkins
|
||||
|
||||
# 添加或修改以下行
|
||||
JENKINS_ARGS="--httpListenAddress=127.0.0.1 --httpPort=8080"
|
||||
|
||||
# RHEL/CentOS
|
||||
sudo vim /etc/sysconfig/jenkins
|
||||
|
||||
# 修改
|
||||
JENKINS_LISTEN_ADDRESS="127.0.0.1"
|
||||
```
|
||||
|
||||
**验证:**
|
||||
|
||||
```bash
|
||||
# 检查监听地址
|
||||
sudo netstat -tlnp | grep 8080
|
||||
# 应显示:127.0.0.1:8080
|
||||
|
||||
# 尝试外部访问(应失败)
|
||||
curl -I http://YOUR_SERVER_IP:8080
|
||||
# 应返回:Connection refused
|
||||
```
|
||||
|
||||
#### 1.2 配置防火墙
|
||||
|
||||
**UFW (Ubuntu/Debian):**
|
||||
|
||||
```bash
|
||||
sudo ufw --force enable
|
||||
sudo ufw default deny incoming
|
||||
sudo ufw default allow outgoing
|
||||
sudo ufw allow 22/tcp comment 'SSH'
|
||||
sudo ufw allow 80/tcp comment 'HTTP'
|
||||
sudo ufw allow 443/tcp comment 'HTTPS'
|
||||
sudo ufw deny 8080/tcp comment 'Jenkins Direct Access'
|
||||
sudo ufw --force reload
|
||||
```
|
||||
|
||||
**Firewalld (RHEL/CentOS):**
|
||||
|
||||
```bash
|
||||
sudo systemctl start firewalld
|
||||
sudo systemctl enable firewalld
|
||||
sudo firewall-cmd --permanent --add-service=ssh
|
||||
sudo firewall-cmd --permanent --add-service=http
|
||||
sudo firewall-cmd --permanent --add-service=https
|
||||
sudo firewall-cmd --permanent --remove-port=8080/tcp
|
||||
sudo firewall-cmd --reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 步骤2:应用层防护
|
||||
|
||||
#### 2.1 配置Nginx反向代理
|
||||
|
||||
**创建配置文件:**
|
||||
|
||||
```bash
|
||||
sudo vim /etc/nginx/conf.d/jenkins-security.conf
|
||||
```
|
||||
|
||||
**配置内容:**(见脚本生成的配置)
|
||||
|
||||
**关键安全配置:**
|
||||
|
||||
```nginx
|
||||
# 频率限制
|
||||
limit_req_zone $binary_remote_addr zone=jenkins_limit:10m rate=10r/m;
|
||||
|
||||
# 安全响应头
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
|
||||
# 客户端限制
|
||||
client_max_body_size 100m;
|
||||
client_body_timeout 60s;
|
||||
```
|
||||
|
||||
#### 2.2 配置HTTP Basic Auth
|
||||
|
||||
```bash
|
||||
# 生成密码文件
|
||||
sudo htpasswd -c /etc/nginx/conf.d/.jenkins-htpasswd admin
|
||||
|
||||
# 或使用openssl
|
||||
sudo openssl passwd -apr1 YOUR_PASSWORD | \
|
||||
sed "s|^|admin:|" | \
|
||||
sudo tee /etc/nginx/conf.d/.jenkins-htpasswd
|
||||
|
||||
# 设置权限
|
||||
sudo chmod 600 /etc/nginx/conf.d/.jenkins-htpasswd
|
||||
sudo chown www-data:www-data /etc/nginx/conf.d/.jenkins-htpasswd
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 步骤3:认证授权层
|
||||
|
||||
#### 3.1 配置Jenkins安全设置
|
||||
|
||||
**禁用匿名访问:**
|
||||
|
||||
```bash
|
||||
# 方法1:通过Jenkins UI
|
||||
# 访问:https://your-domain.com/jenkins/configureSecurity
|
||||
# 设置:授权策略 -> 安全矩阵 -> 取消匿名用户的所有权限
|
||||
|
||||
# 方法2:通过配置文件
|
||||
sudo vim /var/lib/jenkins/config.xml
|
||||
```
|
||||
|
||||
```xml
|
||||
<useSecurity>true</useSecurity>
|
||||
<authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy">
|
||||
<denyAnonymousReadAccess>true</denyAnonymousReadAccess>
|
||||
</authorizationStrategy>
|
||||
```
|
||||
|
||||
#### 3.2 Webhook签名验证
|
||||
|
||||
**Gitea Webhook配置:**
|
||||
|
||||
1. 进入Gitea仓库设置 -> Webhooks
|
||||
2. 添加Webhook:
|
||||
- 目标URL:`https://your-domain.com/generic-webhook-trigger/invoke`
|
||||
- HTTP方法:POST
|
||||
- 触发条件:Push events
|
||||
- **启用签名验证**
|
||||
- 签名密钥:使用生成的`WEBHOOK_SECRET`
|
||||
|
||||
**Nginx验证配置:**
|
||||
|
||||
```nginx
|
||||
location ~ ^/generic-webhook-trigger(/.*)?$ {
|
||||
# IP白名单
|
||||
allow YOUR_GITEA_SERVER_IP;
|
||||
deny all;
|
||||
|
||||
# 验证签名头
|
||||
if ($http_x_gitea_signature = "") {
|
||||
return 403;
|
||||
}
|
||||
|
||||
proxy_pass http://jenkins_backend;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 步骤4:审计监控层
|
||||
|
||||
#### 4.1 配置审计日志
|
||||
|
||||
**Nginx日志格式:**
|
||||
|
||||
```nginx
|
||||
log_format jenkins_security '$remote_addr - $remote_user [$time_local] '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent" '
|
||||
'request_time=$request_time '
|
||||
'ssl_protocol=$ssl_protocol';
|
||||
|
||||
access_log /var/log/nginx/jenkins-access.log jenkins_security;
|
||||
```
|
||||
|
||||
#### 4.2 日志轮转
|
||||
|
||||
```bash
|
||||
sudo vim /etc/logrotate.d/jenkins-security
|
||||
```
|
||||
|
||||
```
|
||||
/var/log/nginx/jenkins-*.log {
|
||||
daily
|
||||
rotate 90
|
||||
compress
|
||||
delaycompress
|
||||
missingok
|
||||
notifempty
|
||||
create 0640 www-data adm
|
||||
sharedscripts
|
||||
postrotate
|
||||
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
|
||||
endscript
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.3 监控脚本
|
||||
|
||||
```bash
|
||||
# 创建监控脚本
|
||||
sudo vim /usr/local/bin/monitor-jenkins-security.sh
|
||||
```
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 监控异常访问
|
||||
|
||||
# 检查失败的认证尝试
|
||||
FAILED_AUTH=$(grep "401" /var/log/nginx/jenkins-access.log | \
|
||||
tail -n 100 | \
|
||||
awk '{print $1}' | \
|
||||
sort | uniq -c | \
|
||||
awk '$1 > 10 {print $2}')
|
||||
|
||||
if [ -n "$FAILED_AUTH" ]; then
|
||||
echo "警告:检测到多次认证失败的IP:"
|
||||
echo "$FAILED_AUTH"
|
||||
# 可以添加自动封禁逻辑
|
||||
fi
|
||||
|
||||
# 检查异常请求
|
||||
grep -E "POST|DELETE|PUT" /var/log/nginx/jenkins-access.log | \
|
||||
tail -n 100 | \
|
||||
grep -v "200\|201" | \
|
||||
awk '{print $1, $7, $9}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 验证检查清单
|
||||
|
||||
### 自动验证
|
||||
|
||||
```bash
|
||||
# 运行验证脚本
|
||||
sudo /usr/local/bin/verify-jenkins-security.sh
|
||||
```
|
||||
|
||||
### 手动验证清单
|
||||
|
||||
- [ ] **网络层**
|
||||
- [ ] Jenkins仅监听127.0.0.1:8080
|
||||
- [ ] 防火墙已阻止8080端口
|
||||
- [ ] 仅允许Nginx代理访问
|
||||
|
||||
- [ ] **应用层**
|
||||
- [ ] Nginx配置语法正确
|
||||
- [ ] HTTPS强制重定向
|
||||
- [ ] 安全响应头已配置
|
||||
- [ ] 频率限制生效
|
||||
|
||||
- [ ] **认证层**
|
||||
- [ ] HTTP Basic Auth已启用
|
||||
- [ ] 匿名访问已禁用
|
||||
- [ ] Webhook签名验证已启用
|
||||
- [ ] IP白名单已配置
|
||||
|
||||
- [ ] **审计层**
|
||||
- [ ] 访问日志正常记录
|
||||
- [ ] 日志轮转已配置
|
||||
- [ ] 监控脚本运行正常
|
||||
|
||||
- [ ] **配置安全**
|
||||
- [ ] Jenkinsfile中无硬编码token
|
||||
- [ ] 敏感信息已移至环境变量
|
||||
- [ ] Jenkins Credentials已配置
|
||||
|
||||
### 渗透测试
|
||||
|
||||
```bash
|
||||
# 1. 尝试直接访问Jenkins(应失败)
|
||||
curl -I http://YOUR_SERVER_IP:8080
|
||||
|
||||
# 2. 尝试匿名访问(应返回401)
|
||||
curl -I https://your-domain.com/jenkins/
|
||||
|
||||
# 3. 使用错误密码(应返回401)
|
||||
curl -I -u admin:wrongpassword https://your-domain.com/jenkins/
|
||||
|
||||
# 4. 测试频率限制
|
||||
for i in {1..20}; do
|
||||
curl -I https://your-domain.com/jenkins/ &
|
||||
done
|
||||
|
||||
# 5. 测试Webhook签名验证
|
||||
curl -X POST https://your-domain.com/generic-webhook-trigger/invoke \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"test": "data"}'
|
||||
# 应返回403
|
||||
|
||||
# 6. 使用正确签名
|
||||
PAYLOAD='{"ref": "refs/heads/release/test"}'
|
||||
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | awk '{print $2}')
|
||||
curl -X POST https://your-domain.com/generic-webhook-trigger/invoke \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Gitea-Signature: sha256=$SIGNATURE" \
|
||||
-d "$PAYLOAD"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚨 应急响应流程
|
||||
|
||||
### 检测到攻击时的响应
|
||||
|
||||
#### Level 1:可疑活动
|
||||
|
||||
**触发条件:**
|
||||
- 多次认证失败(>10次/分钟)
|
||||
- 异常请求模式
|
||||
- 非白名单IP访问Webhook
|
||||
|
||||
**响应措施:**
|
||||
|
||||
```bash
|
||||
# 1. 记录事件
|
||||
echo "$(date): 可疑活动检测 - IP: $ATTACKER_IP" >> /var/log/jenkins-security-events.log
|
||||
|
||||
# 2. 临时封禁IP
|
||||
sudo ufw deny from $ATTACKER_IP
|
||||
|
||||
# 3. 通知管理员
|
||||
./scripts/notify-wechat.sh "安全警告:检测到可疑访问 - IP: $ATTACKER_IP"
|
||||
```
|
||||
|
||||
#### Level 2:确认攻击
|
||||
|
||||
**触发条件:**
|
||||
- 成功利用漏洞
|
||||
- 恶意代码注入
|
||||
- 数据泄露迹象
|
||||
|
||||
**响应措施:**
|
||||
|
||||
```bash
|
||||
# 1. 立即隔离
|
||||
sudo systemctl stop jenkins
|
||||
sudo ufw deny 443/tcp
|
||||
|
||||
# 2. 保存证据
|
||||
sudo tar -czf /tmp/incident-$(date +%Y%m%d_%H%M%S).tar.gz \
|
||||
/var/lib/jenkins \
|
||||
/var/log/nginx/jenkins-*.log \
|
||||
/var/log/jenkins-security-events.log
|
||||
|
||||
# 3. 检查完整性
|
||||
find /var/lib/jenkins -type f -mtime -1 -ls
|
||||
|
||||
# 4. 通知管理层
|
||||
./scripts/notify-wechat.sh "严重安全事件:Jenkins遭受攻击,已隔离系统"
|
||||
```
|
||||
|
||||
#### Level 3:数据泄露
|
||||
|
||||
**触发条件:**
|
||||
- 凭证被窃取
|
||||
- 生产数据泄露
|
||||
- 系统被完全控制
|
||||
|
||||
**响应措施:**
|
||||
|
||||
```bash
|
||||
# 1. 完全断网
|
||||
sudo ifdown eth0
|
||||
|
||||
# 2. 备份现场
|
||||
sudo dd if=/dev/sda of=/backup/incident-disk-image.img
|
||||
|
||||
# 3. 更换所有凭证
|
||||
# - Jenkins管理员密码
|
||||
# - Webhook Token
|
||||
# - SSH密钥
|
||||
# - 数据库密码
|
||||
# - API密钥
|
||||
|
||||
# 4. 通知所有相关方
|
||||
# - 管理层
|
||||
# - 安全团队
|
||||
# - 客户(如涉及客户数据)
|
||||
|
||||
# 5. 启动事件响应计划
|
||||
```
|
||||
|
||||
### 恢复流程
|
||||
|
||||
```bash
|
||||
# 1. 从干净备份恢复
|
||||
sudo rm -rf /var/lib/jenkins
|
||||
sudo tar -xzf /backup/jenkins-clean-backup.tar.gz -C /
|
||||
|
||||
# 2. 应用所有安全补丁
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
|
||||
# 3. 重新配置安全设置
|
||||
sudo ./scripts/security/jenkins-security-hardening.sh
|
||||
|
||||
# 4. 全面验证
|
||||
sudo /usr/local/bin/verify-jenkins-security.sh
|
||||
|
||||
# 5. 逐步恢复服务
|
||||
sudo systemctl start jenkins
|
||||
# 监控日志
|
||||
tail -f /var/log/nginx/jenkins-access.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 长期维护建议
|
||||
|
||||
### 定期安全审计
|
||||
|
||||
**每日:**
|
||||
- 检查访问日志异常
|
||||
- 监控失败认证次数
|
||||
- 检查系统资源使用
|
||||
|
||||
**每周:**
|
||||
- 审查用户权限
|
||||
- 检查插件更新
|
||||
- 分析安全日志
|
||||
|
||||
**每月:**
|
||||
- 更新Jenkins和插件
|
||||
- 更换敏感凭证
|
||||
- 进行渗透测试
|
||||
|
||||
**每季度:**
|
||||
- 全面安全评估
|
||||
- 灾难恢复演练
|
||||
- 安全培训
|
||||
|
||||
### 自动化监控
|
||||
|
||||
```bash
|
||||
# 添加到crontab
|
||||
crontab -e
|
||||
```
|
||||
|
||||
```cron
|
||||
# 每小时检查异常访问
|
||||
0 * * * * /usr/local/bin/monitor-jenkins-security.sh
|
||||
|
||||
# 每天备份配置
|
||||
0 2 * * * tar -czf /backup/jenkins-config-$(date +\%Y\%m\%d).tar.gz /var/lib/jenkins
|
||||
|
||||
# 每周更新检查
|
||||
0 3 * * 0 apt update && apt list --upgradable | grep jenkins
|
||||
|
||||
# 每月更换Webhook Token
|
||||
0 4 1 * * /usr/local/bin/rotate-jenkins-secrets.sh
|
||||
```
|
||||
|
||||
### 安全改进路线图
|
||||
|
||||
**Phase 1(当前):基础防护**
|
||||
- ✅ 网络隔离
|
||||
- ✅ HTTP Basic Auth
|
||||
- ✅ Webhook签名验证
|
||||
|
||||
**Phase 2(1个月内):增强认证**
|
||||
- 🔲 集成OAuth2/OIDC
|
||||
- 🔲 多因素认证(MFA)
|
||||
- 🔲 细粒度权限控制
|
||||
|
||||
**Phase 3(3个月内):高级防护**
|
||||
- 🔲 Web应用防火墙(WAF)
|
||||
- 🔲 入侵检测系统(IDS)
|
||||
- 🔲 安全信息和事件管理(SIEM)
|
||||
|
||||
**Phase 4(6个月内):零信任架构**
|
||||
- 🔲 零信任网络访问(ZTNA)
|
||||
- 🔲 微服务隔离
|
||||
- 🔲 持续安全验证
|
||||
|
||||
---
|
||||
|
||||
## 📞 联系方式
|
||||
|
||||
**安全负责人:** 张翔
|
||||
**应急响应:** security@your-domain.com
|
||||
**技术支持:** devops@your-domain.com
|
||||
|
||||
---
|
||||
|
||||
## 📚 参考资料
|
||||
|
||||
- [Jenkins Security Best Practices](https://www.jenkins.io/doc/book/security/)
|
||||
- [OWASP CI/CD Security Guide](https://owasp.org/www-project-devsecops-guideline/)
|
||||
- [NIST Cybersecurity Framework](https://www.nist.gov/cyberframework)
|
||||
- [Jenkins Security Advisory](https://www.jenkins.io/security/advisories/)
|
||||
|
||||
---
|
||||
|
||||
**最后更新:** 2026-04-07
|
||||
**文档版本:** 1.0
|
||||
Reference in New Issue
Block a user