building-devsecops-pipeline-with-gitlab-ci

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Building DevSecOps Pipeline with GitLab CI

基于GitLab CI构建DevSecOps流水线

Overview

概述

GitLab provides an integrated DevSecOps platform that embeds security testing directly into the CI/CD pipeline. By leveraging GitLab's built-in security scanners---SAST, DAST, container scanning, dependency scanning, secret detection, and license compliance---teams can shift security left, catching vulnerabilities during development rather than post-deployment. GitLab Duo AI assists with false positive detection for SAST vulnerabilities, helping security teams focus on genuine issues.
GitLab提供了一个集成式DevSecOps平台,可将安全测试直接嵌入CI/CD流水线。通过利用GitLab内置的安全扫描器——SAST、DAST、容器扫描、依赖项扫描、密钥检测和许可证合规性检查——团队可以将安全左移,在开发阶段而非部署后发现漏洞。GitLab Duo AI可协助检测SAST漏洞中的误报,帮助安全团队专注于真正的问题。

When to Use

适用场景

  • When deploying or configuring building devsecops pipeline with gitlab ci capabilities in your environment
  • When establishing security controls aligned to compliance requirements
  • When building or improving security architecture for this domain
  • When conducting security assessments that require this implementation
  • 在您的环境中部署或配置基于GitLab CI能力的DevSecOps流水线时
  • 建立符合合规要求的安全控制措施时
  • 构建或改进该领域的安全架构时
  • 开展需要此实现的安全评估时

Prerequisites

前提条件

  • GitLab Ultimate license (required for full security scanner suite)
  • GitLab Runner configured (shared or self-hosted)
  • .gitlab-ci.yml
    pipeline configuration familiarity
  • Docker-in-Docker (DinD) or Kaniko for container builds
  • Application deployed to a staging environment for DAST scanning
  • GitLab Ultimate许可证(完整安全扫描器套件所需)
  • 已配置GitLab Runner(共享或自托管)
  • 熟悉
    .gitlab-ci.yml
    流水线配置
  • 用于容器构建的Docker-in-Docker (DinD)或Kaniko
  • 已部署到预发布环境的应用程序(用于DAST扫描)

Core Security Scanning Stages

核心安全扫描阶段

Static Application Security Testing (SAST)

静态应用安全测试(SAST)

SAST analyzes source code for vulnerabilities before compilation. GitLab supports 14+ languages using analyzers such as Semgrep, SpotBugs, Gosec, Bandit, and NodeJsScan. The simplest inclusion uses GitLab's managed templates.
SAST在编译前分析源代码中的漏洞。GitLab使用Semgrep、SpotBugs、Gosec、Bandit和NodeJsScan等分析器支持14+种语言。最简单的集成方式是使用GitLab的托管模板。

Dynamic Application Security Testing (DAST)

动态应用安全测试(DAST)

DAST tests running applications by simulating attack payloads against HTTP endpoints. It detects XSS, SQLi, CSRF, and other runtime vulnerabilities that static analysis cannot find. DAST requires a deployed, accessible target URL.
DAST通过向HTTP端点模拟攻击载荷来测试运行中的应用程序。它可以检测XSS、SQL注入、CSRF以及静态分析无法发现的其他运行时漏洞。DAST需要一个已部署且可访问的目标URL。

Container Scanning

容器扫描

Uses Trivy to scan Docker images for known CVEs in OS packages and application dependencies. Runs after the Docker build stage to gate images before they reach a registry.
使用Trivy扫描Docker镜像,查找操作系统包和应用程序依赖项中的已知CVE。在Docker构建阶段之后运行,以在镜像进入注册表前进行管控。

Dependency Scanning

依赖项扫描

Inspects dependency manifests (package.json, requirements.txt, pom.xml, Gemfile.lock) for known vulnerable versions. Operates at the source code level, complementing container scanning.
检查依赖项清单(package.json、requirements.txt、pom.xml、Gemfile.lock)中的已知易受攻击版本。在源代码层面运行,与容器扫描形成互补。

Secret Detection

密钥检测

Scans commits for accidentally committed credentials, API keys, tokens, and private keys using pattern matching and entropy analysis. Runs on every commit to prevent secrets from reaching the repository.
使用模式匹配和熵分析扫描提交内容,查找意外提交的凭据、API密钥、令牌和私钥。在每次提交时运行,防止密钥进入代码仓库。

Implementation

实现步骤

Complete Pipeline Configuration

完整流水线配置

yaml
undefined
yaml
undefined

.gitlab-ci.yml

.gitlab-ci.yml

stages:
  • build
  • test
  • security
  • deploy-staging
  • dast
  • deploy-production
