安全最佳实践 #

本节将介绍Jenkins安全加固的最佳实践,帮助您构建安全的CI/CD环境。

安全原则 #

1. 最小权限原则 #

只授予完成任务所需的最小权限。

2. 纵深防御 #

多层安全防护,不依赖单一安全措施。

3. 安全默认 #

默认配置应该是安全的。

4. 定期审计 #

定期检查和审计安全配置。

系统安全 #

更新Jenkins #

定期更新Jenkins到最新稳定版本:

bash
# Docker方式
docker pull jenkins/jenkins:lts
docker stop jenkins
docker rm jenkins
docker run -d --name jenkins jenkins/jenkins:lts

# WAR包方式
wget https://updates.jenkins.io/latest/jenkins.war
systemctl restart jenkins

更新插件 #

定期更新插件:

  1. 进入 Manage Jenkins → Manage Plugins
  2. 检查 Updates 标签
  3. 更新所有插件

禁用不必要的功能 #

text
Manage Jenkins → System:
  ☐ Enable CLI over remoting
  ☐ Enable Jenkins CLI

禁用旧协议 #

text
Manage Jenkins → System → Agent Protocols:
  ☐ JNLP-connect
  ☐ JNLP2-connect
  ☑ JNLP4-connect

认证安全 #

强密码策略 #

安装 Strict Crumb Issuer 插件:

text
Manage Jenkins → System → CSRF Protection:
  ☑ Enable CSRF Protection
  Crumb Issuer: Strict Crumb Issuer
  ☑ Validate Crumb and Session ID

双因素认证 #

安装 Google Authenticator 插件:

text
Manage Jenkins → System → Security Realm:
  Security Realm: Google Authenticator

禁用匿名访问 #

text
Manage Jenkins → Configure Global Security:
  Authorization: Logged-in users can do anything
  ☐ Allow anonymous read access

密码策略 #

安装 Password Strategy 插件:

text
Manage Jenkins → System:
  Password Policy:
    Minimum length: 12
    Require uppercase: true
    Require lowercase: true
    Require digit: true
    Require special character: true

授权安全 #

使用角色策略 #

text
Authorization: Role-Based Strategy

权限分离 #

text
管理员角色:
  - Overall/Administer
  
开发者角色:
  - Job/Read
  - Job/Build
  - Job/Configure
  - Job/Workspace
  
查看者角色:
  - Overall/Read
  - Job/Read

项目级权限 #

对敏感项目设置项目级权限:

text
Job Configuration:
  ☑ Enable project-based security
  配置允许的用户和权限

凭据安全 #

使用凭据管理 #

不要在代码中硬编码敏感信息:

groovy
// 不推荐
sh 'deploy.sh --password mypassword'

// 推荐
withCredentials([string(credentialsId: 'db-password', variable: 'PASSWORD')]) {
    sh 'deploy.sh --password $PASSWORD'
}

凭据轮换 #

定期轮换凭据:

groovy
import jenkins.model.*
import com.cloudbees.plugins.credentials.*
import com.cloudbees.plugins.credentials.impl.*

def updateCredential(String id, String newPassword) {
    def domain = Domain.global()
    def store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()
    
    def oldCred = CredentialsProvider.lookupCredentials(
        StandardUsernamePasswordCredentials,
        Jenkins.instance,
        null,
        null
    ).find { it.id == id }
    
    def newCred = new UsernamePasswordCredentialsImpl(
        CredentialsScope.GLOBAL,
        id,
        oldCred.description,
        oldCred.username,
        newPassword
    )
    
    store.updateCredentials(domain, oldCred, newCred)
}

外部凭据存储 #

使用HashiCorp Vault等外部凭据存储:

groovy
withVault(configuration: [
    engineVersion: 2,
    path: 'secret/jenkins'
], vaultSecrets: [
    [
        path: 'database',
        secretValues: [
            [vaultKey: 'password', envVar: 'DB_PASSWORD']
        ]
    ]
]) {
    sh 'deploy.sh'
}

网络安全 #

HTTPS配置 #

使用HTTPS访问Jenkins:

nginx
server {
    listen 443 ssl http2;
    server_name jenkins.example.com;
    
    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    
    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen 80;
    server_name jenkins.example.com;
    return 301 https://$server_name$request_uri;
}

禁用HTTP #

text
Manage Jenkins → System:
  Jenkins URL: https://jenkins.example.com/

限制访问IP #

nginx
location / {
    allow 10.0.0.0/8;
    allow 192.168.0.0/16;
    deny all;
    
    proxy_pass http://localhost:8080;
}

防火墙配置 #

