If you are a project administrator, you can configure a connection from a project in Harbor to a webhook endpoint. If you configure webhooks, Harbor notifies the webhook endpoint of certain events that occur in the project. Webhooks allow you to integrate Harbor with other tools to streamline continuous integration and development processes.

The action that is taken upon receiving a notification from a Harbor project depends on your continuous integration and development processes. For example, by configuring Harbor to send a POST request to a webhook listener at an endpoint of your choice, you can trigger a build and deployment of an application whenever there is a change to an image in the repository.

Supported Events

You can define multiple webhook endpoints per project. Harbor supports two kinds of endpoints currently, HTTP and SLACK. Webhook notifications provide information about events in JSON format and are delivered by HTTP or HTTPS POST to an existing webhhook endpoint URL or Slack address that you provide. There are 2 JSON formats supported for the webhook payload, Default is the format that has always existed, and the data structure has not changed from the previous versions, except that it has been named, CloudEvents is the format which organizes the payload data as following the spec of CloudEvents. The following table describes the events that trigger notifications and the contents of each notification.

EventWebhook Event TypeContents of Notification
Push artifact to registryPUSH_ARTIFACTRepository namespace name, repository name, resource URL, tags, manifest digest, artifact name, push time timestamp, username of user who pushed artifact
Pull artifact from registryPULL_ARTIFACTRepository namespace name, repository name, manifest digest, artifact name, pull time timestamp, username of user who pulled artifact
Delete artifact from registryDELETE_ARTIFACTRepository namespace name, repository name, manifest digest, artifact name, artifact size, delete time timestamp, username of user who deleted image
Artifact scan completedSCANNING_COMPLETEDRepository namespace name, repository name, tag scanned, artifact name, number of critical issues, number of major issues, number of minor issues, last scan status, scan completion time timestamp, username of user who performed scan
Artifact scan stoppedSCANNING_STOPPEDRepository namespace name, repository name, tag scanned, artifact name, scan status
Artifact scan failedSCANNING_FAILEDRepository namespace name, repository name, tag scanned, artifact name, error that occurred, username of user who performed scan
Project quota exceededQUOTA_EXCEEDRepository namespace name, repository name, tags, manifest digest, artifact name, push time timestamp, username of user who pushed artifact
Project quota near thresholdQUOTA_WARNINGRepository namespace name, repository name, tags, manifest digest, artifact name, push time timestamp, username of user who pushed artifact
Artifact replication status changedREPLICATIONRepository namespace name, repository name, tags, manifest digest, artifact name, push time timestamp, username of user who trigger the replication
Artifact tag retention finishedTAG_RETENTIONRepository namespace name, repository name, the number of total and retained, the rule of retention, deleted artifacts results

Payload Format

The webhook notification is delivered in JSON format. The following example shows the JSON notification for different event types when using HTTP kind endpoint:

Artifact pushed

Default

  1. {
  2. "type": "PUSH_ARTIFACT",
  3. "occur_at": 1680501893,
  4. "operator": "harbor-jobservice",
  5. "event_data": {
  6. "resources": [
  7. {
  8. "digest": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  9. "tag": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  10. "resource_url": "localhost/harbor/alpine@sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4"
  11. }
  12. ],
  13. "repository": {
  14. "date_created": 1680501893,
  15. "name": "alpine",
  16. "namespace": "harbor",
  17. "repo_full_name": "harbor/alpine",
  18. "repo_type": "private"
  19. }
  20. }
  21. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. // id is a generated UUID to make sure the unique
  4. "id": "66e18103-09c1-41f6-982f-37df223f3eeb",
  5. // requestid is the http request id for tracing the source request of this event
  6. "requestid": "51c0b694-0168-4f3c-b0db-282565455d7b",
  7. "source": "/projects/2/webhook/policies/15",
  8. "type": "harbor.artifact.pushed",
  9. "datacontenttype": "application/json",
  10. "time": "2023-04-03T06:04:46Z",
  11. "data": {
  12. "resources": [
  13. {
  14. "digest": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  15. "tag": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  16. "resource_url": "localhost/harbor/alpine@sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4"
  17. }
  18. ],
  19. "repository": {
  20. "date_created": 1680501893,
  21. "name": "alpine",
  22. "namespace": "harbor",
  23. "repo_full_name": "harbor/alpine",
  24. "repo_type": "private"
  25. }
  26. },
  27. "operator": "harbor-jobservice"
  28. }
