Help us learn about your current experience with the documentation. Take the survey.

流水线执行策略

  • Tier: Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

使用流水线执行策略,通过单一配置管理并强制执行多个项目的 CI/CD 作业。

Schema

包含流水线执行策略的 YAML 文件,其结构是在 pipeline_execution_policy 键下嵌套一组符合流水线执行策略 schema 的对象数组。每个安全策略项目下最多可配置五个策略。超出前五个配置的策略将不会被应用。

保存新策略时,GitLab 会根据 此 JSON schema 验证其内容。如果您不熟悉如何阅读 JSON schemas,以下章节和表格提供了替代说明。

字段 类型 必需 描述
pipeline_execution_policy 流水线执行策略的 array true 流水线执行策略列表(最多五个)

pipeline_execution_policy schema

字段 类型 必需 描述
name string true 策略名称。最多 255 个字符。
description (可选) string true 策略描述。
enabled boolean true 启用 (true) 或禁用 (false) 策略的标志。
content contentobject true 引用注入到项目流水线中的 CI/CD 配置。
pipeline_config_strategy string false 可为 inject_policyinject_ci(已弃用)或 override_project_ci。更多信息请参见 流水线策略
policy_scope policy_scopeobject false 根据您指定的项目、组或合规框架标签限定策略范围。
suffix string false 可为 on_conflict(默认)或 never。定义处理作业命名冲突的行为。on_conflict 对会破坏唯一性的作业名称应用唯一后缀。never 会导致流水线失败,如果项目及所有适用策略中的作业名称不唯一。
skip_ci skip_ciobject false 定义用户是否可应用 skip-ci 指令。默认情况下,skip-ci 被忽略,因此带有流水线执行策略的流水线无法被跳过。
variables_override variables_overrideobject false 控制用户是否可覆盖策略变量的行为。默认情况下,策略变量以最高优先级强制执行,用户无法覆盖它们。

注意以下事项:

  • 触发流水线的用户必须对流水线执行策略中指定的流水线执行文件具有至少读取权限,否则流水线不会启动。
  • 如果流水线执行文件被删除或重命名,强制执行该策略的项目中的流水线可能停止工作。
  • 流水线执行策略作业可分配给以下两个保留阶段之一:
    • .pipeline-policy-pre:在流水线开始时,位于 .pre 阶段之前。
    • .pipeline-policy-post:在流水线结束时,位于 .post 阶段之后。
  • 在任何保留阶段注入作业都能保证始终生效。执行策略作业也可分配给任何标准(build、test、deploy)或用户声明的阶段。但在此情况下,作业可能根据项目流水线配置被忽略。
  • 无法在流水线执行策略之外将作业分配给保留阶段。
  • 为流水线执行策略选择唯一的作业名称。某些 CI/CD 配置基于作业名称,如果同一流水线中存在多个同名作业,可能导致意外结果。例如,needs 关键字使一个作业依赖于另一个作业。如果有多个名为 example 的作业,一个 needs example 作业名称的作业会随机仅依赖于其中一个 example 作业实例。
  • 即使项目缺少 CI/CD 配置文件,流水线执行策略仍然有效。
  • 策略的顺序对应用的后缀有影响。
  • 如果应用于某个项目的任何策略具有 suffix: never,且流水线中已存在同名作业,则流水线会失败。
  • 流水线执行策略在所有分支和流水线源上强制执行。您可以使用 工作流规则 控制何时强制执行流水线执行策略。

.pipeline-policy-pre 阶段

.pipeline-policy-pre 阶段中的作业始终执行。此阶段专为安全和合规用例设计。.pipeline-policy-pre 阶段完成前,流水线中的作业不会开始。

如果您的 workflow 不需要此行为,可改用 .pre 阶段或自定义阶段。

确保 .pipeline-policy-pre 成功

  • 状态:实验性功能

此功能为实验性功能,未来版本可能变更。仅在非生产环境中彻底测试,因为生产环境中可能不稳定。

为确保 .pipeline-policy-pre 完成并成功,请在安全策略配置中启用 ensure_pipeline_policy_pre_succeeds 实验。.gitlab/security-policies/policy.yml YAML 配置文件存储在您的安全策略项目中:

experiments:
  ensure_pipeline_policy_pre_succeeds:
    enabled: true

如果 .pipeline-policy-pre 阶段失败或该阶段的所有作业被跳过,则后续阶段的所有作业(包括具有 needs: []when: always 的作业)均被跳过。

当多个流水线执行策略适用时,如果其中任何策略启用了该实验,则实验生效,确保 .pipeline-policy-pre 必须成功。

作业命名最佳实践

