diff --git a/admission/rules/v1/__debug_bin719326235 b/admission/rules/v1/__debug_bin719326235 new file mode 100755 index 0000000..5e4dce7 Binary files /dev/null and b/admission/rules/v1/__debug_bin719326235 differ diff --git a/admission/rules/v1/helpers.go b/admission/rules/v1/helpers.go index e278be2..b0b1542 100644 --- a/admission/rules/v1/helpers.go +++ b/admission/rules/v1/helpers.go @@ -2,11 +2,11 @@ package rules import ( "context" + "encoding/json" "fmt" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apiserver/pkg/admission" "k8s.io/client-go/kubernetes" ) @@ -71,17 +71,27 @@ func resolveJob(ownerRef metav1.OwnerReference, namespace string, clientset kube } // GetContainerNameFromExecToPodEvent returns the container name from the admission event for exec operations. -func GetContainerNameFromExecToPodEvent(event admission.Attributes) string { - if event.GetSubresource() == "exec" { - if obj := event.GetObject(); obj != nil { - if unstructuredObj, ok := obj.(*unstructured.Unstructured); ok { - if object, ok := unstructuredObj.Object["object"].(map[string]interface{}); ok { - if containerName, ok := object["container"].(string); ok { - return containerName - } - } - } - } +func GetContainerNameFromExecToPodEvent(event admission.Attributes) (string, error) { + if event.GetSubresource() != "exec" { + return "", fmt.Errorf("not an exec subresource") + } + + obj := event.GetObject() + if obj == nil { + return "", fmt.Errorf("event object is nil") } - return "" + + // Marshal the unstructured object into JSON + rawData, err := json.Marshal(obj) + if err != nil { + return "", fmt.Errorf("failed to marshal event object: %v", err) + } + + // Unmarshal the JSON into a PodExecOptions object + var podExecOptions v1.PodExecOptions + if err := json.Unmarshal(rawData, &podExecOptions); err != nil { + return "", fmt.Errorf("failed to unmarshal into PodExecOptions: %v", err) + } + + return podExecOptions.Container, nil } diff --git a/admission/rules/v1/r2000_exec_to_pod.go b/admission/rules/v1/r2000_exec_to_pod.go index f367a63..9824a89 100644 --- a/admission/rules/v1/r2000_exec_to_pod.go +++ b/admission/rules/v1/r2000_exec_to_pod.go @@ -77,7 +77,11 @@ func (rule *R2000ExecToPod) ProcessEvent(event admission.Attributes, access inte return nil } - containerName := GetContainerNameFromExecToPodEvent(event) + containerName, err := GetContainerNameFromExecToPodEvent(event) + if err != nil { + logger.L().Error("Failed to get container name from exec to pod event", helpers.Error(err)) + containerName = "" + } ruleFailure := GenericRuleFailure{ BaseRuntimeAlert: apitypes.BaseRuntimeAlert{ diff --git a/admission/rules/v1/r2000_exec_to_pod_test.go b/admission/rules/v1/r2000_exec_to_pod_test.go index 88c8aad..408c9c6 100644 --- a/admission/rules/v1/r2000_exec_to_pod_test.go +++ b/admission/rules/v1/r2000_exec_to_pod_test.go @@ -15,7 +15,14 @@ func TestR2000(t *testing.T) { event := admission.NewAttributesRecord( &unstructured.Unstructured{ Object: map[string]interface{}{ - "kind": "PodExecOptions", + "kind": "PodExecOptions", + "apiVersion": "v1", + "command": []interface{}{"bash"}, + "container": "test-container", + "stdin": true, + "stdout": true, + "stderr": true, + "tty": true, }, }, nil, @@ -27,7 +34,7 @@ func TestR2000(t *testing.T) { schema.GroupVersionResource{ Resource: "pods", }, - "", + "exec", admission.Create, nil, false, @@ -41,6 +48,7 @@ func TestR2000(t *testing.T) { result := rule.ProcessEvent(event, objectcache.KubernetesCacheMockImpl{}) assert.NotNil(t, result) + assert.Equal(t, "test-container", result.GetRuntimeAlertK8sDetails().ContainerName) assert.Equal(t, "test-workload", result.GetRuntimeAlertK8sDetails().WorkloadName) assert.Equal(t, "test-namespace", result.GetRuntimeAlertK8sDetails().WorkloadNamespace) assert.Equal(t, "ReplicaSet", result.GetRuntimeAlertK8sDetails().WorkloadKind)