Artifact pulled

Default

  1. {
  2. "type": "PULL_ARTIFACT",
  3. "occur_at": 1680502372,
  4. "operator": "robot$harbor+wHSYCuGD-Trivy-8e2e7505-d1e6-11ed-9e71-0242ac130009",
  5. "event_data": {
  6. "resources": [
  7. {
  8. "digest": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  9. "tag": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  10. "resource_url": "localhost/harbor/alpine@sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4"
  11. }
  12. ],
  13. "repository": {
  14. "date_created": 1680501893,
  15. "name": "alpine",
  16. "namespace": "harbor",
  17. "repo_full_name": "harbor/alpine",
  18. "repo_type": "private"
  19. }
  20. }
  21. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. "id": "718eab63-2efa-4f88-8c27-8bcacc34929b",
  4. "requestid": "bb4b5b91-aac7-4acd-8dff-e4118e53f6d1"
  5. "source": "/projects/2/webhook/policies/15",
  6. "type": "harbor.artifact.pulled",
  7. "datacontenttype": "application/json",
  8. "time": "2023-04-03T06:12:52Z",
  9. "data": {
  10. "resources": [
  11. {
  12. "digest": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  13. "tag": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  14. "resource_url": "localhost/harbor/alpine@sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4"
  15. }
  16. ],
  17. "repository": {
  18. "date_created": 1680501893,
  19. "name": "alpine",
  20. "namespace": "harbor",
  21. "repo_full_name": "harbor/alpine",
  22. "repo_type": "private"
  23. }
  24. },
  25. "operator": "robot$harbor+wHSYCuGD-Trivy-8e2e7505-d1e6-11ed-9e71-0242ac130009"
  26. }
Artifact deleted

Default

  1. {
  2. "type": "DELETE_ARTIFACT",
  3. "occur_at": 1680502598,
  4. "operator": "harbor-jobservice",
  5. "event_data": {
  6. "resources": [
  7. {
  8. "digest": "sha256:2bb501e6173d9d006e56de5bce2720eb06396803300fe1687b58a7ff32bf4c14",
  9. "tag": "3.8",
  10. "resource_url": "localhost/harbor/alpine:3.8"
  11. }
  12. ],
  13. "repository": {
  14. "date_created": 1680501893,
  15. "name": "alpine",
  16. "namespace": "harbor",
  17. "repo_full_name": "harbor/alpine",
  18. "repo_type": "private"
  19. }
  20. }
  21. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. "id": "343f1623-7cba-487c-88f1-c5ebf55e93aa",
  4. "requestid": "ca0f3ceb-810f-4598-a268-a2291ad4de49",
  5. "source": "/projects/2/webhook/policies/15",
  6. "type": "harbor.artifact.deleted",
  7. "datacontenttype": "application/json",
  8. "time": "2023-04-03T06:16:38Z",
  9. "data": {
  10. "resources": [
  11. {
  12. "digest": "sha256:2bb501e6173d9d006e56de5bce2720eb06396803300fe1687b58a7ff32bf4c14",
  13. "tag": "3.8",
  14. "resource_url": "localhost/harbor/alpine:3.8"
  15. }
  16. ],
  17. "repository": {
  18. "date_created": 1680501893,
  19. "name": "alpine",
  20. "namespace": "harbor",
  21. "repo_full_name": "harbor/alpine",
  22. "repo_type": "private"
  23. }
  24. },
  25. "operator": "harbor-jobservice"
  26. }
Scanning completed

