From 286a67d78c5be2b9ee39ed9fe26aa5a232058832 Mon Sep 17 00:00:00 2001 From: scott Date: Wed, 18 May 2022 20:23:16 +0800 Subject: [PATCH] Fix issue that Audit Server could not correctly encode DeleteOption --- .../src/k8s.io/apiserver/pkg/audit/request.go | 2 +- .../pkg/endpoints/handlers/delete.go | 8 +- .../pkg/endpoints/handlers/delete_test.go | 134 ++++++++++++++++++ 3 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete_test.go diff --git a/staging/src/k8s.io/apiserver/pkg/audit/request.go b/staging/src/k8s.io/apiserver/pkg/audit/request.go index 57a10e62b02..30755a8a568 100644 --- a/staging/src/k8s.io/apiserver/pkg/audit/request.go +++ b/staging/src/k8s.io/apiserver/pkg/audit/request.go @@ -239,7 +239,7 @@ func encodeObject(obj runtime.Object, gv schema.GroupVersion, serializer runtime return &runtime.Unknown{ Raw: buf.Bytes(), - ContentType: runtime.ContentTypeJSON, + ContentType: mediaType, }, nil } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go index 99979fc14b5..a7712f115fa 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go @@ -103,7 +103,7 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope *RequestSc trace.Step("Decoded delete options") objGV := gvk.GroupVersion() - audit.LogRequestObject(req.Context(), obj, objGV, scope.Resource, scope.Subresource, scope.Serializer) + audit.LogRequestObject(req.Context(), obj, objGV, scope.Resource, scope.Subresource, metainternalversionscheme.Codecs) trace.Step("Recorded the audit event") } else { if err := metainternalversionscheme.ParameterCodec.DecodeParameters(req.URL.Query(), scope.MetaGroupVersion, options); err != nil { @@ -238,8 +238,8 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope *RequestSc } // For backwards compatibility, we need to allow existing clients to submit per group DeleteOptions // It is also allowed to pass a body with meta.k8s.io/v1.DeleteOptions - defaultGVK := scope.Kind.GroupVersion().WithKind("DeleteOptions") - obj, gvk, err := scope.Serializer.DecoderToVersion(s.Serializer, defaultGVK.GroupVersion()).Decode(body, &defaultGVK, options) + defaultGVK := scope.MetaGroupVersion.WithKind("DeleteOptions") + obj, gvk, err := metainternalversionscheme.Codecs.DecoderToVersion(s.Serializer, defaultGVK.GroupVersion()).Decode(body, &defaultGVK, options) if err != nil { scope.err(err, w, req) return @@ -250,7 +250,7 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope *RequestSc } objGV := gvk.GroupVersion() - audit.LogRequestObject(req.Context(), obj, objGV, scope.Resource, scope.Subresource, scope.Serializer) + audit.LogRequestObject(req.Context(), obj, objGV, scope.Resource, scope.Subresource, metainternalversionscheme.Codecs) } else { if err := metainternalversionscheme.ParameterCodec.DecodeParameters(req.URL.Query(), scope.MetaGroupVersion, options); err != nil { err = errors.NewBadRequest(err.Error()) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete_test.go new file mode 100644 index 00000000000..edf764a1a04 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete_test.go @@ -0,0 +1,134 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package handlers + +import ( + "context" + "io" + "testing" + + metainternalversionscheme "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + auditapis "k8s.io/apiserver/pkg/apis/audit" + "k8s.io/apiserver/pkg/audit" + "k8s.io/utils/pointer" +) + +type mockCodecs struct { + serializer.CodecFactory + err error +} + +type mockCodec struct { + runtime.Codec + codecs *mockCodecs +} + +func (p mockCodec) Encode(obj runtime.Object, w io.Writer) error { + err := p.Codec.Encode(obj, w) + p.codecs.err = err + return err +} + +func (s *mockCodecs) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder { + out := s.CodecFactory.CodecForVersions(encoder, nil, gv, nil) + return &mockCodec{ + Codec: out, + codecs: s, + } +} + +func TestDeleteResourceAuditLogRequestObject(t *testing.T) { + + ctx := audit.WithAuditContext(context.TODO(), &audit.AuditContext{ + Event: &auditapis.Event{ + Level: auditapis.LevelRequestResponse, + }, + }) + + policy := metav1.DeletePropagationBackground + deleteOption := &metav1.DeleteOptions{ + GracePeriodSeconds: pointer.Int64Ptr(30), + PropagationPolicy: &policy, + } + + fakeCorev1GroupVersion := schema.GroupVersion{ + Group: "", + Version: "v1", + } + testScheme := runtime.NewScheme() + metav1.AddToGroupVersion(testScheme, fakeCorev1GroupVersion) + testCodec := serializer.NewCodecFactory(testScheme) + + tests := []struct { + name string + object runtime.Object + gv schema.GroupVersion + serializer serializer.CodecFactory + ok bool + }{ + { + name: "meta built-in Codec encode v1.DeleteOptions", + object: &metav1.DeleteOptions{ + GracePeriodSeconds: pointer.Int64Ptr(30), + PropagationPolicy: &policy, + }, + gv: metav1.SchemeGroupVersion, + serializer: metainternalversionscheme.Codecs, + ok: true, + }, + { + name: "fake corev1 registered codec encode v1 DeleteOptions", + object: &metav1.DeleteOptions{ + GracePeriodSeconds: pointer.Int64Ptr(30), + PropagationPolicy: &policy, + }, + gv: metav1.SchemeGroupVersion, + serializer: testCodec, + ok: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + + codecs := &mockCodecs{} + codecs.CodecFactory = test.serializer + + audit.LogRequestObject(ctx, deleteOption, test.gv, schema.GroupVersionResource{ + Group: "", + Version: "v1", + Resource: "pods", + }, "", codecs) + + err := codecs.err + if err != nil { + if test.ok { + t.Errorf("expect nil but got %#v", err) + } + t.Logf("encode object: %#v", err) + } else { + if !test.ok { + t.Errorf("expect err but got nil") + } + } + }) + } +}