安全与权限 #
一、安全概述 #
GitLab CI/CD提供了多层次的安全机制,保护代码和部署环境的安全。
text
┌─────────────────────────────────────────────────────────────┐
│ 安全机制层次 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 代码安全 流水线安全 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ • SAST │ │ • 变量保护 │ │
│ │ • 依赖扫描 │ │ • Masked变量 │ │
│ │ • 密钥检测 │ │ • 权限控制 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ 环境安全 部署安全 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ • 环境保护 │ │ • 审批流程 │ │
│ │ • 访问控制 │ │ • 部署窗口 │ │
│ │ • 停止环境 │ │ • 回滚机制 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
二、安全扫描 #
1. SAST(静态应用安全测试) #
启用SAST:
yaml
include:
- template: Jobs/SAST.gitlab-ci.yml
自定义配置:
yaml
include:
- template: Jobs/SAST.gitlab-ci.yml
variables:
SAST_EXCLUDED_PATHS: "vendor,lib"
SAST_BANDIT_EXCLUDED_PATHS: "tests"
2. 依赖扫描 #
启用依赖扫描:
yaml
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
自定义配置:
yaml
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
variables:
DS_EXCLUDED_PATHS: "vendor"
DS_MAX_DEPTH: 5
3. 容器扫描 #
启用容器扫描:
yaml
include:
- template: Jobs/Container-Scanning.gitlab-ci.yml
variables:
CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
4. 密钥检测 #
启用密钥检测:
yaml
include:
- template: Jobs/Secret-Detection.gitlab-ci.yml
5. 完整安全流水线 #
yaml
stages:
- test
- security
include:
- template: Jobs/SAST.gitlab-ci.yml
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
- template: Jobs/Secret-Detection.gitlab-ci.yml
container_scanning:
stage: security
image: docker:latest
services:
- docker:dind
script:
- docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
allow_failure: true
三、变量安全 #
1. Protected变量 #
Protected变量只在protected分支和tags上可用:
- 进入Settings → CI/CD → Variables
- 添加变量时勾选"Protect variable"
yaml
deploy_production:
script:
- echo $PROD_SECRET_KEY
only:
- main
2. Masked变量 #
Masked变量在日志中会被隐藏:
yaml
variables:
SECRET_TOKEN:
value: "my-secret-token"
masked: true
要求:
- 值必须是单行
- 符合正则表达式:
[a-zA-Z0-9_+=/.:@-]+ - 至少8个字符
3. 文件变量 #
敏感文件使用文件变量:
yaml
variables:
SSH_KEY:
type: file
value: |
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
deploy:
script:
- chmod 600 $SSH_KEY
- ssh -i $SSH_KEY user@server
4. 变量作用域 #
yaml
deploy_staging:
environment:
name: staging
variables:
DEPLOY_KEY: $STAGING_KEY
deploy_production:
environment:
name: production
variables:
DEPLOY_KEY: $PRODUCTION_KEY
四、权限控制 #
1. 流水线权限 #
Settings → CI/CD → General pipelines:
| 设置 | 说明 |
|---|---|
| Public pipelines | 公开流水线 |
| Allow pipeline triggers | 允许触发流水线 |
| CI/CD access token | 访问令牌 |
2. 环境权限 #
Settings → CI/CD → Protected environments:
yaml
deploy_production:
stage: deploy
environment:
name: production
script:
- echo "Deploying..."
only:
- main
3. 变量权限 #
Settings → CI/CD → Variables:
| 设置 | 说明 |
|---|---|
| Protect variable | 只在protected分支可用 |
| Mask variable | 在日志中隐藏 |
| Environments | 限制环境 |
4. Job权限 #
yaml
deploy_production:
stage: deploy
environment:
name: production
script:
- echo "Deploying..."
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: false
五、环境保护 #
1. Protected Environments #
Settings → CI/CD → Protected environments:
- 点击"Protect an environment"
- 选择环境名称
- 设置允许的用户/角色
- 设置允许的分支
2. 环境配置 #
yaml
deploy_production:
stage: deploy
environment:
name: production
url: https://example.com
deployment_tier: production
script:
- echo "Deploying..."
only:
- main
when: manual
3. 环境停止 #
yaml
deploy_staging:
stage: deploy
environment:
name: staging
url: https://staging.example.com
on_stop: stop_staging
script:
- echo "Deploying to staging"
stop_staging:
stage: deploy
environment:
name: staging
action: stop
script:
- echo "Stopping staging"
when: manual
only:
- develop
4. 环境审批 #
yaml
deploy_production:
stage: deploy
environment:
name: production
script:
- echo "Deploying..."
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: false
六、密钥管理 #
1. GitLab变量 #
yaml
variables:
DATABASE_URL: "postgres://user:pass@host:5432/db"
API_KEY: "your-api-key"
2. 外部密钥管理 #
HashiCorp Vault #
yaml
variables:
VAULT_ADDR: "https://vault.example.com"
VAULT_TOKEN: "your-token"
deploy:
script:
- export DB_PASSWORD=$(vault kv get -field=password secret/db)
AWS Secrets Manager #
yaml
deploy:
script:
- export DB_PASSWORD=$(aws secretsmanager get-secret-value --secret-id db-password --query SecretString --output text)
3. CI/CD变量最佳实践 #
yaml
variables:
APP_NAME: "myapp"
REGISTRY: "registry.example.com"
deploy:
script:
- echo "Deploying $APP_NAME to $REGISTRY"
七、安全最佳实践 #
1. 最小权限原则 #
yaml
deploy_staging:
environment:
name: staging
script:
- echo "Deploying..."
rules:
- if: $CI_COMMIT_BRANCH == "develop"
2. 分离环境密钥 #
yaml
deploy_staging:
variables:
DEPLOY_KEY: $STAGING_KEY
environment:
name: staging
deploy_production:
variables:
DEPLOY_KEY: $PRODUCTION_KEY
environment:
name: production
when: manual
3. 使用Protected变量 #
yaml
deploy_production:
script:
- echo $PROD_SECRET
only:
- main
4. 启用安全扫描 #
yaml
include:
- template: Jobs/SAST.gitlab-ci.yml
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
- template: Jobs/Secret-Detection.gitlab-ci.yml
5. 限制镜像来源 #
yaml
variables:
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
build:
script:
- docker pull $DOCKER_IMAGE
6. 审计日志 #
Settings → Audit Events:
- 查看所有CI/CD操作日志
- 监控敏感操作
- 设置告警
八、安全流水线示例 #
yaml
stages:
- test
- security
- build
- deploy
include:
- template: Jobs/SAST.gitlab-ci.yml
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
- template: Jobs/Secret-Detection.gitlab-ci.yml
variables:
REGISTRY: $CI_REGISTRY
IMAGE_NAME: $CI_REGISTRY_IMAGE
test:
stage: test
image: node:18
script:
- npm ci
- npm test
coverage: '/Coverage: \d+%/'
security_gate:
stage: security
script:
- echo "Checking security scan results..."
- |
if [ -f "gl-sast-report.json" ]; then
high_vulnerabilities=$(jq '.vulnerabilities | map(select(.severity == "High" or .severity == "Critical")) | length' gl-sast-report.json)
if [ "$high_vulnerabilities" -gt 0 ]; then
echo "Found $high_vulnerabilities high/critical vulnerabilities"
exit 1
fi
fi
allow_failure: false
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
- docker push $IMAGE_NAME:$CI_COMMIT_SHA
deploy_staging:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: staging
url: https://staging.example.com
script:
- kubectl set image deployment/myapp myapp=$IMAGE_NAME:$CI_COMMIT_SHA
only:
- develop
deploy_production:
stage: deploy
image: bitnami/kubectl:latest
environment:
name: production
url: https://example.com
script:
- kubectl set image deployment/myapp myapp=$IMAGE_NAME:$CI_COMMIT_SHA
only:
- main
when: manual
allow_failure: false
下一步 #
现在你已经掌握了安全与权限,接下来让我们学习 父子流水线!
最后更新:2026-03-28