GitLab CI流水线权限隔离

发布于:2025-05-30 ⋅ 阅读:(15) ⋅ 点赞:(0)

方案概述

本方案实现在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. 使用项目变量控制

  1. 在GitLab项目设置中创建变量:

    • PROD_DEPLOY_GROUPS = “owner-group”
    • STAGING_DEPLOY_GROUPS = “maintainer-group,owner-group”
  2. 在.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"'

最佳实践建议

  1. 权限验证双重检查

    • 前端通过.gitlab-ci.yml限制
    • 后端在实际部署脚本中再次验证
  2. 审计日志

    after_script:
      - |
        echo "$(date): $GITLAB_USER_EMAIL ran $CI_JOB_NAME" >> /var/log/ci_audit.log
    
  3. 紧急覆盖机制

    deploy-emergency:
      stage: deploy
      script: ./deploy-prod.sh
      rules:
        - if: '$CI_EMERGENCY_DEPLOY == "true" && $CI_COMMITTER_ACCESS_LEVEL >= 40'
        - when: never
    
  4. 权限矩阵可视化

    • 在项目README中维护权限矩阵表
    • 使用CI Lint工具验证规则

注意事项

  1. 敏感操作(如生产部署)建议始终保留when: manual作为最后保障
  2. CI_COMMITTER_ACCESS_LEVEL在合并请求流水线中可能不可用,需使用CI_MERGE_REQUEST_SOURCE_BRANCH_SHA
  3. 对于fork的项目,需要特别处理权限检查
  4. 缓存和artifacts在不同权限的job之间共享时要注意安全

调试技巧

  1. 添加调试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
    
  2. 使用CI Lint工具测试规则逻辑

  3. 查看流水线变量的实际值:

    curl --header "PRIVATE-TOKEN: <your-token>" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_ID/variables"
    

网站公告

今日签到

点亮在社区的每一天
去签到