Harbor
Harbor is a self-hosted CNCF registry whose security model is built around projects: every image lives under harbor.example.com/<project>/<image>, and access controls are scoped per project. Robot accounts are the right primitive for HarborGuard — they are revocable, do not occupy a user seat, and can be scoped narrowly.
Auth options
| Method | When to use | HarborGuard fields |
|---|---|---|
| Project robot account | Recommended; scoped to one project | Username = full robot name (with robot$ or robot$<project>+ prefix), Password = secret |
| System-wide robot account (Harbor 2.2+) | One robot, many projects | Same fields, prefix is robot$ |
| Username + password | Quick test; rotates with the user | Username = login, Password = password |
| OIDC token | Only for users; can't be issued to a robot | Not recommended for stored connections |
Add the registry
- Registries → Connect Registry.
- Registry URL — the Harbor portal URL minus the path, for example
harbor.example.com. Don't include/harbor/projectsetc. - Harbor isn't auto-detected from the URL; pick Harbor in the provider field if the wizard falls back to Custom.
- Cloud mode: enter the robot name + secret.
- If your Harbor uses HTTP (very common for internal staging), enable Allow HTTP / insecure.
- Save.
Harbor uses real /v2/_catalog so HarborGuard's catalog enumeration works end-to-end.
Robot account scopes
When creating the robot, grant at minimum:
repository:pull,listartifact:readtag:list
Avoid push, delete, and helm-chart-write — HarborGuard only reads.
For a system-wide robot (Harbor 2.2+), add repository(*): pull, list plus artifact(*): read. The * is required; granting repository: pull without a project selector silently scopes to nothing.
Push-event sync
Harbor projects can fire webhooks on push.
- Project → Webhooks → New Webhook.
- Notify type:
http. - Endpoint:
https://<your-harborguard-host>/api/webhooks/harbor. - Event types: Artifact pushed.
- Set the registry's schedule to
on_push.
For multi-project Harbor instances, configure one webhook per project.
Common pitfalls
- Robot prefix. Harbor prepends
robot$(project robot:robot$<project>+name; system robot:robot$name). The wizard's username field must contain the full prefixed name, exactly as Harbor's UI shows it. Stripping the prefix is the single most common 401 cause. - Cross-project robots don't exist (pre-2.2). A project-scoped robot cannot list any other project. Either use a system robot or add multiple HarborGuard registry connections, one per project.
- Self-signed CAs. Harbor is often deployed with a private CA. Cloud-mode connections will fail TLS — deploy a sensor inside the network.
- Replication-only artifacts. If a project is the destination of a Harbor replication and the source has been deleted, manifests may become "unknown" — HarborGuard reports the manifest, scan fails on pull. This is a Harbor-side cleanup issue.
- Vulnerability scanning collision. Harbor has its own scanner integration. Disable Harbor's own scan-on-push if you want HarborGuard to be the system of record — both running together is supported but doubles network egress.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| 401 even with correct secret | Robot username is missing the robot$ prefix |
| Catalog empty | Robot is project-scoped to a project that contains zero repositories, or system robot lacks repository(*) |
| TLS error in cloud mode | Private CA — switch to a sensor deployment |
| Test passes, sync 401s | Robot was created with a "duration" that has expired |
| Webhook fires but never reaches HarborGuard | Harbor's outbound proxy / firewall rules — check the webhook execution log on Harbor |