variables: DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA SECURE_LOG_LEVEL: "info"
stages:
  • build
  • test
  • security
  • deploy-staging
  • dast
  • deploy-production
variables: DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA SECURE_LOG_LEVEL: "info"

Include GitLab managed security templates

Include GitLab managed security templates

include:
  • template: Security/SAST.gitlab-ci.yml
  • template: Security/Secret-Detection.gitlab-ci.yml
  • template: Security/Dependency-Scanning.gitlab-ci.yml
  • template: Security/Container-Scanning.gitlab-ci.yml
  • template: DAST.gitlab-ci.yml
  • template: Security/License-Scanning.gitlab-ci.yml
build: stage: build image: docker:24.0 services: - docker:24.0-dind variables: DOCKER_TLS_CERTDIR: "/certs" script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $DOCKER_IMAGE . - docker push $DOCKER_IMAGE rules: - if: $CI_COMMIT_BRANCH
unit-tests: stage: test image: $DOCKER_IMAGE script: - npm ci - npm run test:coverage coverage: '/Lines\s*:\s*(\d+.?\d*)%/' artifacts: reports: junit: junit-report.xml coverage_report: coverage_format: cobertura path: coverage/cobertura-coverage.xml
include:
  • template: Security/SAST.gitlab-ci.yml
  • template: Security/Secret-Detection.gitlab-ci.yml
  • template: Security/Dependency-Scanning.gitlab-ci.yml
  • template: Security/Container-Scanning.gitlab-ci.yml
  • template: DAST.gitlab-ci.yml
  • template: Security/License-Scanning.gitlab-ci.yml
build: stage: build image: docker:24.0 services: - docker:24.0-dind variables: DOCKER_TLS_CERTDIR: "/certs" script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $DOCKER_IMAGE . - docker push $DOCKER_IMAGE rules: - if: $CI_COMMIT_BRANCH
unit-tests: stage: test image: $DOCKER_IMAGE script: - npm ci - npm run test:coverage coverage: '/Lines\s*:\s*(\d+.?\d*)%/' artifacts: reports: junit: junit-report.xml coverage_report: coverage_format: cobertura path: coverage/cobertura-coverage.xml

Override SAST to run in security stage

Override SAST to run in security stage

sast: stage: security variables: SAST_EXCLUDED_PATHS: "spec,test,tests,tmp,node_modules" SEARCH_MAX_DEPTH: 10
sast: stage: security variables: SAST_EXCLUDED_PATHS: "spec,test,tests,tmp,node_modules" SEARCH_MAX_DEPTH: 10

Override container scanning

Override container scanning

container_scanning: stage: security variables: CS_IMAGE: $DOCKER_IMAGE CS_SEVERITY_THRESHOLD: "HIGH"
container_scanning: stage: security variables: CS_IMAGE: $DOCKER_IMAGE CS_SEVERITY_THRESHOLD: "HIGH"

Override dependency scanning

Override dependency scanning

dependency_scanning: stage: security
dependency_scanning: stage: security

Override secret detection

Override secret detection

secret_detection: stage: security
secret_detection: stage: security

License compliance scanning

License compliance scanning

license_scanning: stage: security
deploy-staging: stage: deploy-staging image: bitnami/kubectl:latest script: - kubectl set image deployment/app app=$DOCKER_IMAGE -n staging - kubectl rollout status deployment/app -n staging --timeout=300s environment: name: staging url: https://staging.example.com rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
license_scanning: stage: security
deploy-staging: stage: deploy-staging image: bitnami/kubectl:latest script: - kubectl set image deployment/app app=$DOCKER_IMAGE -n staging - kubectl rollout status deployment/app -n staging --timeout=300s environment: name: staging url: https://staging.example.com rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

DAST runs against deployed staging

DAST runs against deployed staging

dast: stage: dast variables: DAST_WEBSITE: https://staging.example.com DAST_FULL_SCAN_ENABLED: "true" DAST_BROWSER_SCAN: "true" needs: - deploy-staging rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy-production: stage: deploy-production image: bitnami/kubectl:latest script: - kubectl set image deployment/app app=$DOCKER_IMAGE -n production - kubectl rollout status deployment/app -n production --timeout=300s environment: name: production url: https://app.example.com when: manual rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
undefined
dast: stage: dast variables: DAST_WEBSITE: https://staging.example.com DAST_FULL_SCAN_ENABLED: "true" DAST_BROWSER_SCAN: "true" needs: - deploy-staging rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy-production: stage: deploy-production image: bitnami/kubectl:latest script: - kubectl set image deployment/app app=$DOCKER_IMAGE -n production - kubectl rollout status deployment/app -n production --timeout=300s environment: name: production url: https://app.example.com when: manual rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
undefined

