k8s.io/apiserver@v0.31.1/plugin/pkg/audit/truncate/truncate_test.go (about)

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package truncate
    18  
    19  import (
    20  	"strings"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/require"
    24  
    25  	"k8s.io/apimachinery/pkg/runtime"
    26  	auditinternal "k8s.io/apiserver/pkg/apis/audit"
    27  	auditv1 "k8s.io/apiserver/pkg/apis/audit/v1"
    28  	"k8s.io/apiserver/plugin/pkg/audit/fake"
    29  	// Importing just for the schema definitions.
    30  	_ "k8s.io/apiserver/plugin/pkg/audit/webhook"
    31  )
    32  
    33  var (
    34  	defaultConfig = Config{
    35  		MaxBatchSize: 4 * 1024 * 1024,
    36  		MaxEventSize: 100 * 1024,
    37  	}
    38  )
    39  
    40  func TestTruncatingEvents(t *testing.T) {
    41  	testCases := []struct {
    42  		desc          string
    43  		event         *auditinternal.Event
    44  		wantDropped   bool
    45  		wantTruncated bool
    46  	}{
    47  		{
    48  			desc:  "Empty event should not be truncated",
    49  			event: &auditinternal.Event{},
    50  		},
    51  		{
    52  			desc: "Event with too large body should be truncated",
    53  			event: &auditinternal.Event{
    54  				Level: auditinternal.LevelRequest,
    55  				RequestObject: &runtime.Unknown{
    56  					Raw: []byte("\"" + strings.Repeat("A", int(defaultConfig.MaxEventSize)) + "\""),
    57  				},
    58  			},
    59  			wantTruncated: true,
    60  		},
    61  		{
    62  			desc: "Event with too large metadata should be dropped",
    63  			event: &auditinternal.Event{
    64  				Annotations: map[string]string{
    65  					"key": strings.Repeat("A", int(defaultConfig.MaxEventSize)),
    66  				},
    67  			},
    68  			wantDropped: true,
    69  		},
    70  	}
    71  
    72  	for _, tc := range testCases {
    73  		tc := tc
    74  		t.Run(tc.desc, func(t *testing.T) {
    75  			t.Parallel()
    76  
    77  			var event *auditinternal.Event
    78  
    79  			fb := &fake.Backend{
    80  				OnRequest: func(events []*auditinternal.Event) {
    81  					require.Len(t, events, 1, "Expected single event in batch")
    82  					event = events[0]
    83  				},
    84  			}
    85  			b := NewBackend(fb, defaultConfig, auditv1.SchemeGroupVersion)
    86  			b.ProcessEvents(tc.event)
    87  
    88  			require.Equal(t, !tc.wantDropped, event != nil, "Incorrect event presence")
    89  			if tc.wantTruncated {
    90  				require.Equal(t, annotationValue, event.Annotations[annotationKey], "Annotation should be present")
    91  				require.Nil(t, event.RequestObject, "After truncation request should be nil")
    92  				require.Nil(t, event.ResponseObject, "After truncation response should be nil")
    93  			}
    94  		})
    95  	}
    96  }
    97  
    98  func TestSplittingBatches(t *testing.T) {
    99  	testCases := []struct {
   100  		desc           string
   101  		config         Config
   102  		events         []*auditinternal.Event
   103  		wantBatchCount int
   104  	}{
   105  		{
   106  			desc:           "Events fitting in one batch should not be split",
   107  			config:         defaultConfig,
   108  			events:         []*auditinternal.Event{{}},
   109  			wantBatchCount: 1,
   110  		},
   111  		{
   112  			desc: "Events not fitting in one batch should be split",
   113  			config: Config{
   114  				MaxEventSize: defaultConfig.MaxEventSize,
   115  				MaxBatchSize: 1,
   116  			},
   117  			events: []*auditinternal.Event{
   118  				{Annotations: map[string]string{"key": strings.Repeat("A", int(50))}},
   119  				{Annotations: map[string]string{"key": strings.Repeat("A", int(50))}},
   120  			},
   121  			wantBatchCount: 2,
   122  		},
   123  	}
   124  	for _, tc := range testCases {
   125  		tc := tc
   126  		t.Run(tc.desc, func(t *testing.T) {
   127  			t.Parallel()
   128  
   129  			var gotBatchCount int
   130  			fb := &fake.Backend{
   131  				OnRequest: func(events []*auditinternal.Event) {
   132  					gotBatchCount++
   133  				},
   134  			}
   135  			b := NewBackend(fb, tc.config, auditv1.SchemeGroupVersion)
   136  			b.ProcessEvents(tc.events...)
   137  
   138  			require.Equal(t, tc.wantBatchCount, gotBatchCount)
   139  		})
   140  	}
   141  }