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"
相关推荐
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ1 小时前
gitlab 开发人员无法创建分支,管理员配置分支权限
gitlab
筵陌5 小时前
Linux线程概念与控制(下)
linux
-SGlow-6 小时前
MySQL相关概念和易错知识点(3)(表内容的CURD、内置函数)
linux·运维·服务器·数据库·mysql
永远向阳而生7 小时前
【Linux】磁盘存储+文件系统简介
linux
君不见~7 小时前
Windows 10 WSL&Ubuntu 22.04 安装并迁移到 F 盘
linux·ubuntu·wsl迁移盘符·wsl迁移
PanYu——BJ7 小时前
CentOS Nginx 1.13.9 部署文档
linux·nginx·centos
全栈测试笔记7 小时前
【汇总】接口自动化测试 + 持续集成(文末视频演示)
ci/cd
UQWRJ7 小时前
菜鸟教程Linux ViVimYumApt笔记
linux·运维·笔记
Ray Song7 小时前
Linux DNS解析3 -- DNS解析代理配置使用
linux·dns解析·dns代理
sz66cm8 小时前
Linux基础 -- 内核快速向用户态共享内核变量方案之ctl_table
linux·运维·服务器