# Google Cloud IAM permissions

> ZopNight needs 39 read permissions on GCP, most of them satisfied by Cloud Asset Inventory returning a whole project in one call. The 113 write permissions cover scheduling and remediation only, and are granted separately. The cloudasset.googleapis.com API must be enabled or discovery silently returns nothing.

Source: https://zop.dev/integrations/gcp/permissions
Updated: 2026-08-20

---

## Common questions

### Why only 39 read permissions on GCP but 113 write?

Because GCP splits mutation into many narrow permissions while bulk reads go through a single API. Discovery runs almost entirely through Cloud Asset Inventory, so roles/cloudasset.viewer does the work that takes dozens of Describe calls on AWS. It is not a lopsided grant, just a different shape.

### Service account key or OAuth?

A service account JSON key for anything automated: it works headless and survives unattended, and the key is a stored secret you own. OAuth stores nothing long-lived but needs interactive human consent, which is why it cannot be switched to in place on an existing account.

### What permission does ZopNight need to stop a Cloud SQL instance?

cloudsql.instances.update, covered by roles/cloudsql.editor. Cloud SQL has no stop API; stopping an instance is a patch to its activationPolicy, so the grant is an update rather than a stop.

## Cloud Asset Inventory does the reading

GCP's permission model is finer-grained than the other two, so the count reads oddly: 39 read
permissions against 113 write. That is not a lopsided grant. It reflects that GCP splits
mutation into many narrow permissions while bulk reads go through a single API.

Discovery runs almost entirely through **Cloud Asset Inventory**, which returns the whole
project inventory in one call. That is why the read side is small: one API does the work that
takes dozens of `Describe*` calls on AWS.

## Service account or OAuth?

- **Service account**: a JSON key file. Works headless, survives unattended, and is the right
  choice for automation. The key is a stored secret you own.
- **OAuth**: a three-step Google consent flow, tokens encrypted at rest. Nothing long-lived is
  stored, but it **cannot be switched to in place**, because it needs interactive consent from a
  human. Choose it deliberately, not by default.

Billing is a separate grant either way: on GCP, billing data lives at billing-account scope, not
project scope, so the one-click billing upgrade available on AWS does not apply here.

## The Cloud Asset API has to be enabled

If `cloudasset.googleapis.com` is not enabled on the project, discovery returns nothing at all.
Not an error, just nothing. This is the single most common cause of a GCP account that connects
successfully and then shows an empty inventory.

## What the write permissions cover

`scheduling` (start and stop Compute Engine, GKE node pools, Cloud SQL, Cloud Run, Memorystore),
`remediation` (acting on a finding), `namespace_scheduling` (scaling GKE workloads to zero and
back), and `provisioning`/`deployments` for ZopDay. Nothing reads object contents or table rows.

Cloud SQL is worth calling out: stopping an instance is a patch to its `activationPolicy`, not a
stop API, so the permission you need is `cloudsql.instances.update`.
