Skip to content

Tighten resource attribution in the Stackdriver event sink#1186

Open
erain wants to merge 2 commits into
GoogleCloudPlatform:masterfrom
erain:event-resource-attribution-hardening
Open

Tighten resource attribution in the Stackdriver event sink#1186
erain wants to merge 2 commits into
GoogleCloudPlatform:masterfrom
erain:event-resource-attribution-hardening

Conversation

@erain
Copy link
Copy Markdown
Contributor

@erain erain commented May 12, 2026

Summary

When the event-exporter maps a corev1.Event onto a Stackdriver MonitoredResource, the Pod/Node labels are taken from the event's involvedObject reference. These reference fields are not cross-checked against the event's own metadata.namespace, which is the value the API server validates when an event is created.

This change adds that cross-check inside resourceFromEvent:

  • Pod events must satisfy event.Namespace != \"\" and event.Namespace == event.InvolvedObject.Namespace. When the check passes, namespace_name is sourced from event.Namespace directly. Otherwise the entry falls back to the default cluster-scoped resource.
  • Node events (which have no per-event namespace to compare against) are attributed to k8s_node only when the event originates from one of default, kube-system, or kube-node-lease. Otherwise the entry falls back to the default cluster-scoped resource.

The fallback preserves the log content under the cluster resource, so events that don't pass the check are still exported and inspectable; they just stop being attributed to the workload they reference.

Test plan

  • go test -mod=vendor ./... in event-exporter/ is green.
  • monitored_resource_factory_test.go gains coverage for: pod event whose event namespace disagrees with the involved object, pod event with empty event namespace, node event in trusted namespace, node event in untrusted namespace.
  • log_entry_factory_test.go cases updated to populate event.Namespace consistent with the new requirement; pod-label enrichment path still exercised end-to-end.

erain added 2 commits May 12, 2026 15:58
When mapping a corev1.Event onto a Stackdriver MonitoredResource, only
emit a Pod- or Node-scoped resource when the event's own metadata
namespace agrees with the involvedObject reference:

  - For Pod events, require event.Namespace == event.InvolvedObject.Namespace
    (and use event.Namespace for the namespace_name label, since that is
    the value the API server validated against RBAC).
  - For Node events, restrict node attribution to events originating in
    namespaces where node-scoped events are expected (default,
    kube-system, kube-node-lease).

Events that fail the check are still exported, but fall back to the
default cluster-scoped resource so that the log content remains
visible without being attributed to an unrelated workload.

Updates the existing tests to populate the event namespace and adds
cases that cover the new fallback paths.
"default" is writable by ordinary workloads under standard RBAC, so
allowing node attribution from there leaves room for events created in
"default" to be attributed to an arbitrary node. Drop it from the
trusted set so that only "kube-system" and "kube-node-lease"
produce a node-scoped MonitoredResource; everything else falls back to
the cluster-scoped resource.

Updates the resource-factory tests so that node events from "default"
exercise the fallback, and the log-entry factory tests use a trusted
system namespace for their node fixtures.
@erain
Copy link
Copy Markdown
Contributor Author

erain commented May 13, 2026

Pushed f85462c to address the review feedback:

  • Dropped default from the trusted set in monitored_resource_factory.go; only kube-system and kube-node-lease now produce a node-scoped MonitoredResource. Pod attribution is unchanged (still requires event.Namespace != "" and event.Namespace == event.InvolvedObject.Namespace, with namespace_name sourced from event.Namespace).
  • monitored_resource_factory_test.go: the previous defaultk8s_node case now asserts the cluster fallback; a kube-node-leasek8s_node case is added so both trusted namespaces are covered.
  • log_entry_factory_test.go: node fixtures switched from default to kube-system so the trusted-namespace path is still exercised.

go test -mod=vendor ./... from event-exporter/:

?   	github.com/GoogleCloudPlatform/k8s-stackdriver/event-exporter	[no test files]
ok  	github.com/GoogleCloudPlatform/k8s-stackdriver/event-exporter/kubernetes/podlabels	(cached)
?   	github.com/GoogleCloudPlatform/k8s-stackdriver/event-exporter/kubernetes/watchers	[no test files]
ok  	github.com/GoogleCloudPlatform/k8s-stackdriver/event-exporter/kubernetes/watchers/events	(cached)
?   	github.com/GoogleCloudPlatform/k8s-stackdriver/event-exporter/sinks	[no test files]
ok  	github.com/GoogleCloudPlatform/k8s-stackdriver/event-exporter/sinks/stackdriver	0.820s
?   	github.com/GoogleCloudPlatform/k8s-stackdriver/event-exporter/utils	[no test files]

@JeffLuoo
Copy link
Copy Markdown
Contributor

/lgtm
/approve

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants