Skip to content

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 get or list. Google’s predefined viewers for these services carry verbs that are not reads — cloudsql.viewer can export the database, compute.viewer can 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’s families input;
  • removed by the revoke script and by terraform destroy, which delete the role definition too, so nothing of ours is left in your project.
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-credentials uses. 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.get returns that certificate and its key in masterAuth. 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.clusterViewer includes container.clusters.connect, which exists solely to authenticate to a cluster’s control plane, and which this custom role deliberately omits.
  • roles/container.viewer is 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.

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:

Terminal window
./grant-nodrik-access.sh \
--tenant-sa "$TENANT_SA" \
--topic "$TOPIC" \
--project "$PROJECT_ID" \
--family managed-sql \
--dry-run

Defining 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.

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.

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.

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.