没有可见指标表明作业是由安全策略生成的。为便于识别策略创建的作业并避免作业名称冲突,请在作业名称中添加唯一前缀或后缀。

示例:

  • 使用:policy1:deployments:sast。此名称在所有其他策略和项目中很可能是唯一的。
  • 不要使用:sast。此名称在其他策略和项目中很可能重复。

流水线执行策略根据 suffix 属性处理命名冲突。如果存在多个同名作业:

  • 使用 on_conflict(默认),如果作业名称与流水线中的其他作业冲突,则添加后缀。
  • 使用 never,冲突时不添加后缀,流水线失败。

后缀基于作业合并到主流水线的顺序添加。

顺序如下:

  1. 项目流水线作业
  2. 项目策略作业(如适用)
  3. 组策略作业(如适用,按层次结构排序,最顶层的组最后应用)

应用的后缀格式为:

:policy-<security-policy-project-id>-<policy-index>

示例结果作业:sast:policy-123456-0

如果同一安全策略项目中的多个策略定义了相同的作业名称,则数字后缀对应冲突策略的索引。

示例结果作业:

  • sast:policy-123456-0
  • sast:policy-123456-1

作业阶段最佳实践

流水线执行策略中定义的作业可使用项目 CI/CD 配置中定义的任何 stage,包括保留阶段 .pipeline-policy-pre.pipeline-policy-post

如果您的策略仅包含 .pre.post 阶段的作业,则该策略的流水线被视为 empty。它不会与项目的流水线合并。

要在流水线执行策略中使用 .pre.post 阶段,必须包含至少一个在其他阶段运行的作业。例如:.pipeline-policy-pre

当您使用 inject_policy 流水线策略 时,如果目标项目不包含自己的 .gitlab-ci.yml 文件,则所有策略阶段都会注入到流水线中。

当您使用(已弃用的)inject_ci 流水线策略 时,如果目标项目不包含自己的 .gitlab-ci.yml 文件,则可用的阶段仅为默认流水线阶段和保留阶段。

当您强制执行流水线执行策略时,如果项目包含您无权修改的 CI/CD 配置,应在 .pipeline-policy-pre.pipeline-policy-post 阶段定义作业。这些阶段始终可用,不受任何项目 CI/CD 配置影响。

当您使用 override_project_ci 流水线策略 且包含多个流水线执行策略和自定义阶段时,阶段必须以相同的相对顺序定义才能相互兼容:

有效配置示例:

  - override-policy-1 stages: [build, test, policy-test, deploy]
  - override-policy-2 stages: [test, deploy]

无效配置示例:

  - override-policy-1 stages: [build, test, policy-test, deploy]
  - override-policy-2 stages: [deploy, test]

如果一个或多个 override_project_ci 策略具有无效的 stages 配置,流水线将失败。

content 类型

字段 类型 必需 描述
project string true 同一 GitLab 实例上项目的完整 GitLab 项目路径。
file string true 相对于根目录 (/) 的完整文件路径。YAML 文件必须具有 .yml.yaml 扩展名。
ref string false 获取文件的 ref。未指定时默认为项目的 HEAD。

在策略中使用 content 类型引用存储在另一个仓库中的 CI/CD 配置。这允许您在多个策略中重用相同的 CI/CD 配置,减少维护这些配置的开销。例如,如果您想在策略 A 和策略 B 中强制执行自定义密钥检测 CI/CD 配置,可以创建单个 YAML 配置文件并在两个策略中引用该配置。

先决条件:

  • 在强制执行包含 content 类型的策略的项目中触发流水线的用户,必须对包含 CI/CD 配置的项目具有至少只读权限。
  • 在强制执行流水线执行策略的项目中,用户必须对包含 CI/CD 配置的项目具有至少只读权限才能触发流水线。

在 GitLab 17.4 及更高版本中,您可以使用 content 类型为安全策略项目中的 CI/CD 配置文件授予所需的只读权限。为此,请在安全策略项目的常规设置中启用 Pipeline execution policies 设置。启用此设置会授予触发流水线的用户读取由流水线执行策略强制执行的 CI/CD 配置文件的权限。此设置不会授予用户访问存储配置文件的项目其他部分的权限。更多详细信息,请参见 自动授予访问权限

skip_ci 类型

流水线执行策略提供对谁可以使用 [skip ci] 指令的控制。您可以指定允许使用 [skip ci] 的特定用户或服务账户,同时确保执行关键安全和合规检查。

使用 skip_ci 关键字指定用户是否允许应用 skip_ci 指令跳过流水线。当未指定该关键字时,skip_ci 指令被忽略,防止所有用户绕过流水线执行策略。