Default

  1. {
  2. "type": "SCANNING_COMPLETED",
  3. "occur_at": 1680502375,
  4. "operator": "auto",
  5. "event_data": {
  6. "resources": [
  7. {
  8. "digest": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  9. "resource_url": "localhost/harbor/alpine@sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  10. "scan_overview": {
  11. "application/vnd.security.vulnerability.report; version=1.1": {
  12. "report_id": "af0546c1-67dc-4e9d-927e-372900ead0df",
  13. "scan_status": "Success",
  14. "severity": "None",
  15. "duration": 8,
  16. "summary": {
  17. "total": 0,
  18. "fixable": 0,
  19. "summary": {}
  20. },
  21. "start_time": "2023-04-03T06:12:47Z",
  22. "end_time": "2023-04-03T06:12:55Z",
  23. "scanner": {
  24. "name": "Trivy",
  25. "vendor": "Aqua Security",
  26. "version": "v0.37.2"
  27. },
  28. "complete_percent": 100
  29. }
  30. }
  31. }
  32. ],
  33. "repository": {
  34. "name": "alpine",
  35. "namespace": "harbor",
  36. "repo_full_name": "harbor/alpine",
  37. "repo_type": "private"
  38. }
  39. }
  40. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. "id": "64bce2fe-6159-454d-8389-852d01ef1e9d",
  4. "requestid": "98ecbced-4169-443b-8e19-459a8c81675d",
  5. "source": "/projects/2/webhook/policies/15",
  6. "type": "harbor.scan.completed",
  7. "datacontenttype": "application/json",
  8. "time": "2023-04-03T06:12:55Z",
  9. "data": {
  10. "resources": [
  11. {
  12. "digest": "sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  13. "resource_url": "localhost/harbor/alpine@sha256:954b378c375d852eb3c63ab88978f640b4348b01c1b3456a024a81536dafbbf4",
  14. "scan_overview": {
  15. "application/vnd.security.vulnerability.report; version=1.1": {
  16. "report_id": "af0546c1-67dc-4e9d-927e-372900ead0df",
  17. "scan_status": "Success",
  18. "severity": "None",
  19. "duration": 8,
  20. "summary": {
  21. "total": 0,
  22. "fixable": 0,
  23. "summary": {}
  24. },
  25. "start_time": "2023-04-03T06:12:47Z",
  26. "end_time": "2023-04-03T06:12:55Z",
  27. "scanner": {
  28. "name": "Trivy",
  29. "vendor": "Aqua Security",
  30. "version": "v0.37.2"
  31. },
  32. "complete_percent": 100
  33. }
  34. }
  35. }
  36. ],
  37. "repository": {
  38. "name": "alpine",
  39. "namespace": "harbor",
  40. "repo_full_name": "harbor/alpine",
  41. "repo_type": "private"
  42. }
  43. },
  44. "operator": "auto"
  45. }
Scanning stopped

Default

  1. {
  2. "type": "SCANNING_STOPPED",
  3. "occur_at": 1680502334,
  4. "operator": "auto",
  5. "event_data": {
  6. "resources": [
  7. {
  8. "digest": "sha256:e802987f152d7826cf929ad4999fb3bb956ce7a30966aeb46c749f9120eaf22c",
  9. "resource_url": "localhost/harbor/alpine@sha256:e802987f152d7826cf929ad4999fb3bb956ce7a30966aeb46c749f9120eaf22c",
  10. "scan_overview": {
  11. "application/vnd.security.vulnerability.report; version=1.1": {
  12. "report_id": "bf92700b-fa5e-4fe4-891c-42b730c81151",
  13. "scan_status": "Stopped",
  14. "severity": "",
  15. "duration": 5,
  16. "summary": null,
  17. "start_time": "2023-04-03T06:12:09Z",
  18. "end_time": "2023-04-03T06:12:14Z",
  19. "complete_percent": 0
  20. }
  21. }
  22. }
  23. ],
  24. "repository": {
  25. "name": "alpine",
  26. "namespace": "harbor",
  27. "repo_full_name": "harbor/alpine",
  28. "repo_type": "private"
  29. }
  30. }
  31. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. "id": "a8a03301-9e31-433f-ace3-240ac16f17b7",
  4. "requestid": "daea2f4d-7a08-400d-9eef-e5f726da976e",
  5. "source": "/projects/2/webhook/policies/15",
  6. "type": "harbor.scan.stopped",
  7. "datacontenttype": "application/json",
  8. "time": "2023-04-03T06:12:14Z",
  9. "data": {
  10. "resources": [
  11. {
  12. "digest": "sha256:e802987f152d7826cf929ad4999fb3bb956ce7a30966aeb46c749f9120eaf22c",
  13. "resource_url": "localhost/harbor/alpine@sha256:e802987f152d7826cf929ad4999fb3bb956ce7a30966aeb46c749f9120eaf22c",
  14. "scan_overview": {
  15. "application/vnd.security.vulnerability.report; version=1.1": {
  16. "report_id": "bf92700b-fa5e-4fe4-891c-42b730c81151",
  17. "scan_status": "Stopped",
  18. "severity": "",
  19. "duration": 5,
  20. "summary": null,
  21. "start_time": "2023-04-03T06:12:09Z",
  22. "end_time": "2023-04-03T06:12:14Z",
  23. "complete_percent": 0
  24. }
  25. }
  26. }
  27. ],
  28. "repository": {
  29. "name": "alpine",
  30. "namespace": "harbor",
  31. "repo_full_name": "harbor/alpine",
  32. "repo_type": "private"
  33. }
  34. },
  35. "operator": "auto"
  36. }