bash
# 只允许内网访问
iptables -A INPUT -p tcp --dport 8080 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j DROP

Agent安全 #

禁用Master构建 #

text
Manage Jenkins → System:
  # of executors: 0

Agent认证 #

text
Manage Jenkins → Configure Global Security:
  ☑ Enable Agent → Master Access Control
  ☑ Require authentication for agent connections

Agent协议 #

只使用安全的Agent协议:

text
Manage Jenkins → System → Agent Protocols:
  ☐ JNLP-connect
  ☐ JNLP2-connect
  ☑ JNLP4-connect

Agent权限 #

限制Agent的访问权限:

text
Manage Jenkins → Manage Nodes:
  Node Configuration → Node Properties:
    ☑ Tool Locations
    ☑ Environment variables

日志和监控 #

审计日志 #

安装 Audit Trail 插件:

text
Manage Jenkins → System → Audit Trail:
  ☑ Log all requests
  Log file: /var/log/jenkins/audit.log

安全日志 #

配置安全相关日志:

text
Manage Jenkins → System Log:
  Add Logger:
    Logger: hudson.security
    Level: FINE

监控告警 #

安装 Monitoring 插件:

text
Manage Jenkins → Monitoring:
  监控系统资源和JVM状态

备份和恢复 #

备份配置 #

定期备份Jenkins配置:

bash
#!/bin/bash
BACKUP_DIR="/backup/jenkins"
DATE=$(date +%Y%m%d)

# 备份配置
tar -czf ${BACKUP_DIR}/jenkins-config-${DATE}.tar.gz \
    ${JENKINS_HOME}/config.xml \
    ${JENKINS_HOME}/jobs \
    ${JENKINS_HOME}/users \
    ${JENKINS_HOME}/credentials.xml

# 备份密钥
tar -czf ${BACKUP_DIR}/jenkins-secrets-${DATE}.tar.gz \
    ${JENKINS_HOME}/secrets

# 保留最近30天的备份
find ${BACKUP_DIR} -name "*.tar.gz" -mtime +30 -delete

恢复配置 #

bash
# 恢复配置
tar -xzf jenkins-config-20260328.tar.gz -C ${JENKINS_HOME}

# 恢复密钥
tar -xzf jenkins-secrets-20260328.tar.gz -C ${JENKINS_HOME}

# 重启Jenkins
systemctl restart jenkins

安全检查清单 #

系统安全 #

  • [ ] 更新Jenkins到最新版本
  • [ ] 更新所有插件
  • [ ] 禁用不必要的功能
  • [ ] 禁用旧协议

认证安全 #

  • [ ] 配置认证方式
  • [ ] 禁用匿名访问
  • [ ] 实施强密码策略
  • [ ] 启用双因素认证

授权安全 #

  • [ ] 配置授权策略
  • [ ] 使用角色管理
  • [ ] 遵循最小权限原则
  • [ ] 配置项目级权限

凭据安全 #

  • [ ] 使用凭据管理
  • [ ] 定期轮换凭据
  • [ ] 考虑外部凭据存储
  • [ ] 不在日志中暴露凭据

网络安全 #

  • [ ] 启用HTTPS
  • [ ] 配置防火墙
  • [ ] 限制访问IP
  • [ ] 配置反向代理

Agent安全 #

  • [ ] 禁用Master构建
  • [ ] 启用Agent认证
  • [ ] 使用安全协议
  • [ ] 限制Agent权限

日志和监控 #

  • [ ] 启用审计日志
  • [ ] 配置安全日志
  • [ ] 设置监控告警
  • [ ] 定期检查日志

备份和恢复 #

  • [ ] 定期备份配置
  • [ ] 备份密钥文件
  • [ ] 测试恢复流程
  • [ ] 异地备份

安全加固脚本 #

groovy
import jenkins.model.*
import hudson.security.*

def instance = Jenkins.getInstance()

// 禁用CLI
instance.setCliEnabled(false)

// 设置安全域
def realm = new HudsonPrivateSecurityRealm(false)
instance.setSecurityRealm(realm)

// 设置授权策略
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
strategy.setAllowAnonymousRead(false)
instance.setAuthorizationStrategy(strategy)

// 禁用JNLP
instance.setSlaveAgentPort(-1)

// 保存配置
instance.save()

println "Security hardening completed!"

下一步学习 #

小结 #

  • 安全是一个持续的过程
  • 遵循最小权限原则
  • 定期更新和审计
  • 使用HTTPS和安全协议
  • 保护凭据安全
  • 监控和日志审计
  • 定期备份配置
最后更新:2026-03-28