字段 类型 可能值 描述
allowed boolean true, false 允许 (true) 或阻止 (false) 对具有强制执行流水线执行策略的流水线使用 skip-ci 指令的标志。
allowlist object users 指定始终允许使用 skip-ci 指令的用户,无论 allowed 标志为何。使用 users: 后跟包含代表用户 ID 的 id 键的对象数组。

variables_override 类型

字段 类型 可能值 描述
allowed boolean true, false true 时,其他配置可覆盖策略变量。当 false 时,其他配置无法覆盖策略变量。
exceptions array stringarray 对全局规则的例外。当 allowed: false 时,exceptions 是允许列表。当 allowed: true 时,exceptions 是拒绝列表。

此选项控制如何处理具有强制执行策略的流水线中的用户定义变量。此功能允许您:

  • 默认拒绝用户定义变量(推荐),提供更强的安全性,但要求您将所有应可自定义的变量添加到 exceptions 允许列表中。
  • 默认允许用户定义变量,提供更大的灵活性但安全性较低,因为您必须将对策略执行有影响的变量添加到 exceptions 拒绝列表中。
  • 定义对 allowed 全局规则的例外。

用户定义变量可能影响流水线中任何策略作业的行为,并可能来自各种来源:

当未指定 variables_override 选项时,保持“最高优先级”行为。有关此行为的更多信息,请参见 流水线执行策略中的变量优先级

当流水线执行策略控制变量优先级时,作业日志中包含配置的 variables_override 选项和策略名称。要查看这些日志,gitlab-runner 必须更新到 18.1 或更高版本。

示例 variables_override 配置

variables_override 选项添加到您的流水线执行策略配置中:

pipeline_execution_policy:
  - name: Security Scans
    description: '强制执行安全扫描'
    enabled: true
    pipeline_config_strategy: inject_policy
    content:
      include:
        - project: gitlab-org/security-policies
          file: security-scans.yml
    variables_override:
      allowed: false
      exceptions:
        - CS_IMAGE
        - SAST_EXCLUDED_ANALYZERS
强制执行安全扫描同时允许容器自定义(允许列表方法)

要强制执行安全扫描但允许项目团队指定自己的容器镜像:

variables_override:
  allowed: false
  exceptions:
    - CS_IMAGE

此配置阻止所有用户定义的变量,除了 CS_IMAGE,确保安全扫描无法被禁用,同时允许团队自定义容器镜像。

防止特定安全变量覆盖(拒绝列表方法)

要允许大多数变量,但防止禁用安全扫描:

variables_override:
  allowed: true
  exceptions:
    - SECRET_DETECTION_DISABLED
    - SAST_DISABLED
    - DEPENDENCY_SCANNING_DISABLED
    - DAST_DISABLED
    - CONTAINER_SCANNING_DISABLED

此配置允许所有用户定义的变量,但那些可能禁用安全扫描的变量除外。

虽然此配置可提供灵活性,但由于安全影响,不建议使用。任何未在 exceptions 中明确列出的变量都可能被用户注入。因此,策略配置的安全性不如使用 allowlist 方法时高。

policy scope schema

要自定义策略强制执行,您可以定义策略的范围以包含或排除指定的项目、组或合规框架标签。更多详细信息,请参见 范围

管理 CI/CD 配置的访问权限

当您在项目上强制执行流水线执行策略时,触发流水线的用户必须对包含策略 CI/CD 配置的项目具有至少只读权限。您可以手动或自动授予对项目的访问权限。

手动授予访问权限

要允许用户或组运行具有强制执行流水线执行策略的流水线,您可以邀请他们加入包含策略 CI/CD 配置的项目。

自动授予访问权限

您可以自动授予对策略 CI/CD 配置的访问权限,供所有在具有强制执行流水线执行策略的项目中运行流水线的用户使用。

先决条件:

  • 确保流水线执行策略 CI/CD 配置存储在安全策略项目中。
  • 在安全策略项目的常规设置中,启用 Pipeline execution policies 设置。

如果您还没有安全策略项目,并希望创建第一个流水线执行策略,请创建一个空项目并将其链接为安全策略项目。 要链接项目:

  1. 在您要强制执行策略的组或项目中,选择 Secure > Policies > Edit policy project
  2. 选择安全策略项目。

该项目成为安全策略项目,并且该设置变为可用。

要使用 $CI_JOB_TOKEN 创建下游流水线,您需要确保项目和组有权请求安全策略项目。 在安全策略项目中,转到 Settings > CI/CD > Job token permissions 并将授权的组和项目添加到允许列表中。 如果看不到 CI/CD 设置,请转到 Settings > General > Visibility, project features, permissions 并启用 CI/CD