Scanning failed

Default

  1. {
  2. "type": "SCANNING_FAILED",
  3. "occur_at": 1680505885,
  4. "operator": "auto",
  5. "event_data": {
  6. "resources": [
  7. {
  8. "digest": "sha256:dabea2944dcc2b86482b4f0b0fb62da80e0673e900c46c0e03b45919881a5d84",
  9. "resource_url": "localhost/harbor/alpine@sha256:dabea2944dcc2b86482b4f0b0fb62da80e0673e900c46c0e03b45919881a5d84",
  10. "scan_overview": {
  11. "application/vnd.security.vulnerability.report; version=1.1": {
  12. "report_id": "a2573415-c727-4723-bc92-376c1d978637",
  13. "scan_status": "Error",
  14. "severity": "",
  15. "duration": 10,
  16. "summary": null,
  17. "start_time": "2023-04-03T07:11:15Z",
  18. "end_time": "2023-04-03T07:11:25Z",
  19. "complete_percent": 0
  20. }
  21. }
  22. }
  23. ],
  24. "repository": {
  25. "name": "alpine",
  26. "namespace": "harbor",
  27. "repo_full_name": "harbor/alpine",
  28. "repo_type": "private"
  29. }
  30. }
  31. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. "id": "bdfe1de3-c069-4efc-b4f4-1a75c9a148c4",
  4. "requestid": "b28412fe-7934-42c8-9633-4d22d872d718",
  5. "source": "/projects/2/webhook/policies/15",
  6. "type": "harbor.scan.failed",
  7. "datacontenttype": "application/json",
  8. "time": "2023-04-03T07:11:25Z",
  9. "data": {
  10. "resources": [
  11. {
  12. "digest": "sha256:dabea2944dcc2b86482b4f0b0fb62da80e0673e900c46c0e03b45919881a5d84",
  13. "resource_url": "localhost/harbor/alpine@sha256:dabea2944dcc2b86482b4f0b0fb62da80e0673e900c46c0e03b45919881a5d84",
  14. "scan_overview": {
  15. "application/vnd.security.vulnerability.report; version=1.1": {
  16. "report_id": "a2573415-c727-4723-bc92-376c1d978637",
  17. "scan_status": "Error",
  18. "severity": "",
  19. "duration": 10,
  20. "summary": null,
  21. "start_time": "2023-04-03T07:11:15Z",
  22. "end_time": "2023-04-03T07:11:25Z",
  23. "complete_percent": 0
  24. }
  25. }
  26. }
  27. ],
  28. "repository": {
  29. "name": "alpine",
  30. "namespace": "harbor",
  31. "repo_full_name": "harbor/alpine",
  32. "repo_type": "private"
  33. }
  34. },
  35. "operator": "auto"
  36. }
Quota exceeded

