使用 Harbor Event Triggers

概述

Harbor Event Triggers 允许你通过 Harbor 的 Webhook 事件自动触发 Tekton pipelines。它支持多种事件类型,包括 artifact 推送、拉取、删除以及扫描完成,从而帮助你为 container images 和 OCI charts 构建完整的 CI/CD 自动化工作流。

核心特性

  • 多事件类型支持:支持多种 Harbor 事件,例如 Push Artifact、Pull Artifact、Delete Artifact 和 Scanning Completed。
  • 标准化触发绑定:提供标准化的 ClusterTriggerBindings,确保跨平台一致性。
  • 灵活的参数映射:自动从 Harbor 事件中提取关键信息作为 pipeline 参数。
  • 多 artifact 类型支持:同时支持 container images 和 OCI charts。

支持的事件类型

基本事件信息

所有输出变量都可用于 pipeline 参数映射。你可以使用 $(tt.params.<param name>) 访问参数值。

基本变量(适用于所有事件)

变量名描述示例值
event-type事件类型PUSH_ARTIFACT, PULL_ARTIFACT, DELETE_ARTIFACT, SCANNING_COMPLETED
occur-at事件发生时间1763369448
operator触发该事件的用户admin
repository-nameRepository 名称alpine
repository-namespaceRepository Namespacelibrary
repository-full-nameRepository 完整名称library/alpine
repository-typeRepository 类型public, private, chart
artifact-digestArtifact Digestsha256:c4975008127577bfc34169439e890db7cfb1cedccabe49c059c88f913cb27edd
artifact-tagArtifact Taglatest, v1.0.0(可选,如果 artifact 仅通过 digest 引用,则可能为空)
artifact-resource-urlArtifact 资源 URL192.168.0.117/library/alpine:latest
WARNING

处理可选字段:artifact-tag 字段是可选的,如果 artifact 仅通过 digest 引用,则 payload 中可能不存在该字段。repository-date-created 字段适用于 push 和 pull 事件,但不适用于 delete 和 scanning 事件。

重要:如果 TriggerBinding 中引用的字段可能在 payload 中缺失,则必须在 TriggerTemplate 中为该参数设置 default 值。否则,当字段缺失时,trigger 将失败。例如,如果 artifact-tag 可能缺失,请在 TriggerTemplate 的参数定义中添加 default: ""。

1. Push Artifact 事件

当 artifact(container image 或 OCI chart)被推送到 Harbor repository 时触发。适用于:

  • 自动化 image 构建和部署
  • Image 验证和测试
  • 自动 tagging 和版本管理
  • 多阶段构建 pipeline

Push Artifact 事件变量

变量名描述示例值
repository-date-createdRepository 创建时间1763369448

上面列出的所有基本变量也都可用。

2. Pull Artifact 事件

当 artifact 从 Harbor repository 被拉取时触发。适用于:

  • 使用情况跟踪和分析
  • 安全监控
  • 资源消耗跟踪
  • 部署验证

Pull Artifact 事件变量

变量名描述示例值
repository-date-createdRepository 创建时间1763369448

上面列出的所有基本变量也都可用。

3. Delete Artifact 事件

当 artifact 从 Harbor repository 中删除时触发。适用于:

  • 清理自动化
  • 审计日志
  • 资源管理
  • 合规性跟踪

Delete Artifact 事件变量

上面列出的所有基本变量都可用。请注意,repository-date-created 不适用于 delete 事件。

4. Scanning Completed 事件

当 artifact 的漏洞扫描完成时触发。适用于:

  • 安全策略执行
  • 自动安全检查
  • 漏洞报告
  • 自动修复工作流

Scanning Completed 事件变量

上面列出的所有基本变量都可用。请注意,repository-date-created 不适用于 scanning 事件。

WARNING

scan_overview 字段结构会因扫描类型(SBOM、漏洞检查)而异。该结构使用动态 MIME type key(例如 application/vnd.security.vulnerability.report; version=1.1),因此不能直接在 TriggerBindings 中使用 JSONPath 解析。如果你需要提取详细的扫描结果(例如漏洞数量、扫描状态),请考虑使用 CEL interceptors,或为不同的扫描类型创建单独的 bindings。

TIP

有关事件结构的更多细节,请参考 Harbor 官方 webhook 文档。

配置指南

处理可选字段

Harbor 事件中的某些字段可能是可选的,或者会根据事件类型或 artifact 的引用方式而缺失。例如:

  • artifact-tag:如果 artifact 仅通过 digest 引用,则可能缺失
  • repository-date-created:在 push 和 pull 事件中可用,但在 delete 和 scanning 事件中不可用

重要:当使用引用可选字段的 ClusterTriggerBindings 时,你必须在 TriggerTemplate 中为这些参数提供默认值。如果 payload 中缺少某个字段且未提供默认值,trigger 将因 JSONPath 解析错误而失败。

示例:要处理可选的 artifact-tag 字段,可按如下方式配置 TriggerTemplate:

spec:
  params:
    - name: artifact-tag
      default: ""  # 可选字段的空字符串默认值