配置

  1. 在策略项目中,选择 Settings > General > Visibility, project features, permissions

  2. 启用设置 Pipeline execution policies: Grant access to the CI/CD configurations for projects linked to this security policy project as the source for security policies

  3. 在策略项目中,为策略 CI/CD 配置创建文件。

    # policy-ci.yml
    
    policy-job:
      script: ...
  4. 在您要强制执行策略的组或项目中,创建一个流水线执行策略,并指定安全策略项目的 CI/CD 配置文件。

    pipeline_execution_policy:
    - name: My pipeline execution policy
      description: Enforces CI/CD jobs
      enabled: true
      pipeline_config_strategy: inject_policy
      content:
        include:
        - project: my-group/my-security-policy-project
          file: policy-ci.yml

流水线配置策略

流水线配置策略定义了将策略配置与项目流水线合并的方法。流水线执行策略在隔离的流水线中执行 .gitlab-ci.yml 文件中定义的作业,这些作业被合并到目标项目的流水线中。

inject_policy 类型

此策略将自定义 CI/CD 配置添加到现有项目流水线中,而不完全替换项目的原始 CI/CD 配置。当您希望使用附加步骤(如添加新的安全扫描、合规检查或自定义脚本)来增强或扩展当前流水线时,此策略非常适用。

与已弃用的 inject_ci 策略不同,inject_policy 允许您将自定义策略阶段注入到流水线中,让您对 CI/CD workflow 中策略规则的应用位置进行更精细的控制。

如果启用了多个策略,此策略会注入每个策略中的所有作业。

使用此策略时,项目 CI/CD 配置无法覆盖策略流水线中定义的任何行为,因为每个流水线都有独立的 YAML 配置。

对于没有 .gitlab-ci.yml 文件的项目,此策略隐式创建 .gitlab-ci.yml 文件。执行的流水线仅包含流水线执行策略中定义的作业。

当流水线执行策略使用阻止策略作业运行的工作流规则时,唯一运行的作业是项目的 CI/CD 作业。如果项目使用阻止项目 CI/CD 作业运行的工作流规则,唯一运行的作业是流水线执行策略作业。

阶段注入

策略流水线的阶段遵循标准的 CI/CD 配置。您通过提供自定义阶段之前和之后的阶段来定义自定义策略阶段注入到项目流水线中的顺序。

项目和策略流水线阶段表示为有向无环图 (DAG),其中节点是阶段,边代表依赖关系。当您合并流水线时,各个 DAG 会合并为单个更大的 DAG。之后,执行拓扑排序,确定所有流水线中阶段应执行的顺序。此排序确保在最终顺序中尊重所有依赖关系。 如果存在冲突的依赖关系,流水线将无法运行。要修复依赖关系,请确保项目和策略中使用的阶段保持一致。

如果策略流水线配置中未明确定义阶段,流水线将使用默认阶段 stages: [build, test, deploy]。如果包含这些阶段但顺序不同,流水线将因 Cyclic dependencies detected when enforcing policies 错误而失败。

以下示例演示了此行为。所有示例均假设以下项目 CI/CD 配置:

# .gitlab-ci.yml
stages: [build, test, deploy]

project-build-job:
  stage: build
  script: ...

project-test-job:
  stage: test
  script: ...

project-deploy-job:
  stage: deploy
  script: ...
示例 1
# policy-ci.yml
stages: [test, policy-stage, deploy]

policy-job:
  stage: policy-stage
  script: ...

在此示例中,policy-stage 阶段:

  • 如果存在 test 阶段,必须在其后注入。
  • 如果存在 deploy 阶段,必须在其前注入。

结果:流水线包含以下阶段:[build, test, policy-stage, deploy]

特殊情况:

  • 如果 .gitlab-ci.yml 指定阶段为 [build, deploy, test],流水线将因 Cyclic dependencies detected when enforcing policies 错误而失败,因为约束无法满足。要修复失败,请调整项目配置以使阶段与策略保持一致。
  • 如果 .gitlab-ci.yml 指定阶段为 [build],则结果流水线具有以下阶段:[build, policy-stage]
示例 2
# policy-ci.yml
stages: [policy-stage, deploy]

policy-job:
  stage: policy-stage
  script: ...

在此示例中,policy-stage 阶段:

  • 如果存在 deploy 阶段,必须在其前注入。

结果:流水线包含以下阶段:[build, test, policy-stage, deploy]

