Skip to content

Google Artifact Registry

GCP runs two image registries side by side: the legacy Container Registry (gcr.io, us.gcr.io, eu.gcr.io, asia.gcr.io) and the modern Artifact Registry (<region>-docker.pkg.dev). They share Google's auth model but differ in IAM roles, repository structure, and feature set. The wizard auto-detects Artifact Registry from the *-docker.pkg.dev suffix; legacy GCR hostnames must be picked manually.

Auth options

MethodWhen to useHarborGuard fields
Service-account JSON keyMost common; works in cloud and sensor modeUsername _json_key, Password = entire JSON file contents
Workload Identity (sensor on GKE)No long-lived keys; sensor pod inherits a Google identityNone — handled by the sensor
Application Default Credentials (sensor on GCE/Cloud Run)Sensor runs on GCP compute with an attached service accountNone — handled by the sensor
OAuth access tokenShort-lived (1 hour); only useful for ad-hoc testsUsername oauth2accesstoken, Password = the token

Add the registry

  1. Registries → Connect Registry.
  2. Registry URL:
    • Artifact Registry: us-central1-docker.pkg.dev (or your region)
    • Legacy GCR: gcr.io, us.gcr.io, eu.gcr.io, asia.gcr.io
  3. The wizard tags Artifact Registry hostnames as Google GAR Detected. For GCR, set the provider manually.
  4. Cloud mode: enter _json_key as the username and paste the full service-account JSON (including the surrounding {}) as the password. Don't escape the newlines in the private key — paste verbatim.
  5. Save.

The first sync enumerates repositories under your project. For Artifact Registry, the URL path includes <project>/<repository>/<image>; HarborGuard uses the project from the JSON key.

Required IAM roles

Use caseRoleGranted on
Artifact Registry, read-onlyroles/artifactregistry.readerThe repository (preferred) or the project
Legacy GCR, read-onlyroles/storage.objectViewer on the underlying GCS bucket (artifacts.<project>.appspot.com and regional variants)The bucket
Bothroles/artifactregistry.reader + roles/storage.objectViewerProject, if you don't want to enumerate buckets

Granular permissions actually exercised: artifactregistry.repositories.list, artifactregistry.repositories.downloadArtifacts, artifactregistry.tags.list, artifactregistry.versions.list, artifactregistry.dockerimages.get.

Push-event sync

Artifact Registry can publish to a Pub/Sub topic on every push. To wire on_push:

  1. Enable Artifact Registry Pub/Sub notifications in the GCP console (creates a topic like gcr or artifact-registry).
  2. Create a push subscription targeting https://<your-harborguard-host>/api/webhooks/gcp.
  3. Set the registry's schedule to on_push.

Legacy GCR uses a different topic name (gcr) but the same flow.

Common pitfalls

  • GAR vs GCR confusion. A migrated project will have both gcr.io (read-through to Artifact Registry) and a real *-docker.pkg.dev host. Add the GAR host directly; reading through the GCR alias works but bypasses Artifact Registry's per-repository IAM.
  • Region encoding. us-docker.pkg.dev (multi-region) and us-central1-docker.pkg.dev (single region) are distinct registries with different repos.
  • JSON key formatting. The wizard's password field must contain the full JSON object as a single value. Pasting just the private_key field results in "authentication failed" with a misleading 401.
  • Project ID vs project number. The JSON key embeds the project ID; HarborGuard uses that, not the numeric ID. Repositories created with the project number in their path still resolve.
  • Disabling the legacy GCR API. If you've enabled Artifact Registry's GCR repository, disabling the standalone Container Registry API will silently break legacy gcr.io hostnames — keep both enabled during migration.

Troubleshooting

SymptomLikely cause
401 on test, credentials look correctUsername field is something other than _json_key
403 listing repositoriesService account lacks artifactregistry.repositories.list at the project level
GCR works but GAR returns 404Used the GCR alias hostname for an Artifact Registry repo — switch to *-docker.pkg.dev
Some images sync, others 404Repository-level IAM grants exist for some repos and not others
Sensor on GKE fails to authenticateWorkload Identity isn't bound — confirm the iam.gke.io/gcp-service-account annotation on the sensor's KSA

On this page