Optional: a configuration role per service
The four viewer roles read telemetry — logs,
metrics, error groups, Cloud Run revisions — and only telemetry. Some
questions are not in the telemetry. A PostgreSQL instance pinned at 100
connections is either under load or at a max_connections of 100, and
that flag lives in the instance’s settings, which none of the four roles
can read. Nodrik reports what was seen and says what would confirm it —
never a guess.
For each of the services below, one more read-only role lets Nodrik read the settings as well. Every one is:
- optional — nothing stops working without it, and Nodrik never asks for it in advance; it investigates with what is available and says when a setting would have decided the answer;
- per service — the role reads the configuration of the service the alert was about, never the project;
- a custom role defined in your project, holding exactly the
permissions the tool behind it calls, all of them
getorlist. Google’s predefined viewers for these services carry verbs that are not reads —cloudsql.viewercan export the database,compute.viewercan read a VM’s serial console — so Nodrik defines its own rather than footnote theirs; - granted the same three ways as the four roles: the console
wizard,
grant-nodrik-access.sh --family <name>, or the Terraform module’sfamiliesinput; - removed by the revoke script and by
terraform destroy, which delete the role definition too, so nothing of ours is left in your project.
The roles
Section titled “The roles”| Service | --family |
Role id | Reads | Cannot |
|---|---|---|---|---|
| Cloud SQL | managed-sql |
nodrikManagedSqlConfigViewer |
instance settings and database flags — tier, disk, availability, max_connections, the maintenance window |
change any of them, read or export any data, connect, or log in |
| Memorystore | cache |
nodrikCacheConfigViewer |
Redis, Valkey and Memcached instance settings — memory size, eviction policy, tier, version, replicas, window | change any of them, read any cached data, or connect |
| GKE | kubernetes |
nodrikKubernetesConfigViewer |
cluster settings from the GKE API — control-plane and node-pool versions, release channel, autoscaling bounds | change any of them, or read anything inside the cluster: no pod, workload, ConfigMap or Secret — see below |
| Compute Engine | compute |
nodrikComputeConfigViewer |
instance settings — machine type, status, scheduling, the managed instance group and its autoscaler, recent zone operations | change any of them, or read the serial console or screenshots. instances.get does return instance metadata, startup script included; Nodrik’s tool discards it — see below |
| Load balancing | networking |
nodrikNetworkingConfigViewer |
backend health with the reason, timeouts, balancing mode, health-check thresholds, URL-map routes | change any of them, or read instance internals |
The permission list of each role is in
grant-nodrik-access.sh
under FAMILY_ROLES, and the same list is what the product’s own test
suite asserts the tool calls — a permission no tool uses cannot be asked
for.
GKE: the API and the logs, never the cluster
Section titled “GKE: the API and the logs, never the cluster”Worth stating plainly, because it is the question every Kubernetes team asks first. Nodrik never connects to your cluster’s control plane. Not with this role, not with any other, not later.
What Nodrik reads for a GKE incident, on the four roles you already
granted, is what GKE already exports to Cloud Logging and Cloud
Monitoring: the Kubernetes events (kubectl describe‘s Events section),
the cluster autoscaler’s decisions and refusals, the nodes’ OOM kills,
container restarts and memory against limits, node conditions, and the
Kubernetes API server’s own audit log — which carries every Deployment
write with its body. That answers most of what breaks: a crash, an OOM
kill, a failing probe, an image that will not pull, a pod that cannot be
scheduled, an upgrade.
The kubernetes role above adds the cluster’s configuration from the
GKE API — container.clusters.get and container.clusters.list, and
nothing else. The GKE API has no pods, no Deployments, no ConfigMaps and
no Secrets; those live inside your cluster, behind its API server.
Two things about container.clusters.get are worth stating rather than
leaving you to find, because a reviewer who knows GKE will:
- It is the permission
gcloud container clusters get-credentialsuses. An identity holding it can generate a kubeconfig for your cluster and present itself to the API server. What it cannot do is read anything once there: the role carries no permission on any Kubernetes object, so under IAM and RBAC it is authorised for nothing inside the cluster beyond API discovery — no pods, no Secrets, no ConfigMaps, no workloads. Nodrik’s code, for its part, has no Kubernetes client at all; it only ever calls the GKE API and Cloud Logging. - On a cluster that still issues a legacy client certificate,
clusters.getreturns that certificate and its key inmasterAuth. Nodrik’s tool never prints that field, but the permission returns it, and on a cluster with legacy ABAC it is a credential. GKE has not issued one by default since 1.12; if yours still does, turn it off before granting this role.
Two roles Google offers would go further, and Nodrik will not ask for either:
roles/container.clusterViewerincludescontainer.clusters.connect, which exists solely to authenticate to a cluster’s control plane, and which this custom role deliberately omits.roles/container.vieweris 170 permissions, including reading ConfigMaps and creating token reviews.
What Nodrik cannot see as a result — pod phase, exit codes, an HPA’s own state — is named under “what would confirm it”, and the card is honest about the boundary rather than guessing across it.
Compute Engine: the role returns metadata, the tool discards it
Section titled “Compute Engine: the role returns metadata, the tool discards it”compute.instances.get returns the whole instance resource, and that
includes metadata.items — where startup-script, ssh-keys and, in
practice, secrets end up. A role that holds the permission can read it;
there is no narrower permission that returns the machine type without
the metadata.
What Nodrik’s tool does with the response is an allowlist of fields: machine type, status, scheduling, the managed instance group and its autoscaler, and recent zone operations. Metadata is never printed, never reaches the model and never reaches the transcript, and a test asserts that from the negative side. The distinction matters and is stated plainly: the permission allows reading a startup script; the tool does not, and the transcript you can read afterwards is the evidence.
The serial console (compute.instances.getSerialPortOutput), screenshots
(getScreenshot) and guest attributes (getGuestAttributes) need
permissions this role does not hold — roles/compute.viewer carries all
three, which is why Nodrik does not ask for it.
How to grant one
Section titled “How to grant one”The console offers the same three paths it offers for the four roles,
with your values filled in — open Settings › Projects › Grant and
add ?family=<name> to the address, or follow the link Nodrik leaves when
an investigation needed it.
By script, one flag, repeatable:
./grant-nodrik-access.sh \ --tenant-sa "$TENANT_SA" \ --topic "$TOPIC" \ --project "$PROJECT_ID" \ --family managed-sql \ --dry-runDefining a custom role needs iam.roles.create on the project, which
roles/resourcemanager.projectIamAdmin does not carry
(roles/iam.roleAdmin does). The person who granted the four roles is
frequently not the person who can define a fifth; the wizard says so
rather than failing generically, and the handoff link carries the family
so the right person lands on the right ledger.
With Terraform, one input:
module "nodrik" { source = "github.com/thoughtgears/nodrik-onboarding//terraform?ref=v0.2.0"
tenant_service_account = "tenant-acme-prod@tg-shard-N.iam.gserviceaccount.com" tenant_topic = "projects/tg-hub-N/topics/tenant-acme-prod-alerts" project_ids = ["my-production-project"] families = ["managed-sql"]}Your next plan shows one role and one binding per project and family,
and nothing else.
When Nodrik asks
Section titled “When Nodrik asks”Once, and only after it mattered. When an investigation ends without an answer and the alert was in a service whose settings Nodrik could not read, one notification appears in the console bell naming that investigation, saying what the role reads and what it cannot, and linking to the grant for that project. It is asked once per service per project, ever — five Cloud SQL alerts in a week do not produce five asks — and nothing waits on it: Nodrik keeps investigating that service without the role, just less well.
The offer then stands quietly on Settings › What Nodrik has seen, beside the service, where you can grant it later, press Don’t ask again, or — after that — Ask me again. Nodrik records that it asked and whether you declined. It never records that you granted: what Nodrik can read is checked live, every time, so a role you later remove in your own project is simply seen missing at the next check.
Verifying it
Section titled “Verifying it”The same check that verifies the four roles asks about these too, in one call, as your own tenant service account. Settings › Projects › Check again refreshes it, and every investigation re-checks before its first step: a setting Nodrik could read is one it reads, and one it could not is a sentence in the report rather than a guess.
Removing one
Section titled “Removing one”revoke-nodrik-access.sh removes every family binding it finds and
deletes the role definitions Nodrik created, whether or not you pass
--family — revocation should not require you to remember what you
granted. terraform destroy is the exact reverse of apply.