GitLab 安全加固
GitLab 承载源代码与 CI 密钥,是攻击者的高价值目标。以下加固项按 网络 → 认证 → 权限 → 审计 顺序实施,生产环境应全部覆盖。
1. HTTPS安全
1.1 强制 HTTPS
编辑 /etc/gitlab/gitlab.rb:
external_url 'https://gitlab.example.com'
nginx['redirect_http_to_https'] = true
nginx['ssl_certificate'] = "/etc/gitlab/ssl/gitlab.example.com.crt"
nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/gitlab.example.com.key"
nginx['ssl_protocols'] = "TLSv1.2 TLSv1.3"
nginx['ssl_ciphers'] = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"
nginx['ssl_prefer_server_ciphers'] = "on"
nginx['hsts_max_age'] = 31536000
nginx['hsts_include_subdomains'] = false
Let's Encrypt 自动证书:
letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['ops@example.com']
sudo gitlab-ctl reconfigure
curl -vI https://gitlab.example.com 2>&1 | grep -E 'HTTP/|Strict-Transport'
1.2 安全响应头
nginx['custom_gitlab_server_config'] = "
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy strict-origin-when-cross-origin;
"
2. SSH安全
GitLab SSH 默认端口 22,可通过 gitlab-sshd 或系统 sshd 提供服务。
2.1 修改 SSH 端口(可选)
gitlab_rails['gitlab_shell_ssh_port'] = 2222
防火墙同步放行:
sudo ufw allow 2222/tcp
用户 clone 地址变为 ssh://git@gitlab.example.com:2222/group/project.git。
2.2 SSH 密钥策略
Admin Area → Settings → General → Visibility and access controls:
- 禁止上传弱密钥(RSA < 2048)
- 启用 Two-factor authentication 强制策略(见下文)
- 定期审计 SSH Key:
Admin → Users → 导出用户列表
禁用 DSA 密钥、限制 ed25519/RSA 4096:
gitlab_rails['gitlab_shell_git_timeout'] = 800
3. 用户权限控制
3.1 注册与可见性
Admin → Settings → General:
| 配置项 | 生产建议 |
|---|---|
| Sign-up enabled | 关闭,仅 LDAP/OAuth 或 Admin 创建 |
| Default project visibility | Private |
| Default group visibility | Private |
| Restrict group creation | 仅 Admin 或 Trusted 用户 |
3.2 最小权限原则
- 项目级:Developer 仅给需要 push 的成员;Maintainer 控制在 2 人以内
- 组级:Owner 仅限平台管理员
- 使用 Group Access Token 替代共享个人账号
批量审计过期成员:
sudo gitlab-rails runner "
User.active.find_each do |u|
last = u.last_activity_on
puts \"#{u.username}\t#{last}\" if last && last < 90.days.ago.to_date
end
"
3.3 双因素认证
Admin → Settings → General → Sign-in restrictions → 勾选 Enforce two-factor authentication,Grace period 设为 7 天。
4. Token安全管理
GitLab 有多种 Token,泄露风险从高到低需分级管理。
| Token 类型 | 权限范围 | 管理建议 |
|---|---|---|
| Personal Access Token | 用户全部可访问资源 | 设过期时间、最小 scope |
| Project/Group Access Token | 项目/组范围 | 优先用于 CI 与自动化 |
| Deploy Token | 只读/读写 registry | 仅 registry pull |
| CI/CD Variables | Pipeline 内可见 | Mask + Protected + File type |
| Runner Registration Token | 注册 Runner | 改用 authentication token |
4.1 强制 Token 过期
Admin → Settings → General → Account and limit → 设置 Access token expiration 上限(如 90 天)。
4.2 CI 变量安全
项目 → Settings → CI/CD → Variables:
- 敏感值勾选 Mask variable
- 生产变量勾选 Protect variable(仅 protected 分支可用)
- 大密钥使用 File 类型,避免出现在 job log
撤销泄露 Token:
# Admin 撤销指定用户所有 PAT
sudo gitlab-rails runner "
user = User.find_by(username: 'leaked_user')
user.personal_access_tokens.active.each(&:revoke!)
"
5. Runner安全
Runner 能执行任意 CI 脚本,等同于在目标环境获得 shell 权限。
5.1 隔离策略
| Executor | 隔离级别 | 适用场景 |
|---|---|---|
| Docker | 中(共享 Docker daemon 有风险) | 通用 CI |
| Kubernetes | 高(Pod 级隔离) | 生产推荐 |
| Shell | 低 | 仅限专用裸机 |
5.2 Runner 加固
# /etc/gitlab-runner/config.toml
[[runners]]
[runners.docker]
privileged = false
disable_cache = false
volumes = ["/cache"]
allowed_images = ["registry.example.com/**"]
[runners.cache]
Type = "s3"
- 关闭
privileged = true,除非确实需要 DinD - 使用 Runner authentication token(GitLab 16+),废弃 registration token
- Protected Runner 仅服务 protected 分支/tag
- 不同安全域使用不同 Runner(如 prod-runner / dev-runner)
清理离线 Runner:
sudo gitlab-rails runner "
Ci::Runner.unscoped.where(contacted_at: ..30.days.ago).each(&:destroy!)
"
6. 审计日志
6.1 应用级审计事件
EE 提供完整 Audit Events;CE 可通过以下方式补充:
- Admin → Monitoring → Audit log(EE)
- 应用日志:
/var/log/gitlab/gitlab-rails/production.log - Nginx 访问日志:
/var/log/gitlab/nginx/gitlab_access.log
导出最近登录失败:
sudo grep 'Failed Login' /var/log/gitlab/gitlab-rails/production.log | tail -50
6.2 系统审计
# 配置变更追踪(/etc/gitlab/gitlab.rb 纳入 Git 管理)
sudo git log --oneline /etc/gitlab/gitlab.rb
# 谁修改了 gitlab.rb
sudo ausearch -f /etc/gitlab/gitlab.rb 2>/dev/null | tail -20
启用 auditd 监控关键路径:
sudo auditctl -w /etc/gitlab/gitlab.rb -p wa -k gitlab_config
sudo auditctl -w /var/opt/gitlab/backups -p wa -k gitlab_backup
7. 安全最佳实践
- 网络隔离:GitLab 置于内网或 Zero Trust 之后,Admin 面板不对公网开放
- 及时升级:关注 GitLab Security Releases,Critical 漏洞 48 小时内评估升级
- Container Registry 扫描:启用依赖扫描(SAST/Dependency Scanning)或接入 Trivy
- 禁用不必要服务:
grafana['enable'] = false # 若使用外部 Grafana
prometheus['enable'] = true # 保留监控但限制访问 IP
gitlab_rails['impersonation_enabled'] = false # 禁止 Admin 模拟用户(按需)
- 定期安全巡检清单:
- 无过期/未使用的 PAT 和 Deploy Token
- 所有 Admin 已启用 2FA
- Runner 无 privileged 滥用
- CI Variables 无明文密钥出现在公开项目
- TLS 证书有效期 > 30 天
-
gitlab-rake gitlab:check无安全相关 WARN
sudo gitlab-rake gitlab:check SANITIZE=true
sudo gitlab-ctl deploy-page status # 确认维护页可用,便于紧急下线