Security Approval Policies

安全审批策略

Configure scan execution policies to enforce mandatory security scans:
  1. Navigate to Security & Compliance > Policies
  2. Create a "Scan Execution Policy" requiring SAST and secret detection on all branches
  3. Create a "Merge Request Approval Policy" requiring security team approval when critical vulnerabilities are detected
配置扫描执行策略以强制实施必需的安全扫描:
  1. 导航至“安全与合规 > 策略”
  2. 创建“扫描执行策略”,要求所有分支运行SAST和密钥检测
  3. 创建“合并请求审批策略”,当检测到严重漏洞时,要求安全团队审批

Custom SAST Ruleset Configuration

自定义SAST规则集配置

Create
.gitlab/sast-ruleset.toml
to customize analyzer behavior:
toml
[semgrep]
  [[semgrep.ruleset]]
    dirs = ["src"]

  [[semgrep.passthrough]]
    type = "url"
    target = "/sgrep-rules/custom-rules.yml"
    value = "https://semgrep.dev/p/owasp-top-ten"

  [[semgrep.passthrough]]
    type = "url"
    target = "/sgrep-rules/java-rules.yml"
    value = "https://semgrep.dev/p/java"
创建
.gitlab/sast-ruleset.toml
以自定义分析器行为:
toml
[semgrep]
  [[semgrep.ruleset]]
    dirs = ["src"]

  [[semgrep.passthrough]]
    type = "url"
    target = "/sgrep-rules/custom-rules.yml"
    value = "https://semgrep.dev/p/owasp-top-ten"

  [[semgrep.passthrough]]
    type = "url"
    target = "/sgrep-rules/java-rules.yml"
    value = "https://semgrep.dev/p/java"

Security Dashboard and Vulnerability Management

安全仪表板与漏洞管理

Vulnerability Report

漏洞报告

GitLab consolidates all scanner findings into a single Vulnerability Report accessible at Security & Compliance > Vulnerability Report. Each vulnerability includes:
  • Severity rating (Critical, High, Medium, Low, Info)
  • Scanner source (SAST, DAST, Container, Dependency, Secret)
  • Location in source code or image layer
  • Remediation guidance and suggested fixes
  • Status tracking (Detected, Confirmed, Dismissed, Resolved)
GitLab将所有扫描器的发现整合到一个统一的漏洞报告中,可通过“安全与合规 > 漏洞报告”访问。每个漏洞包含:
  • 严重等级(Critical、High、Medium、Low、Info)
  • 扫描器来源(SAST、DAST、容器、依赖项、密钥)
  • 在源代码或镜像层中的位置
  • 修复指南和建议修复方案
  • 状态跟踪(已检测、已确认、已驳回、已解决)

Merge Request Security Widget

合并请求安全小部件

Every merge request displays a security scanning widget showing:
  • New vulnerabilities introduced by the MR
  • Fixed vulnerabilities resolved by the MR
  • Comparison against the target branch baseline
每个合并请求都会显示一个安全扫描小部件,展示:
  • 该MR引入的新漏洞
  • 该MR修复的已解决漏洞
  • 与目标分支基线的对比

Pipeline Optimization

流水线优化

  • Parallel execution: Security scanners run concurrently in the security stage
  • Caching: Use CI cache for dependency downloads to speed up scanning
  • Incremental scanning: SAST can scan only changed files using
    SAST_INCREMENTAL: "true"
  • Fail conditions: Set
    allow_failure: false
    on critical scanners to enforce quality gates
  • 并行执行:安全扫描器在安全阶段并发运行
  • 缓存:使用CI缓存存储依赖项下载内容,加快扫描速度
  • 增量扫描:SAST可使用
    SAST_INCREMENTAL: "true"
    仅扫描变更的文件
  • 失败条件:为关键扫描器设置
    allow_failure: false
    以实施质量门控

Monitoring and Metrics

监控与指标

MetricDescriptionTarget
Pipeline security coveragePercentage of projects with all scanners enabled> 95%
Critical vulnerability MTTRTime from detection to resolution for critical findings< 48 hours
False positive ratePercentage of dismissed-as-false-positive findings< 15%
Secret detection block ratePercentage of secret commits blocked by push rules> 99%
指标描述目标
流水线安全覆盖率启用所有扫描器的项目占比> 95%
严重漏洞平均修复时间从检测到解决严重漏洞的时间< 48小时
误报率被驳回为误报的发现占比< 15%
密钥检测拦截率被推送规则拦截的密钥提交占比> 99%

References

参考资料