如何在GitLab免费版CI流水线中组织Docker镜像签名及多环节审批流程?
基于GitLab免费版的多环节审批流水线实现方案
核心思路
利用GitLab CI/CD的阶段划分、手动触发作业、作业依赖关系以及CI变量校验,模拟不同环节的审批逻辑:自动测试环节(SCA/SAST/DAST)通过后自动推进,人工环节(代码评审)需手动确认后进入下一阶段,最终完成镜像签名与生产仓库推送。
1. 流水线阶段拆分与审批逻辑映射
将现有流程拆分为6个独立阶段,对应不同的审批/执行规则:
- pre-build-checks:自动执行SCA、SAST,通过后自动进入下一阶段
- code-review-approval:代码评审完成后,需人工触发此作业(模拟审批)
- build-push-dev:镜像构建并推送到开发环境私有仓库(依赖前两个阶段完成)
- deploy-test-dast:部署到测试环境并执行DAST,通过后自动推进
- approval-final:校验所有前序环节状态,需人工确认最终审批
- sign-push-prod:确认所有审批完成后,执行cosign签名并推送到生产仓库
2. 具体CI配置示例
stages: - pre-build-checks - code-review-approval - build-push-dev - deploy-test-dast - approval-final - sign-push-prod # 自动执行SCA、SAST,不允许失败 sast-sca-job: stage: pre-build-checks script: - echo "执行SCA依赖漏洞扫描..." - echo "执行SAST静态代码安全检查..." rules: - if: '$CI_PIPELINE_SOURCE == "push"' allow_failure: false # 代码评审后的人工审批触发作业 code-review-approval-job: stage: code-review-approval script: - echo "代码评审已完成,确认进入镜像构建环节" when: manual rules: - if: '$CI_PIPELINE_SOURCE == "push"' # 构建并推送开发环境镜像,依赖前序环节完成 build-dev-image: stage: build-push-dev script: - docker build -t dev-registry.example.com/app:$CI_COMMIT_SHA . - docker push dev-registry.example.com/app:$CI_COMMIT_SHA needs: ["sast-sca-job", "code-review-approval-job"] rules: - if: '$CI_PIPELINE_SOURCE == "push"' # 部署测试环境+DAST测试,自动推进 deploy-test-dast: stage: deploy-test-dast script: - echo "部署镜像到测试环境..." - echo "执行DAST动态安全扫描..." needs: ["build-dev-image"] allow_failure: false rules: - if: '$CI_PIPELINE_SOURCE == "push"' # 最终审批:自动校验前序自动环节状态+人工确认 final-approval: stage: approval-final script: # 通过GitLab API校验前序自动测试作业是否全部成功 - | JOB_STATUS=$(curl --header "PRIVATE-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_ID/jobs" | jq '.[] | select(.stage == "pre-build-checks" or .stage == "deploy-test-dast") | .status') if echo "$JOB_STATUS" | grep -v "success"; then echo "前序自动测试环节未全部通过,终止流程" exit 1 fi echo "所有自动环节已通过,确认进入生产推送阶段" when: manual needs: ["deploy-test-dast"] rules: - if: '$CI_PIPELINE_SOURCE == "push"' # 签名并推送生产镜像 sign-push-prod-image: stage: sign-push-prod script: # 拉取开发环境镜像并打生产标签 - docker pull dev-registry.example.com/app:$CI_COMMIT_SHA - docker tag dev-registry.example.com/app:$CI_COMMIT_SHA prod-registry.example.com/app:$CI_COMMIT_SHA # cosign签名镜像(私钥存储在CI/CD变量中) - cosign sign --key $COSIGN_PRIVATE_KEY prod-registry.example.com/app:$CI_COMMIT_SHA - docker push prod-registry.example.com/app:$CI_COMMIT_SHA needs: ["final-approval"] rules: - if: '$CI_PIPELINE_SOURCE == "push"'
3. 关键细节说明
- 手动触发作业:用
when: manual实现人工审批,团队成员只需在GitLab流水线页面点击"运行"即可推进流程,替代被否决的评论审批方式。 - 作业依赖控制:通过
needs字段确保每个阶段必须等待前序必要环节完成后才能执行,避免流程跳步。 - 自动状态校验:在最终审批环节通过GitLab API自动校验前序自动测试的状态,确保所有自动环节都达标,再允许进入生产推送阶段。
- 敏感信息管理:将cosign私钥、仓库凭证等敏感内容存储在GitLab项目的CI/CD变量中,避免明文暴露。
4. 额外优化建议
- 代码评审环节可结合GitLab的保护分支规则,设置必须通过指定数量的评审后才能合并代码,将MR合并作为流水线触发的前置条件,强化代码评审的强制性。
- 针对DAST测试,可添加漏洞阈值校验脚本(如高危漏洞数量为0才允许通过),进一步提升自动环节的严谨性。
内容的提问来源于stack exchange,提问作者Kirill Rudnev
相关产品推荐
相关产品推荐