Default

  1. {
  2. "type": "QUOTA_EXCEED",
  3. "occur_at": 1680505484,
  4. "operator": "",
  5. "event_data": {
  6. "resources": [
  7. {
  8. "digest": "sha256:402d21757a03a114d273bbe372fa4b9eca567e8b6c332fa7ebf982b902207242"
  9. }
  10. ],
  11. "repository": {
  12. "name": "alpine",
  13. "namespace": "harbor",
  14. "repo_full_name": "harbor/alpine",
  15. "repo_type": "private"
  16. },
  17. "custom_attributes": {
  18. "Details": "adding 2.1 MiB of storage resource, which when updated to current usage of 8.3 MiB will exceed the configured upper limit of 10.0 MiB."
  19. }
  20. }
  21. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. "id": "81f243ce-699c-44d6-9dbe-b2ee5f10237a",
  4. "requestid": "4b9dcf9a-db23-460c-9b52-c9d994e362ee",
  5. "source": "/projects/2/webhook/policies/15",
  6. "type": "harbor.quota.exceeded",
  7. "datacontenttype": "application/json",
  8. "time": "2023-04-03T07:04:44Z",
  9. "data": {
  10. "resources": [
  11. {
  12. "digest": "sha256:402d21757a03a114d273bbe372fa4b9eca567e8b6c332fa7ebf982b902207242"
  13. }
  14. ],
  15. "repository": {
  16. "name": "alpine",
  17. "namespace": "harbor",
  18. "repo_full_name": "harbor/alpine",
  19. "repo_type": "private"
  20. },
  21. "custom_attributes": {
  22. "Details": "adding 2.1 MiB of storage resource, which when updated to current usage of 8.3 MiB will exceed the configured upper limit of 10.0 MiB."
  23. }
  24. },
  25. "operator": ""
  26. }
Quota near threshold

Default

  1. {
  2. "type": "QUOTA_WARNING",
  3. "occur_at": 1680505653,
  4. "operator": "",
  5. "event_data": {
  6. "resources": [
  7. {
  8. "digest": "sha256:514ec80ffbe1a2ab1d9a3d5e6082296296a1d8b6870246edf897228e5df2367d"
  9. }
  10. ],
  11. "repository": {
  12. "name": "alpine",
  13. "namespace": "harbor",
  14. "repo_full_name": "harbor/alpine",
  15. "repo_type": "private"
  16. },
  17. "custom_attributes": {
  18. "Details": "quota usage reach 85%: resource storage used 12.6 MiB of 14.0 MiB"
  19. }
  20. }
  21. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. "id": "1267b437-ea5a-4e06-bbe5-75e6fde733d3",
  4. "requestid": "77eb6c26-f3e9-45d3-bd40-2fd9421c56cd",
  5. "source": "/projects/2/webhook/policies/15",
  6. "type": "harbor.quota.warned",
  7. "datacontenttype": "application/json",
  8. "time": "2023-04-03T07:07:33Z",
  9. "data": {
  10. "resources": [
  11. {
  12. "digest": "sha256:514ec80ffbe1a2ab1d9a3d5e6082296296a1d8b6870246edf897228e5df2367d"
  13. }
  14. ],
  15. "repository": {
  16. "name": "alpine",
  17. "namespace": "harbor",
  18. "repo_full_name": "harbor/alpine",
  19. "repo_type": "private"
  20. },
  21. "custom_attributes": {
  22. "Details": "quota usage reach 85%: resource storage used 12.6 MiB of 14.0 MiB"
  23. }
  24. },
  25. "operator": ""
  26. }
Replication status changed