特殊情况:

  • 如果 .gitlab-ci.yml 指定阶段为 [build, deploy, test],则结果流水线阶段为:[build, policy-stage, deploy, test]
  • 如果项目流水线中没有 deploy 阶段,policy-stage 阶段将在流水线末尾注入,紧邻 .pipeline-policy-post
示例 3
# policy-ci.yml
stages: [test, policy-stage]

policy-job:
  stage: policy-stage
  script: ...

在此示例中,policy-stage 阶段:

  • 如果存在 test 阶段,必须在其后注入。

结果:流水线包含以下阶段:[build, test, deploy, policy-stage]

特殊情况:

  • 如果项目流水线中没有 test 阶段,policy-stage 阶段将在流水线末尾注入,紧邻 .pipeline-policy-post
示例 4
# policy-ci.yml
stages: [policy-stage]

policy-job:
  stage: policy-stage
  script: ...

在此示例中,policy-stage 阶段没有约束。

结果:流水线包含以下阶段:[build, test, deploy, policy-stage]

示例 5
# policy-ci.yml
stages: [check, lint, test, policy-stage, deploy, verify, publish]

policy-job:
  stage: policy-stage
  script: ...

在此示例中,policy-stage 阶段:

  • 如果存在阶段 checklinttest,必须在其后注入。
  • 如果存在阶段 deployverifypublish,必须在其前注入。

结果:流水线包含以下阶段:[build, test, policy-stage, deploy]

特殊情况:

  • 如果 .gitlab-ci.yml 指定阶段为 [check, publish],则结果流水线具有以下阶段:[check, policy-stage, publish]

inject_ci (已弃用)

此功能已在 GitLab 17.9 中弃用。请使用 inject_policy,因为它支持强制执行自定义策略阶段。

此策略将自定义 CI/CD 配置添加到现有项目流水线中,而不完全替换项目的原始 CI/CD 配置。当您希望使用附加步骤(如添加新的安全扫描、合规检查或自定义脚本)来增强或扩展当前流水线时,此策略非常适用。

启用多个策略会以累加方式注入所有作业。

使用此策略时,项目 CI/CD 配置无法覆盖策略流水线中定义的任何行为,因为每个流水线都有独立的 YAML 配置。

对于没有 .gitlab-ci.yml 文件的项目,此策略隐式创建 .gitlab-ci.yml 文件。这允许执行仅包含流水线执行策略中定义的作业的流水线。

当流水线执行策略使用阻止策略作业运行的工作流规则时,唯一运行的作业是项目的 CI/CD 作业。如果项目使用阻止项目 CI/CD 作业运行的工作流规则,唯一运行的作业是流水线执行策略作业。

override_project_ci

此策略用流水线执行策略定义的新配置替换项目现有的 CI/CD 配置。当您需要标准化或替换整个流水线时(例如,在高度管制的行业中强制执行组织范围的 CI/CD 标准或合规要求),此策略非常理想。要覆盖流水线配置,请定义 CI/CD 作业且不要使用 include:project

此策略优先于使用 inject_ciinject_policy 策略的其他策略。如果应用了具有 override_project_ci 的策略,项目 CI/CD 配置将被忽略。但是,其他安全策略配置不会被覆盖。

当您在流水线执行策略中将 override_project_ci 与扫描执行策略一起使用时,CI/CD 配置会合并,并且两个策略都应用于结果流水线。

或者,您可以将项目的 CI/CD 配置与项目的 .gitlab-ci.yml 合并而不是覆盖它。要合并配置,请使用 include:project。此策略允许用户将项目 CI/CD 配置包含在流水线执行策略配置中,使用户能够自定义策略作业。例如,他们可以将策略和项目 CI/CD 配置合并到一个 YAML 文件中,以覆盖 before_script 配置或定义必需的变量(如 CS_IMAGE)来定义要扫描的容器的必需路径。这是此行为的简短演示。 下图说明了项目级别和策略级别定义的变量如何在结果流水线中被选择:

%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TB

classDef yaml text-align:left

