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"
相关推荐
张小姐的猫5 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生6 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
diving deep6 小时前
CI/CD
ci/cd
imc.117 小时前
linux基础IO
linux·运维·服务器
BelongPanda9 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯9 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_777998349 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器
yunwei379 小时前
eBPF 教程:检查 exec 后真正安装的可执行镜像
linux·开源
笑锝没心没肺10 小时前
yum update 报错:GPG key retrieval failed: [Errno 14] HTTPS Error 404 - Not Found
linux·运维·服务器
AAA@峥10 小时前
CentOS Stream8 基于 Packstack 搭建 OpenStack 云平台全流程实战
linux·centos·openstack