这样可以确保当 Harbor 事件 payload 中缺少 tag 字段时,trigger 会使用空字符串,而不是失败。

前提条件

  1. 环境中已创建 EventListener,并且能够在目标 namespace 中处理 Trigger。更多信息请联系你的平台管理员。
  2. Harbor 可以访问上述 EventListener。
  3. 所需的 Pipeline 以及必要的运行配置已创建完成。
  4. 你有权限修改 Harbor project 的 Webhook 设置。

通过 Harbor UI 配置 Webhook

  1. 访问你的 Harbor project 设置。
  2. 导航到 Webhooks。
  3. 点击 New Webhook。
  4. 配置 webhook:
    • Name:输入一个描述性名称(例如 tekton-webhook)
    • Endpoint URL:输入 EventListener URL,例如:
      http://<your-eventlistener-url>
      或
      https://<your-eventlistener-url>
    • Auth Header:(可选)如有需要,配置认证 header。
    • Skip Certificate Verification:如果使用自签名证书,则启用此项。
  5. 按需选择事件类型:
    • Push Artifact:在 artifact 被推送时触发
    • Pull Artifact:在 artifact 被拉取时触发
    • Delete Artifact:在 artifact 被删除时触发
    • Scanning Completed:在漏洞扫描完成时触发
  6. 点击 Save。

Pipeline Trigger 配置示例

如果目标是通过 trigger 实现持续集成,并满足以下需求:

  • 当 image 被推送时,自动触发构建和部署。
  • 当扫描完成时,自动触发安全检查。
WARNING

事件类型过滤:如果你的 Harbor webhook 配置为发送多种事件类型(例如同时发送 Push Artifact 和 Pull Artifact),则必须在 Triggers 中配置 CEL interceptors 按类型过滤事件。如果没有 interceptor,所有配置的事件类型都会触发同一个 pipeline,这可能导致非预期执行。

例如,如果你的 webhook 将 PUSH_ARTIFACT 和 PULL_ARTIFACT 事件都发送到同一个 EventListener,并且你有一个不带 interceptor 的 Trigger,那么这两种事件都会触发 pipeline。请使用 interceptors 将不同的事件类型路由到不同的 Triggers 或 pipelines。

为简化本文档,我们假设 pipeline 已准备好,并提供以下参数:

参数名描述示例值
repository-full-name目标 pipeline 的 Repository 完整名称library/alpine
artifact-tagArtifact taglatest
artifact-digestArtifact digestsha256:c4975008127577bfc34169439e890db7cfb1cedccabe49c059c88f913cb27edd
TIP

请替换为你的实际 pipeline 信息。

信息描述
my-namespaceNamespace 名称
my-pipelinePipeline 名称
workspacesWorkspace 配置,请根据实际 pipeline 的 workspace 配置和要求进行修改

接下来,我们只需要配置下面两个 trigger:

创建 Push Artifact Trigger

将以下 YAML 保存为 harbor-push-trigger.yaml:

apiVersion: triggers.tekton.dev/v1beta1
kind: Trigger
metadata:
    name: my-pipeline-push   # 建议根据 pipeline 名称修改前缀
    namespace: my-namespace  # 改为实际 namespace
spec:
    bindings:
    - ref:
        kind: ClusterTriggerBinding
        name: harbor-push-artifact
    interceptors: # 仅过滤并处理 PUSH_ARTIFACT 事件
    - ref:
        kind: ClusterInterceptor
        name: cel
      params:
      - name: filter
        value: body.type == "PUSH_ARTIFACT"  # 仅在 push 事件时触发
    template:
      spec:
        params:
        - name: repository-full-name
        - name: artifact-tag
          default: ""  # 可选字段:如果 artifact 仅通过 digest 引用,则可能为空
        - name: artifact-digest
        resourcetemplates:
        - apiVersion: tekton.dev/v1
          kind: PipelineRun
          metadata:
              generateName: my-pipeline-push- # 建议根据 pipeline 名称修改前缀
          spec:
              pipelineRef:
                name: my-pipeline  # 改为实际 pipeline 名称
              params:
              - name: repository-full-name
                value: $(tt.params.repository-full-name)
              - name: artifact-tag
                value: $(tt.params.artifact-tag)
              - name: artifact-digest
                value: $(tt.params.artifact-digest)
              workspaces: # 需要根据 pipeline 要求和环境配置修改 workspaces
              - name: output
                emptyDir: {}

在环境中创建该资源:

kubectl apply -f harbor-push-trigger.yaml
TIP

事件类型过滤示例:如果你的 Harbor webhook 同时发送 Push 和 Pull 事件,并且你希望分别处理它们,可以创建使用 CEL interceptors 按事件类型过滤的独立 Triggers:

Push Event Trigger(如上所示):

interceptors:
- ref:
    kind: ClusterInterceptor
    name: cel
  params:
  - name: filter
    value: body.type == "PUSH_ARTIFACT"

Pull Event Trigger(如需要):

interceptors:
- ref:
    kind: ClusterInterceptor
    name: cel
  params:
  - name: filter
    value: body.type == "PULL_ARTIFACT"