ActualPolicyYAML["<pre>
variables:
  MY_VAR: 'policy'
policy-job:
  stage: test
</pre>"]

class ActualPolicyYAML yaml

ActualProjectYAML["<pre>
variables:
  MY_VAR: 'project'
project-job:
  stage: test
</pre>"]

class ActualProjectYAML yaml

PolicyVariablesYAML["<pre>
variables:
  MY_VAR: 'policy'
</pre>"]

class PolicyVariablesYAML yaml

ProjectVariablesYAML["<pre>
variables:
  MY_VAR: 'project'
</pre>"]

class ProjectVariablesYAML yaml

ResultingPolicyVariablesYAML["<pre>
variables:
  MY_VAR: 'policy'
</pre>"]

class ResultingPolicyVariablesYAML yaml

ResultingProjectVariablesYAML["<pre>
variables:
  MY_VAR: 'project'
</pre>"]

class ResultingProjectVariablesYAML yaml

PolicyCiYAML(Policy CI YAML) --> ActualPolicyYAML
ProjectCiYAML(<code>.gitlab-ci.yml</code>) --> ActualProjectYAML

subgraph "Policy Pipeline"
  subgraph "Test stage"
    subgraph "<code>policy-job</code>"
      PolicyVariablesYAML
    end
  end
end

subgraph "Project Pipeline"
  subgraph "Test stage"
    subgraph "<code>project-job</code>"
      ProjectVariablesYAML
    end
  end
end

ActualPolicyYAML -- "Used as source" --> PolicyVariablesYAML
ActualProjectYAML -- "Used as source" --> ProjectVariablesYAML

subgraph "Resulting Pipeline"
  subgraph "Test stage"
    subgraph "<code>policy-job</code> "
      ResultingPolicyVariablesYAML
    end

    subgraph "<code>project-job</code> "
      ResultingProjectVariablesYAML
    end
  end
end

PolicyVariablesYAML -- "Inject <code>policy-job</code> if Test Stage exists" --> ResultingPolicyVariablesYAML
ProjectVariablesYAML -- "Basis of the resulting pipeline" --> ResultingProjectVariablesYAML

流水线执行策略中的工作流规则会覆盖项目的原始 CI/CD 配置。通过在策略中定义工作流规则,您可以设置在所有链接项目中强制执行的规则,例如防止使用分支流水线。

将项目的 CI/CD 配置包含在流水线执行策略配置中

当您使用 override_project_ci 策略时,项目配置可以包含在流水线执行策略配置中:

include:
  - project: $CI_PROJECT_PATH
    ref: $CI_COMMIT_SHA
    file: $CI_CONFIG_PATH
    rules:
      - exists:
          paths:
            - '$CI_CONFIG_PATH'
          project: '$CI_PROJECT_PATH'
          ref: '$CI_COMMIT_SHA'

compliance_job:
 ...

CI/CD 变量

不要将敏感信息或凭据存储在变量中,因为它们作为明文策略配置的一部分存储在 Git 仓库中。

流水线执行作业在隔离环境中执行。在另一个策略或项目的 .gitlab-ci.yml 文件中定义的变量在流水线执行策略中不可用,并且无法从外部覆盖,除非 variables_override 类型 允许。

可以使用组或项目设置与流水线执行策略共享变量,这些设置遵循标准的 CI/CD 变量优先级 规则。但是,当使用流水线执行策略时,优先级规则更复杂,因为它们可能取决于流水线执行策略策略:

  • inject_policy 策略:如果变量在流水线执行策略中定义,作业始终使用此值。如果变量未在流水线执行策略中定义,作业将应用组或项目设置中的值。
  • inject_ci 策略:如果变量在流水线执行策略中定义,作业始终使用此值。如果变量未在流水线执行策略中定义,作业将应用组或项目设置中的值。
  • override_project_ci 策略:结果流水线中的所有作业都被视为策略作业。策略中定义的变量(包括包含文件中的变量)优先于项目和组变量。这意味着包含项目中 CI/CD 配置的作业中的变量优先于项目和组设置中定义的变量。

有关流水线执行策略中变量的更多详细信息,请参见 流水线执行策略中的变量优先级

您可以在 UI 中定义项目或组变量

流水线执行策略中的变量优先级

当您使用流水线执行策略时,特别是使用 override_project_ci 策略时,在多个位置定义的变量值的优先级可能与标准的 GitLab CI/CD 流水线不同。以下是一些需要理解的重要点:

  • 使用 override_project_ci 时,结果流水线中的所有作业(包括来自包含项目的 CI/CD 配置的作业)都被视为策略作业。
  • 在策略流水线中定义的变量(针对整个实例或作业)优先于在项目或组设置中定义的变量。
  • 此行为适用于所有作业,包括来自项目 CI/CD 配置文件(.gitlab-ci.yml)的作业。

示例

如果项目 CI/CD 配置中的变量和包含的 .gitlab-ci.yml 文件中定义的作业变量具有相同名称,则在使用 override_project_ci 时,作业变量优先。

在项目的 CI/CD 设置中定义了 MY_VAR 变量:

  • 键:MY_VAR
  • 值:Project configuration variable value

在包含项目的 .gitlab-ci.yml 中,定义了同名变量:

project-job:
  variables:
    MY_VAR: "Project job variable value"
  script:
    - echo $MY_VAR  # This will output "Project job variable value"

在这种情况下,作业变量值 Project job variable value 优先。

[skip ci] 的行为

默认情况下,为防止常规流水线触发,用户可以将带有 [skip ci] 的提交推送到受保护分支。但是,使用流水线执行策略定义的作业始终会触发,因为策略会忽略 [skip ci] 指令。这可以防止开发人员跳过策略中定义的作业的执行,确保始终执行关键安全和合规检查。

有关 [skip ci] 行为的更灵活控制,请参见 skip_ci 类型 部分。

示例

这些示例展示了您可以使用流水线执行策略实现的功能。

流水线执行策略

您可以在存储在 安全策略项目 中的 .gitlab/security-policies/policy.yml 文件中使用以下示例:

---
pipeline_execution_policy:
- name: My pipeline execution policy
  description: Enforces CI/CD jobs
  enabled: true
  pipeline_config_strategy: override_project_ci
  content:
    include:
    - project: my-group/pipeline-execution-ci-project
      file: policy-ci.yml
      ref: main # optional
  policy_scope:
    projects:
      including:
      - id: 361

基于项目变量自定义强制执行的作业

您可以根据项目变量的存在自定义强制执行的作业。在此示例中,CS_IMAGE 的值在策略中定义为 alpine:latest。但是,如果项目也定义了 PROJECT_CS_IMAGE 的值,则使用该值。CI/CD 变量必须是预定义的项目变量,而不是在项目的 .gitlab-ci.yml 文件中定义的。

variables:
  CS_ANALYZER_IMAGE: "$CI_TEMPLATE_REGISTRY_HOST/security-products/container-scanning:8"
  CS_IMAGE: alpine:latest

policy::container-security:
  stage: .pipeline-policy-pre
  rules:
    - if: $PROJECT_CS_IMAGE
      variables:
        CS_IMAGE: $PROJECT_CS_IMAGE
    - when: always
  script:
    - echo "CS_ANALYZER_IMAGE:$CS_ANALYZER_IMAGE"
    - echo "CS_IMAGE:$CS_IMAGE"

使用 .gitlab-ci.yml 和制品自定义强制执行的作业

因为策略流水线在隔离环境中运行,流水线执行策略无法直接读取 .gitlab-ci.yml 中的变量。如果您想使用 .gitlab-ci.yml 中的变量而不是在项目的 CI/CD 配置中定义它们,可以使用制品将变量从 .gitlab-ci.yml 配置传递到流水线执行策略的流水线。

# .gitlab-ci.yml

build-job:
  stage: build
  script:
    - echo "BUILD_VARIABLE=value_from_build_job" >> build.env
  artifacts:
    reports:
      dotenv: build.env
stages:
- build
- test

test-job:
  stage: test
  script:
    - echo "$BUILD_VARIABLE" # Prints "value_from_build_job"

使用项目配置中的 before_script 自定义安全扫描器的行为

要自定义策略强制执行的作业在项目 .gitlab-ci.yml 中的行为,您可以覆盖 before_script。为此,请在策略中使用 override_project_ci 策略并包含项目的 CI/CD 配置。示例流水线执行策略配置:

# policy.yml
type: pipeline_execution_policy
name: Secret detection
description: >-
  This policy enforces secret detection and allows projects to override the
  behavior of the scanner.
enabled: true
pipeline_config_strategy: override_project_ci
content:
  include:
    - project: gitlab-org/pipeline-execution-policies/compliance-project
      file: secret-detection.yml
# secret-detection.yml
include:
  - project: $CI_PROJECT_PATH
    ref: $CI_COMMIT_SHA
    file: $CI_CONFIG_PATH
  - template: Jobs/Secret-Detection.gitlab-ci.yml

在项目的 .gitlab-ci.yml 中,您可以为扫描器定义 before_script

include:
  - template: Jobs/Secret-Detection.gitlab-ci.yml

secret_detection:
  before_script:
    - echo "Before secret detection"

通过使用 override_project_ci 并包含项目配置,允许 YAML 配置被合并。

配置特定资源的变量控制

您可以允许团队设置可覆盖流水线执行策略变量的全局变量,同时仍允许作业特定的覆盖。这允许团队为安全扫描设置适当的默认值,但为其他作业使用适当的资源。

在您的 resource-optimized-scans.yml 中包含:

variables:
  # Default resource settings for all jobs
  KUBERNETES_MEMORY_REQUEST: 4Gi
  KUBERNETES_MEMORY_LIMIT: 4Gi
  # Default values that teams can override via project variables
  SAST_KUBERNETES_MEMORY_REQUEST: 4Gi

sast:
  variables:
    SAST_EXCLUDED_ANALYZERS: 'spotbugs'
    KUBERNETES_MEMORY_REQUEST: $SAST_KUBERNETES_MEMORY_REQUEST
    KUBERNETES_MEMORY_LIMIT: $SAST_KUBERNETES_MEMORY_REQUEST

在您的 policy.yml 中包含:

pipeline_execution_policy:
- name: Resource-Optimized Security Policy
  description: Enforces security scans with efficient resource management
  enabled: true
  pipeline_config_strategy: inject_ci
  content:
    include:
    - project: security/policy-templates
      file: resource-optimized-scans.yml
      ref: main

  variables_override:
    allowed: false
    exceptions:
      # Allow scan-specific resource overrides
      - SAST_KUBERNETES_MEMORY_REQUEST
      - SECRET_DETECTION_KUBERNETES_MEMORY_REQUEST
      - CS_KUBERNETES_MEMORY_REQUEST
      # Allow necessary scan customization
      - CS_IMAGE
      - SAST_EXCLUDED_PATHS

这种方法允许团队使用变量覆盖设置扫描特定的资源变量(如 SAST_KUBERNETES_MEMORY_REQUEST),而不会影响其流水线中的所有作业,从而为大型项目提供更好的资源管理。此示例还展示了您可以扩展给开发人员的其他常见扫描自定义选项。请确保记录可用的变量,以便您的开发团队可以利用它们。

在流水线执行策略中使用组或项目变量

您可以在流水线执行策略中使用组或项目变量。

使用项目变量 PROJECT_VAR="I'm a project",以下流水线执行策略作业的结果为:I'm a project

pipeline execution policy job:
    stage: .pipeline-policy-pre
    script:
    - echo "$PROJECT_VAR"

使用流水线执行策略强制执行变量的值

在流水线执行策略中定义的变量的值会覆盖同名组或策略变量的值。在此示例中,变量 PROJECT_VAR 的项目值被覆盖,作业结果为:I'm a pipeline execution policy

variables:
  PROJECT_VAR: "I'm a pipeline execution policy"

pipeline execution policy job:
    stage: .pipeline-policy-pre
    script:
    - echo "$PROJECT_VAR"

带有安全策略范围的示例 policy.yml

在此示例中,安全策略的 policy_scope

  • 包含应用了 ID 为 9 的合规框架的任何项目。
  • 排除 ID 为 456 的项目。
pipeline_execution_policy:
- name: Pipeline execution policy
  description: ''
  enabled: true
  pipeline_config_strategy: inject_policy
  content:
    include:
    - project: my-group/pipeline-execution-ci-project
      file: policy-ci.yml
  policy_scope:
    compliance_frameworks:
    - id: 9
    projects:
      excluding:
      - id: 456

在流水线执行策略中配置 ci_skip

在以下示例中,强制执行流水线执行策略,并且 跳过 CI 被禁止,但用户 ID 为 75 的用户除外。

pipeline_execution_policy:
  - name: My pipeline execution policy with ci.skip exceptions
    description: 'Enforces CI/CD jobs'
    enabled: true
    pipeline_config_strategy: inject_policy
    content:
      include:
        - project: group-a/project1
          file: README.md
    skip_ci:
      allowed: false
      allowlist:
        users:
          - id: 75

配置 exists 条件

使用 exists 规则配置流水线执行策略,以便在存在特定文件时包含项目的 CI/CD 配置文件。

在以下示例中,如果存在 Dockerfile,流水线执行策略包含项目的 CI/CD 配置。您必须将 exists 规则设置为使用 '$CI_PROJECT_PATH' 作为 project,否则 GitLab 会在存储安全策略 CI/CD 配置的项目中评估文件是否存在。

include:
  - project: $CI_PROJECT_PATH
    ref: $CI_COMMIT_SHA
    file: $CI_CONFIG_PATH
    rules:
      - exists:
          paths:
            - 'Dockerfile'
          project: '$CI_PROJECT_PATH'

要使用此方法,组或项目必须使用 override_project_ci 策略。

使用流水线执行策略强制执行容器扫描 component

您可以使用安全扫描组件来改进版本控制和强制执行。

include:
  - component: gitlab.com/components/container-scanning/container-scanning@main
    inputs:
      cs_image: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

container_scanning: # override component with additional configuration
  variables:
    CS_REGISTRY_USER: $CI_REGISTRY_USER
    CS_REGISTRY_PASSWORD: $CI_REGISTRY_PASSWORD
    SECURE_LOG_LEVEL: debug # add for verbose debugging of the container scanner
  before_script:
  - echo $CS_IMAGE # optionally add a before_script for additional debugging