Default

  1. {
  2. "type": "REPLICATION",
  3. "occur_at": 1680501904,
  4. "operator": "MANUAL",
  5. "event_data": {
  6. "replication": {
  7. "harbor_hostname": "localhost",
  8. "job_status": "Success",
  9. "artifact_type": "image",
  10. "override_mode": true,
  11. "trigger_type": "MANUAL",
  12. "policy_creator": "admin",
  13. "execution_timestamp": 1680501881,
  14. "src_resource": {
  15. "registry_name": "hub",
  16. "registry_type": "docker-hub",
  17. "endpoint": "https://hub.docker.com",
  18. "namespace": "library"
  19. },
  20. "dest_resource": {
  21. "registry_type": "harbor",
  22. "endpoint": "http://localhost",
  23. "namespace": "harbor"
  24. },
  25. "successful_artifact": [
  26. {
  27. "type": "image",
  28. "status": "Success",
  29. "name_tag": "alpine [1 item(s) in total]"
  30. }
  31. ]
  32. }
  33. }
  34. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. "id": "e3005250-ffa8-4a10-af92-91fe25cca22c",
  4. "requestid": "0d896c4d-353a-422e-b43b-5067d98ec2a3",
  5. "source": "/projects/2/webhook/policies/15",
  6. "type": "harbor.replication.status.changed",
  7. "datacontenttype": "application/json",
  8. "time": "2023-04-03T06:05:04Z",
  9. "data": {
  10. "replication": {
  11. "harbor_hostname": "localhost",
  12. "job_status": "Success",
  13. "artifact_type": "image",
  14. "override_mode": true,
  15. "trigger_type": "MANUAL",
  16. "policy_creator": "admin",
  17. "execution_timestamp": 1680501881,
  18. "src_resource": {
  19. "registry_name": "hub",
  20. "registry_type": "docker-hub",
  21. "endpoint": "https://hub.docker.com",
  22. "namespace": "library"
  23. },
  24. "dest_resource": {
  25. "registry_type": "harbor",
  26. "endpoint": "http://localhost",
  27. "namespace": "harbor"
  28. },
  29. "successful_artifact": [
  30. {
  31. "type": "image",
  32. "status": "Success",
  33. "name_tag": "alpine [1 item(s) in total]"
  34. }
  35. ]
  36. }
  37. },
  38. "operator": "MANUAL"
  39. }
Tag retention finished

Default

  1. {
  2. "type": "TAG_RETENTION",
  3. "occur_at": 1680502598,
  4. "operator": "MANUAL",
  5. "event_data": {
  6. "retention": {
  7. "total": 1,
  8. "retained": 0,
  9. "harbor_hostname": "localhost",
  10. "project_name": "harbor",
  11. "retention_policy_id": 2,
  12. "retention_rule": [
  13. {
  14. "template": "always",
  15. "tag_selectors": [
  16. {
  17. "kind": "doublestar",
  18. "decoration": "matches",
  19. "pattern": "xxxxxxxxxx",
  20. "extras": "{\"untagged\":true}"
  21. }
  22. ],
  23. "scope_selectors": {
  24. "repository": [
  25. {
  26. "kind": "doublestar",
  27. "decoration": "repoMatches",
  28. "pattern": "**",
  29. "extras": ""
  30. }
  31. ]
  32. }
  33. }
  34. ],
  35. "result": "SUCCESS",
  36. "deleted_artifact": [
  37. {
  38. "type": "image",
  39. "status": "SUCCESS",
  40. "name_tag": "alpine:3.8"
  41. }
  42. ]
  43. }
  44. }
  45. }

CloudEvents

  1. {
  2. "specversion": "1.0",
  3. "id": "a8618595-6fa0-4cf4-afdc-870459b1d7f6",
  4. "requestid": "d71943e8-872d-40cd-b12a-f6bafcce1202",
  5. "source": "/projects/2/webhook/policies/15",
  6. "type": "harbor.tag_retention.finished",
  7. "datacontenttype": "application/json",
  8. "time": "2023-04-03T06:16:38Z",
  9. "data": {
  10. "retention": {
  11. "total": 1,
  12. "retained": 0,
  13. "harbor_hostname": "localhost",
  14. "project_name": "harbor",
  15. "retention_policy_id": 2,
  16. "retention_rule": [
  17. {
  18. "template": "always",
  19. "tag_selectors": [
  20. {
  21. "kind": "doublestar",
  22. "decoration": "matches",
  23. "pattern": "xxxxxxxxxx",
  24. "extras": "{\"untagged\":true}"
  25. }
  26. ],
  27. "scope_selectors": {
  28. "repository": [
  29. {
  30. "kind": "doublestar",
  31. "decoration": "repoMatches",
  32. "pattern": "**",
  33. "extras": ""
  34. }
  35. ]
  36. }
  37. }
  38. ],
  39. "result": "SUCCESS",
  40. "deleted_artifact": [
  41. {
  42. "type": "image",
  43. "status": "SUCCESS",
  44. "name_tag": "alpine:3.8"
  45. }
  46. ]
  47. }
  48. },
  49. "operator": "MANUAL"
  50. }