即使两种事件都发送到同一个 EventListener,这也能确保 push 事件只触发 push pipeline,而 pull 事件只触发 pull pipeline。

创建 Scanning Completed Trigger

将以下 YAML 保存为 harbor-scanning-trigger.yaml:

apiVersion: triggers.tekton.dev/v1beta1
kind: Trigger
metadata:
  name: my-pipeline-scanning # 建议根据 pipeline 名称修改前缀
  namespace: my-namespace # 改为实际 namespace
spec:
  bindings:
    - ref:
        kind: ClusterTriggerBinding
        name: harbor-scanning-completed
  interceptors: # 添加 Interceptor,仅过滤成功的扫描,或按漏洞严重级别过滤
  - ref:
      kind: ClusterInterceptor
      name: cel
    params:
    - name: filter
      value: |
        # 仅过滤成功的扫描
        # 注意:scan_overview 结构会因扫描类型而异,请相应调整路径
        # 对于漏洞扫描,其结构为:body.event_data.resources[0].scan_overview["application/vnd.security.vulnerability.report; version=1.1"].scan_status == "Success"
  template:
    spec:
      params:
        - name: repository-full-name
        - name: artifact-tag
          default: ""  # 可选字段:如果 artifact 仅通过 digest 引用,则可能为空
        - name: artifact-digest
      resourcetemplates:
      - apiVersion: tekton.dev/v1
        kind: PipelineRun
        metadata:
          generateName: my-pipeline-scan- # 建议根据 pipeline 名称修改前缀
        spec:
          pipelineRef:
            name: my-pipeline # 根据 pipeline 名称修改
          params:
            - name: repository-full-name
              value: $(tt.params.repository-full-name)
            - name: artifact-tag
              value: $(tt.params.artifact-tag)
            - name: artifact-digest
              value: $(tt.params.artifact-digest)
          workspaces: # 需要根据 pipeline 要求和环境配置修改 workspaces
            - name: output
              emptyDir: {}
TIP

请根据需要调整 Interceptor 配置。你可以按扫描状态、漏洞严重级别等条件进行过滤。请注意,scan_overview 结构使用动态 MIME type key,因此你可能需要根据扫描类型调整 JSONPath 表达式。

在环境中创建该资源:

kubectl apply -f harbor-scanning-trigger.yaml

验证 Triggers

通过向 Harbor 推送 image 并触发漏洞扫描来进行验证。

CLI:

你可以使用 kubectl -n <namespace> get pipelinerun 获取 pipeline 执行状态。

控制台:

访问 Pipelines > PipelineRuns 查看已触发的 pipelines。

使用场景

使用场景 1:自动化镜像部署

场景:当 container images 被推送到 Harbor 时,自动将其部署到 staging 或 production 环境。

配置:

  • 使用 harbor-push-artifact binding 创建 Trigger
  • 配置 pipeline 使用 artifact-resource-url 拉取 image,并将其部署到目标环境
  • 可选:使用 CEL interceptors 按 repository namespace 或 tag pattern 进行过滤

示例场景:

  • 将标记为 production 的 images 部署到 production 环境
  • 将来自特定 namespaces 的 images 部署到 staging 环境
  • 仅对符合特定命名模式的 images 触发部署

使用场景 2:安全策略执行

场景:通过阻止存在严重漏洞的 images 部署来执行安全策略。

配置:

  • 使用 harbor-scanning-completed binding 创建 Trigger
  • 使用 CEL interceptor 过滤出包含严重漏洞的扫描结果
  • 配置 pipeline 来:
    • 从扫描结果中检查漏洞数量
    • 如果严重漏洞数量超过阈值,则阻止部署
    • 向安全团队发送通知

示例场景:

  • 阻止存在严重漏洞的 images 部署
  • 自动隔离具有高风险漏洞的 images
  • 生成用于合规性的安全报告

使用场景 3:Artifact 生命周期管理

场景:根据使用模式和保留策略自动管理 artifact 生命周期。

配置:

  • 为 harbor-pull-artifact 和 harbor-delete-artifact 事件创建 Triggers
  • 跟踪 artifact 使用情况和时间
  • 根据策略自动删除旧的或未使用的 artifact

示例场景:

  • 归档 90 天内未被拉取的旧 artifacts
  • 在部署到 production 后清理开发 artifacts
  • 通过数据保留策略保持合规

使用场景 4:多阶段 CI/CD Pipeline

场景:构建一个完整的 CI/CD pipeline,在 image 推送时触发,执行测试、进行安全扫描,并根据扫描结果完成部署。

配置:

  • 创建多个 Triggers:
    1. harbor-push-artifact trigger:启动构建和测试 pipeline
    2. harbor-scanning-completed trigger:如果扫描通过,则继续部署
  • 使用 pipeline 依赖和 workspaces 在各阶段之间共享 artifacts

示例场景:

  • Build → Test → Scan → Deploy 工作流
  • 并行测试和扫描以加快反馈
  • 根据测试和扫描结果进行条件部署