使用 Harbor Event Triggers

概述

Harbor Event Triggers 允许您通过 Harbor 的 Webhook 事件自动触发 Tekton pipeline。它支持多种事件类型,包括 artifact push、pull、delete 以及 scanning completion,从而帮助您为容器镜像和 OCI charts 构建完整的 CI/CD 自动化工作流。

核心特性

  • 多事件类型支持:支持多种 Harbor 事件,如 Push Artifact、Pull Artifact、Delete Artifact 和 Scanning Completed。
  • 标准化 Trigger 绑定:提供标准化的 ClusterTriggerBindings,以确保跨平台一致性。
  • 灵活的参数映射:自动从 Harbor 事件中提取关键内容,用于 pipeline 参数。
  • 多 artifact 类型支持:同时支持容器镜像和 OCI charts。

支持的事件类型

基本事件信息

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

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

Variable NameDescriptionExample Value
event-typeEvent TypePUSH_ARTIFACT, PULL_ARTIFACT, DELETE_ARTIFACT, SCANNING_COMPLETED
occur-atEvent Occurrence Time1763369448
operatorWho triggered the eventadmin
repository-nameRepository Namealpine
repository-namespaceRepository Namespacelibrary
repository-full-nameRepository Full Namelibrary/alpine
repository-typeRepository Typepublic, private, chart
artifact-digestArtifact Digestsha256:c4975008127577bfc34169439e890db7cfb1cedccabe49c059c88f913cb27edd
artifact-tagArtifact Taglatest, v1.0.0 (optional, may be empty if artifact is referenced by digest only)
artifact-resource-urlArtifact Resource 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 Event

当将 artifact(容器镜像或 OCI chart)推送到 Harbor repository 时触发。适用于:

  • 自动化镜像构建和部署
  • 镜像验证和测试
  • 自动化 tagging 和 versioning
  • 多阶段 build pipeline

Push Artifact Event Variables

Variable NameDescriptionExample Value
repository-date-createdRepository Creation Time1763369448

上述所有基础变量也都可用。

2. Pull Artifact Event

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

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

Pull Artifact Event Variables

Variable NameDescriptionExample Value
repository-date-createdRepository Creation Time1763369448

上述所有基础变量也都可用。

3. Delete Artifact Event

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

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

Delete Artifact Event Variables

上述所有基础变量均可用。请注意,repository-date-created 不适用于 delete 事件。

4. Scanning Completed Event

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

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

Scanning Completed Event Variables

上述所有基础变量均可用。请注意,repository-date-created 不适用于 scanning 事件。

WARNING

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

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: ""  # Optional field 的空字符串默认值

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

前提条件

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

通过 Harbor UI 配置 Webhook

  1. 进入您的 Harbor project settings。
  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 实现持续集成,并满足以下需求:

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

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

例如,如果您的 webhook 将 PUSH_ARTIFACTPULL_ARTIFACT 事件都发送到同一个 EventListener,并且某个 Trigger 没有 interceptor,那么这两种事件都会触发 pipeline。请使用 interceptor 将不同的事件类型路由到不同的 Trigger 或 pipeline。

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

Parameter NameDescriptionExample Value
repository-full-name目标 pipeline 的 Repository 完整名称library/alpine
artifact-tagArtifact taglatest
artifact-digestArtifact digestsha256:c4975008127577bfc34169439e890db7cfb1cedccabe49c059c88f913cb27edd
TIP

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

InformationDescription
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 interceptor 按事件类型过滤的独立 Trigger:

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 键,因此您可能需要根据扫描类型调整 JSONPath 表达式。

在环境中创建该资源:

kubectl apply -f harbor-scanning-trigger.yaml

验证 Trigger

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

CLI:

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

Console:

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

使用场景

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

场景:当容器镜像推送到 Harbor 时,自动将其部署到 staging 或 production 环境。

配置

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

示例用例

  • 将带有 production 标签的镜像部署到 production 环境
  • 将来自特定 namespace 的镜像部署到 staging 环境
  • 仅对匹配特定命名模式的镜像触发部署

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

场景:通过阻止包含严重漏洞的镜像部署来执行安全策略。

配置

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

示例用例

  • 防止部署包含严重漏洞的镜像
  • 自动隔离具有高风险漏洞的镜像
  • 为合规性生成安全报告

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

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

配置

  • harbor-pull-artifactharbor-delete-artifact 事件创建 Trigger
  • 跟踪 artifact 使用情况和存活时间
  • 根据策略自动删除过期或未使用的 artifact

示例用例

  • 归档 90 天内未被拉取的旧 artifact
  • 在部署到 production 后清理开发 artifact
  • 满足数据保留策略要求

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

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

配置

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

示例用例

  • Build → Test → Scan → Deploy 工作流
  • 并行测试和扫描,以获得更快的反馈
  • 基于测试和扫描结果的条件部署