From 5dcfaae7b90c4838e488eace376e05c9e807f23b Mon Sep 17 00:00:00 2001 From: kidddddddddddddddddddddd <1062602710@qq.com> Date: Wed, 2 Nov 2022 16:17:52 +0800 Subject: [PATCH] strict decode policy first --- .../apiserver/pkg/audit/policy/reader.go | 21 ++++++++++++++---- .../apiserver/pkg/audit/policy/reader_test.go | 22 +++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/audit/policy/reader.go b/staging/src/k8s.io/apiserver/pkg/audit/policy/reader.go index e4d5b10fb9b..5383d479d1b 100644 --- a/staging/src/k8s.io/apiserver/pkg/audit/policy/reader.go +++ b/staging/src/k8s.io/apiserver/pkg/audit/policy/reader.go @@ -20,12 +20,13 @@ import ( "fmt" "io/ioutil" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" auditinternal "k8s.io/apiserver/pkg/apis/audit" auditv1 "k8s.io/apiserver/pkg/apis/audit/v1" "k8s.io/apiserver/pkg/apis/audit/validation" "k8s.io/apiserver/pkg/audit" - "k8s.io/klog/v2" ) @@ -61,11 +62,23 @@ func LoadPolicyFromFile(filePath string) (*auditinternal.Policy, error) { func LoadPolicyFromBytes(policyDef []byte) (*auditinternal.Policy, error) { policy := &auditinternal.Policy{} - decoder := audit.Codecs.UniversalDecoder(apiGroupVersions...) + strictDecoder := serializer.NewCodecFactory(audit.Scheme, serializer.EnableStrict).UniversalDecoder() - _, gvk, err := decoder.Decode(policyDef, nil, policy) + // Try strict decoding first. + _, gvk, err := strictDecoder.Decode(policyDef, nil, policy) if err != nil { - return nil, fmt.Errorf("failed decoding: %v", err) + if !runtime.IsStrictDecodingError(err) { + return nil, fmt.Errorf("failed decoding: %w", err) + } + var ( + lenientDecoder = audit.Codecs.UniversalDecoder(apiGroupVersions...) + lenientErr error + ) + _, gvk, lenientErr = lenientDecoder.Decode(policyDef, nil, policy) + if lenientErr != nil { + return nil, fmt.Errorf("failed lenient decoding: %w", lenientErr) + } + klog.Warningf("Audit policy contains errors, falling back to lenient decoding: %v", err) } // Ensure the policy file contained an apiVersion and kind. diff --git a/staging/src/k8s.io/apiserver/pkg/audit/policy/reader_test.go b/staging/src/k8s.io/apiserver/pkg/audit/policy/reader_test.go index 83410031c83..32bcdfde7a5 100644 --- a/staging/src/k8s.io/apiserver/pkg/audit/policy/reader_test.go +++ b/staging/src/k8s.io/apiserver/pkg/audit/policy/reader_test.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apiserver/pkg/apis/audit" + // import to call webhook's init() function to register audit.Policy to schema _ "k8s.io/apiserver/plugin/pkg/audit/webhook" @@ -70,6 +71,18 @@ rules: - level: Metadata ` +const policyWithUnknownField = ` +apiVersion: audit.k8s.io/v1 +kind: Policy +rules: +- level: None + resources: + - group: coordination.k8s.io + resources: + - "leases" + verbs: ["watch", "get", "list"] # invalid indentation on verbs +` + var expectedPolicy = &audit.Policy{ Rules: []audit.PolicyRule{{ Level: audit.LevelNone, @@ -113,6 +126,15 @@ func TestParsePolicyWithNoVersionOrKind(t *testing.T) { assert.Contains(t, err.Error(), "unknown group version field") } +func TestParsePolicyWithUnknownField(t *testing.T) { + f, err := writePolicy(t, policyWithUnknownField) + require.NoError(t, err) + defer os.Remove(f) + + _, err = LoadPolicyFromFile(f) + require.NoError(t, err) +} + func TestPolicyCntCheck(t *testing.T) { var testCases = []struct { caseName, policy string