Notice that only http type endpoint supports select Default or CloudEvents format, when you select the Slack type, and fill a Slack incoming webhook URL as endpoint, the message you received in Slack will be a rich text like the following.

  1. Harbor webhook events
  2. event_type: PUSH_ARTIFACT
  3. occur_at: April 15th at 11:59 AM
  4. operator: admin
  5. event_data:
  6. {
  7. "resources": [
  8. {
  9. "digest": "sha256:8a9e9863dbb6e10edb5adfe917c00da84e1700fa76e7ed02476aa6e6fb8ee0d8",
  10. "tag": "latest",
  11. "resource_url": "hub.harbor.com/test-webhook/debian:latest"
  12. }
  13. ],
  14. "repository": {
  15. "date_created": 1586922308,
  16. "name": "debian",
  17. "namespace": "test-webhook",
  18. "repo_full_name": "test-webhook/debian",
  19. "repo_type": "private"
  20. }
  21. }

Webhook Endpoint Recommendations

There are two kinds of endpoints. For HTTP the endpoint that receives the webhook should ideally have a webhook listener that is capable of interpreting the payload and acting upon the information it contains. For example, running a shell script.

And for Slack endpoint, you should follow the guide of Slack incoming webhook.

Example Use Cases

You can configure your continuous integration and development infrastructure so that it performs the following types of operations when it receives a webhook notification from Harbor.

  • Artifact push:
    • Trigger a new build immediately following a push on selected repositories or tags.
    • Notify services or applications that use the artifact that a new artifact is available and pull it.
    • Scan the artifact using Trivy.
    • Replicate the artifact to remote registries.
  • Image scanning:
    • If a vulnerability is found, rescan the image or replicate it to another registry.
    • If the scan passes, deploy the image.

Configure Webhooks

  1. Log in to the Harbor interface with an account that has at least project administrator privileges.

  2. Go to Projects, select a project, and select Webhooks.

    Webhooks option
  3. Select notify type HTTP, so the webhook will be send to a HTTP endpoint.

  4. Select payload format as Default or CloudEvents when choose the HTTP notify type.

  5. Select events that you want to subscribe.

  6. Enter the URL for your webhook endpoint listener.

  7. If your webhook listener implements authentication, enter the authentication header.

  8. To implement HTTPS POST instead of HTTP POST, select the Verifiy Remote Certficate check box.

    Webhook URL
  9. Click Add to create the webhook.

You can modify the webhook, you can also Enable or Deactivate the webhook.

Webhook Job Histories

  1. Click the radio box of one webhook policy, then will list the recent webhook executions in the following section.

    Webhook executions
  2. Select one webhook execution, then will redirect to the tasks page under this execution.

    Webhook tasks
  3. Click the log button of one task, then will redirect to the page to show the webhook job logs.

    Webhook logs

If a webhook notification fails to send, or if it receives an HTTP error response with a code other than 2xx, the notification is re-sent based on the configuration that you set in harbor.yml.

Docker Compose

  1. notification:
  2. # Maximum retry count for webhook job
  3. # Increase or decrease the retry count when webhook job failed, pay attention that a high number of retries can put pressure on the webhook job queue
  4. webhook_job_max_retry: 3
  5. # HTTP client timeout for webhook job
  6. # Increase the timeout if the webhook endpoint cannot respond to harbor within the specified timeout
  7. webhook_job_http_client_timeout: 3 #seconds

Helm

  1. jobservice:
  2. notification:
  3. # Maximum retry count for webhook job
  4. # Increase or decrease the retry count when webhook job failed, pay attention that a high number of retries can put pressure on the webhook job queue
  5. webhook_job_max_retry: 3
  6. # HTTP client timeout for webhook job
  7. # Increase the timeout if the webhook endpoint cannot respond to harbor within the specified timeout
  8. webhook_job_http_client_timeout: 3 # in seconds

Globally Enable and Deactivate Webhooks

As a Harbor system administrator, you can enable and deactivate webhook notifications for all projects.

  1. Go to Configuration > System Settings.

  2. Scroll down and check or uncheck the Webhooks enabled check box.

    Enable/deactivate webhooks