diff --git a/event-exporter/sinks/stackdriver/log_entry_factory_test.go b/event-exporter/sinks/stackdriver/log_entry_factory_test.go index 46637852a..991ca57d5 100644 --- a/event-exporter/sinks/stackdriver/log_entry_factory_test.go +++ b/event-exporter/sinks/stackdriver/log_entry_factory_test.go @@ -111,6 +111,7 @@ func TestFromEvent(t *testing.T) { { desc: "k8s pod event with pod labels", event: &corev1.Event{ + ObjectMeta: metav1.ObjectMeta{Namespace: "test_namespace"}, Type: "Normal", InvolvedObject: involvedPodObject, LastTimestamp: lastTimestamp, diff --git a/event-exporter/sinks/stackdriver/monitored_resource_factory.go b/event-exporter/sinks/stackdriver/monitored_resource_factory.go index 51099572c..8da19ef4d 100644 --- a/event-exporter/sinks/stackdriver/monitored_resource_factory.go +++ b/event-exporter/sinks/stackdriver/monitored_resource_factory.go @@ -74,7 +74,15 @@ func (f *monitoredResourceFactory) resourceFromEvent(event *corev1.Event) *sd.Mo switch event.InvolvedObject.Kind { case pod: - monitoredResource = f.buildPodMonitoredResource(event) + // The event's own metadata.namespace is the RBAC-enforced source + // of truth for where the event was created. Only emit a pod-scoped + // resource when the involved object's namespace agrees with it; + // otherwise fall back to the default cluster-scoped resource. + if event.Namespace != "" && event.Namespace == event.InvolvedObject.Namespace { + monitoredResource = f.buildPodMonitoredResource(event) + } else { + monitoredResource = f.defaultResource + } case node: monitoredResource = f.buildNodeMonitoredResource(event) default: @@ -86,7 +94,7 @@ func (f *monitoredResourceFactory) resourceFromEvent(event *corev1.Event) *sd.Mo func (f *monitoredResourceFactory) buildPodMonitoredResource(event *corev1.Event) *sd.MonitoredResource { labels := copyMap(f.commonLabels) labels[podName] = event.InvolvedObject.Name - labels[namespaceName] = event.InvolvedObject.Namespace + labels[namespaceName] = event.Namespace return &sd.MonitoredResource{ Type: k8sPod, diff --git a/event-exporter/sinks/stackdriver/monitored_resource_factory_test.go b/event-exporter/sinks/stackdriver/monitored_resource_factory_test.go index edd7034c7..ccdd3891c 100644 --- a/event-exporter/sinks/stackdriver/monitored_resource_factory_test.go +++ b/event-exporter/sinks/stackdriver/monitored_resource_factory_test.go @@ -8,6 +8,7 @@ import ( "fmt" sd "google.golang.org/api/logging/v2" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestMonitoredResourceFromEvent(t *testing.T) { @@ -31,8 +32,11 @@ func TestMonitoredResourceFromEvent(t *testing.T) { }, }, { + // Pod event whose involvedObject namespace matches the event's + // own metadata namespace is attributed to the pod. config: newTypesConfig, event: &corev1.Event{ + ObjectMeta: metav1.ObjectMeta{Namespace: "test_pod_namespace"}, InvolvedObject: corev1.ObjectReference{Kind: pod, Name: "test_pod_name", Namespace: "test_pod_namespace"}, }, wanted: &sd.MonitoredResource{ @@ -46,6 +50,40 @@ func TestMonitoredResourceFromEvent(t *testing.T) { }, }, }, + { + // Pod event whose involvedObject namespace disagrees with the + // event's own metadata namespace must not be attributed to the + // claimed pod; fall back to the cluster resource. + config: newTypesConfig, + event: &corev1.Event{ + ObjectMeta: metav1.ObjectMeta{Namespace: "user_namespace"}, + InvolvedObject: corev1.ObjectReference{Kind: pod, Name: "test_pod_name", Namespace: "kube-system"}, + }, + wanted: &sd.MonitoredResource{ + Type: k8sCluster, + Labels: map[string]string{ + clusterName: newTypesConfig.clusterName, + location: newTypesConfig.location, + projectID: newTypesConfig.projectID, + }, + }, + }, + { + // Pod event with no event-level namespace cannot be attributed + // to a pod; fall back to the cluster resource. + config: newTypesConfig, + event: &corev1.Event{ + InvolvedObject: corev1.ObjectReference{Kind: pod, Name: "test_pod_name", Namespace: "kube-system"}, + }, + wanted: &sd.MonitoredResource{ + Type: k8sCluster, + Labels: map[string]string{ + clusterName: newTypesConfig.clusterName, + location: newTypesConfig.location, + projectID: newTypesConfig.projectID, + }, + }, + }, { config: newTypesConfig, event: &corev1.Event{