Skip to content

lookout state wi

When a GKE pod gets 403s or metadata-server errors calling GCP APIs, verify the Workload Identity chain — KSA annotation (iam.gke.io/gcp-service-account) → roles/iam.workloadIdentityUser binding on the GSA — reporting only the broken links; vanilla clusters report an explicit unavailable.

MCP tool: k8s_workload_identity

Terminal window
lookout state wi [flags]
FlagTypeDefaultMeaning
--namespacestring—limit the scan to one namespace
-Abool—scan all namespaces
--workloadstring—target one workload as <Kind>/<namespace>/<name>, e.g. Deployment/prod/api
--sinceduration—how far back to look (0 = command default)
--formatstringlogfmtoutput format: logfmt|json (one record per line either way)
--timeoutduration10sabort the invocation after this long (exit 1)
--kubeconfigstring—path to a kubeconfig file, instead of $KUBECONFIG / ~/.kube/config
--contextstring—kubeconfig context to read, instead of its current-context. Selects a cluster for THIS invocation only — nothing is written back — so concurrent invocations can target different clusters. Reported as context=<name> in the summary line
--exemptionsstring—path to a git-reviewed exemption file (YAML); covered findings are ANNOTATED with their reason and expiry and counted as exempt=<n> in the summary, never dropped

Every kind= this command can emit, and the severities it carries them at. Nothing else appears in its output; a kind absent from a run means the check looked and found nothing. See the finding-kind glossary for the whole vocabulary.

KindSeverityClaim
wi.gsa_missingcriticalthe annotated Google service account does not exist — every GCP call from these pods fails
wi.unboundcriticalthe KSA annotates a GSA but the roles/iam.workloadIdentityUser binding is missing or malformed
wi.unannotated_useinfoa pod sets GOOGLE_APPLICATION_CREDENTIALS but its ServiceAccount carries no Workload Identity annotation
cloud.unavailableinfothe cloud capability this check needs is unavailable, so nothing was examined — an explicit degradation record, never silence

Beyond the shared envelope fields (kind, severity, namespace, kind_of_object, name, reason, message, fingerprint, exempt_reason, exempt_expires):

FieldMeaning
gsathe cloud identity (GSA email) the ServiceAccount’s annotation claims
podshow many in-scope pods run as the affected ServiceAccount
problemmachine-matchable problem code from the provider (e.g. no-workload-identity-binding)
containercontainer carrying the GOOGLE_APPLICATION_CREDENTIALS env var
envthe credential-file env var found (GOOGLE_APPLICATION_CREDENTIALS)
capabilitycloud.unavailable: the provider capability this command needed (workload-identity)
providercloud.unavailable: the provider that was asked
unavailablesummary-line note: why the cloud read could not be served

Output: one finding per line (logfmt; —format=json for one JSON object per line), keys in fixed order; healthy resources emit nothing. The final line is always the summary: scanned= findings= elapsed= — findings=0 with a summary present means “scanned and healthy”; a stream without a summary line is void. Exit 0 data, 1 runtime error (diagnostics on stderr only), 2 usage.

Terminal window
lookout state wi
lookout state wi --namespace=prod
lookout state wi --workload=Deployment/prod/api --format=json