Skip to content

lookout state webhooks

When creates/updates hang or fail cluster-wide with “failed calling webhook”, or before relying on a policy engine: audit every admission webhook — dead backends × failurePolicy (Fail + dead backend rejects every matching admission), the namespace/rule blast radius, timeout stall risk, CA-bundle expiry. The full check; health’s webhooks category delegates here.

MCP tool: k8s_admission_webhooks

Terminal window
lookout state webhooks [flags]
FlagTypeDefaultMeaning
--cert-warnduration720hreport webhook CA bundles expiring within this window
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
webhook.failing_closedcriticalthe webhook has no working backend and failurePolicy=Fail: every gated write is rejected cluster-wide
webhook.dead_backendwarningthe webhook’s service backend is missing, has no ready endpoints, or does not serve the named port
webhook.slow_riskinfothe webhook’s timeout is long enough to slow every gated write if the backend degrades
webhook.ca_expiredcriticalthe webhook’s caBundle has expired: the API server cannot verify it
webhook.ca_expiringwarningthe webhook’s caBundle expires within —cert-warn

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

FieldMeaning
webhookadmission webhook as <configuration>/<webhook name>
serviceservice backend the webhook points at, as <namespace>/<name>
backendwhy the backend is dead: service missing, no ready endpoints, or port <p> not on service
gatesnamespaces the webhook gates, from namespaceSelector: all namespaces, or <matched>/<total> namespaces with up to 5 names
rulescompact operations/resources summary of the webhook’s rules, e.g. “CREATE,UPDATE pods,deployments.apps”
object_selectorthe webhook’s objectSelector, when one is set
timeoutwebhook timeoutSeconds as <n>s (nil defaults to the API’s 10s)
subjectCA-bundle certificate subject (CN when set); never key material
not_afterCA-bundle certificate NotAfter, RFC 3339
days_leftwhole days until NotAfter (negative = expired)

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 webhooks
lookout state webhooks --format=json --cert-warn=336h