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"
相关推荐
网易独家音乐人Mike Zhou13 分钟前
【Linux应用】开发板USB共享网络,网线或USB以太网共享网络(局域网连接PC和开发板,实现PC给开发板共享网络,USB通过NDIS驱动共享)
linux·网络·单片机·mcu·物联网·嵌入式·iot
basketball6161 小时前
Linux C 管道文件操作
linux·运维·c语言
浩浩测试一下1 小时前
Windows 与 Linux 内核安全及 Metasploit/LinEnum 在渗透测试中的综合应用
linux·运维·windows·web安全·网络安全·系统安全·安全架构
stark张宇1 小时前
Linux 文件创建、删除、移动、复制基础知识整理
linux·服务器·centos
Jiangnan_Cai3 小时前
Linux 系统 docker 部署 Dify
linux·docker·大模型·dify
Two_brushes.4 小时前
【linux网络】深入理解 TCP/UDP:从基础端口号到可靠传输机制全解析
linux·运维·服务器
FJW0208144 小时前
【Linux】系统引导修复
linux·运维·服务器
慌糖4 小时前
CentOS 安装 Redis 简明指南
linux·redis·centos
设计师小聂!4 小时前
linux常用命令(一)
linux·运维·服务器
hnlucky4 小时前
《Nginx + 双Tomcat实战:域名解析、静态服务与反向代理、负载均衡全指南》
java·linux·服务器·前端·nginx·tomcat·web