GitLab CI流水线权限隔离

方案概述

本方案实现在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. 基于分支保护的方案

yaml 复制代码
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. 基于自定义变量的方案(更灵活)

yaml 复制代码
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. 基于分支+角色的混合方案

yaml 复制代码
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中:

yaml 复制代码
deploy-prod:
  stage: deploy
  script: ./deploy-prod.sh
  rules:
    - if: '$CI_COMMITTER_ACCESS_LEVEL == 50 || $CI_USER_GROUP =~ $PROD_DEPLOY_GROUPS'
    - when: manual

2. 使用外部权限服务

yaml 复制代码
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. 审计日志

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

    yaml 复制代码
    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查看权限信息:

    yaml 复制代码
    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. 查看流水线变量的实际值:

    bash 复制代码
    curl --header "PRIVATE-TOKEN: <your-token>" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_ID/variables"
相关推荐
新时代牛马2 小时前
OpenSSL引擎 + PKCS11 + SoftHSM2认证
linux
皓月盈江3 小时前
国产Linux银河麒麟操作系统安装开源免费Draw.io(diagrams.net)替代Visio
linux·ubuntu·开源·draw.io·visio·银河麒麟操作系统·diagrams.net
2301_793102495 小时前
linux——C程序的编译与调试
linux
三体世界5 小时前
HTTPS加密原理
linux·开发语言·网络·c++·网络协议·http·https
CBCU5 小时前
关于ubuntu环境下vscode进行debug的随笔
linux·vscode·ubuntu
浅浅练习两年半5 小时前
5.3 LED字符设备驱动
linux
우 유6 小时前
【ing】Ubuntu安装Anaconda及环境配置\docker\pycharm
linux·运维·ubuntu
lqjun08276 小时前
在Ubuntu 24.04上安装cuDNN v8.x.x兼容CUDA 11.8
linux·运维·ubuntu
ZKf30FkG7 小时前
在 CentOS 7.9 中 Node 18.20.2 安装指南
linux·运维·centos
Virgocloud7 小时前
Centos更换镜像源-腾讯云镜像源
linux·centos·腾讯云