方案概述
本方案实现在GitLab CI/CD中根据不同人员的权限级别执行不同的流水线步骤,主要基于GitLab的以下特性:
rules
条件判断variables
变量传递only/except
条件限制- 用户权限API查询
基础权限模型设计
1. 用户角色定义
角色 | 描述 | 对应GitLab权限 |
---|---|---|
Developer | 普通开发人员 | Developer |
Maintainer | 项目维护者 | Maintainer |
Owner | 项目所有者 | Owner |
Auditor | 审计人员 | Reporter |
2. 权限与流水线阶段对应关系
流水线阶段 | Developer | Maintainer | Owner | Auditor |
---|---|---|---|---|
build | ✓ | ✓ | ✓ | ✓ |
test | ✓ | ✓ | ✓ | ✓ |
staging | ✗ | ✓ | ✓ | ✓ |
production | ✗ | ✗ | ✓ | ✗ |
audit | ✗ | ✗ | ✗ | ✓ |
实现方案
1. 基于分支保护的方案
stages:
- build
- test
- staging
- production
- audit
build:
stage: build
script: echo "Building..."
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
test:
stage: test
script: echo "Testing..."
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
staging:
stage: staging
script: echo "Deploying to staging..."
rules:
- if: '$CI_COMMITTER_ACCESS_LEVEL >= 40' # Maintainer及以上
- if: '$CI_DEPLOY_USER_ACCESS_LEVEL >= 40'
production:
stage: production
script: echo "Deploying to production..."
rules:
- if: '$CI_COMMITTER_ACCESS_LEVEL == 50' # Only Owner
- if: '$CI_DEPLOY_USER_ACCESS_LEVEL == 50'
audit:
stage: audit
script: echo "Running audit..."
rules:
- if: '$CI_COMMITTER_ACCESS_LEVEL == 20' # Reporter
- if: '$CI_DEPLOY_USER_ACCESS_LEVEL == 20'
2. 基于自定义变量的方案(更灵活)
variables:
# 通过API获取用户权限级别
USER_ACCESS_LEVEL: $(
curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/members/$GITLAB_USER_ID" | \
jq '.access_level'
)
stages:
- build
- test
- staging
- production
- audit
.job_template: &job_settings
interruptible: true
tags:
- docker
build:
<<: *job_settings
stage: build
script: echo "Building..."
rules:
- if: '$USER_ACCESS_LEVEL >= 30' # Developer+
test:
<<: *job_settings
stage: test
script: echo "Testing..."
rules:
- if: '$USER_ACCESS_LEVEL >= 30' # Developer+
staging:
<<: *job_settings
stage: staging
script: echo "Deploying to staging..."
rules:
- if: '$USER_ACCESS_LEVEL >= 40' # Maintainer+
production:
<<: *job_settings
stage: production
script: echo "Deploying to production..."
rules:
- if: '$USER_ACCESS_LEVEL == 50' # Owner only
- when: manual
audit:
<<: *job_settings
stage: audit
script: echo "Running audit..."
rules:
- if: '$USER_ACCESS_LEVEL == 20' # Reporter only
3. 基于分支+角色的混合方案
stages:
- pre-build
- build
- test
- deploy
pre-build:
stage: pre-build
script:
- |
# 根据用户权限设置变量
if [ $CI_COMMITTER_ACCESS_LEVEL -ge 40 ]; then
echo "DEPLOY_ENV=staging" >> deploy.env
fi
if [ $CI_COMMITTER_ACCESS_LEVEL -eq 50 ]; then
echo "DEPLOY_ENV=production" >> deploy.env
fi
artifacts:
reports:
dotenv: deploy.env
build:
stage: build
script: echo "Building..."
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
test:
stage: test
script: echo "Testing..."
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
deploy-staging:
stage: deploy
script: echo "Deploying to staging..."
rules:
- if: '$DEPLOY_ENV == "staging"'
needs: ["pre-build"]
deploy-production:
stage: deploy
script: echo "Deploying to production..."
rules:
- if: '$DEPLOY_ENV == "production"'
- when: manual
needs: ["pre-build"]
高级控制方案
1. 使用项目变量控制
-
在GitLab项目设置中创建变量:
PROD_DEPLOY_GROUPS
= “owner-group”STAGING_DEPLOY_GROUPS
= “maintainer-group,owner-group”
-
在.gitlab-ci.yml中:
deploy-prod:
stage: deploy
script: ./deploy-prod.sh
rules:
- if: '$CI_COMMITTER_ACCESS_LEVEL == 50 || $CI_USER_GROUP =~ $PROD_DEPLOY_GROUPS'
- when: manual
2. 使用外部权限服务
deploy:
stage: deploy
before_script:
- |
ACCESS_LEVEL=$(curl -s "https://auth-service.example.com/check?user=$GITLAB_USER_LOGIN&project=$CI_PROJECT_ID")
export DEPLOY_ACCESS=$ACCESS_LEVEL
script:
- |
if [ "$DEPLOY_ACCESS" == "prod" ]; then
./deploy-prod.sh
elif [ "$DEPLOY_ACCESS" == "stage" ]; then
./deploy-stage.sh
else
echo "No deploy permission"
exit 1
fi
rules:
- if: '$CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "api"'
最佳实践建议
-
权限验证双重检查:
- 前端通过.gitlab-ci.yml限制
- 后端在实际部署脚本中再次验证
-
审计日志:
after_script: - | echo "$(date): $GITLAB_USER_EMAIL ran $CI_JOB_NAME" >> /var/log/ci_audit.log
-
紧急覆盖机制:
deploy-emergency: stage: deploy script: ./deploy-prod.sh rules: - if: '$CI_EMERGENCY_DEPLOY == "true" && $CI_COMMITTER_ACCESS_LEVEL >= 40' - when: never
-
权限矩阵可视化:
- 在项目README中维护权限矩阵表
- 使用CI Lint工具验证规则
注意事项
- 敏感操作(如生产部署)建议始终保留
when: manual
作为最后保障 CI_COMMITTER_ACCESS_LEVEL
在合并请求流水线中可能不可用,需使用CI_MERGE_REQUEST_SOURCE_BRANCH_SHA
- 对于fork的项目,需要特别处理权限检查
- 缓存和artifacts在不同权限的job之间共享时要注意安全
调试技巧
-
添加调试job查看权限信息:
show-info: stage: .pre script: - echo "User: $GITLAB_USER_LOGIN" - echo "Access level: $CI_COMMITTER_ACCESS_LEVEL" - echo "Groups: $CI_USER_GROUPS" rules: - when: always
-
使用CI Lint工具测试规则逻辑
-
查看流水线变量的实际值:
curl --header "PRIVATE-TOKEN: <your-token>" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_ID/variables"