diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/audit.go b/staging/src/k8s.io/apiserver/pkg/server/options/audit.go index af5b06a5bd7..74e2e71971b 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/audit.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/audit.go @@ -154,6 +154,10 @@ func NewAuditOptions() *AuditOptions { GroupVersionString: "audit.k8s.io/v1", }, LogOptions: AuditLogOptions{ + MaxSize: 100, + MaxAge: 366, + MaxBackups: 100, + Format: pluginlog.FormatJson, BatchOptions: AuditBatchOptions{ Mode: ModeBlocking, @@ -436,11 +440,11 @@ func (o *AuditLogOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.Path, "audit-log-path", o.Path, "If set, all requests coming to the apiserver will be logged to this file. '-' means standard out.") fs.IntVar(&o.MaxAge, "audit-log-maxage", o.MaxAge, - "The maximum number of days to retain old audit log files based on the timestamp encoded in their filename.") + "The maximum number of days to retain old audit log files based on the timestamp encoded in their filename. Setting a value of 0 means old audit log files are not removed based on age.") fs.IntVar(&o.MaxBackups, "audit-log-maxbackup", o.MaxBackups, "The maximum number of old audit log files to retain. Setting a value of 0 will mean there's no restriction on the number of files.") fs.IntVar(&o.MaxSize, "audit-log-maxsize", o.MaxSize, - "The maximum size in megabytes of the audit log file before it gets rotated.") + "The maximum size in megabytes of the audit log file before it gets rotated. Setting to 0 disables rotation (not recommended).") fs.StringVar(&o.Format, "audit-log-format", o.Format, "Format of saved audits. \"legacy\" indicates 1-line text format for each event."+ " \"json\" indicates structured json format. Known formats are "+ @@ -506,6 +510,10 @@ func (o *AuditLogOptions) getWriter() (io.Writer, error) { return nil, fmt.Errorf("ensureLogFile: %w", err) } + if o.MaxSize == 0 { + return os.OpenFile(o.Path, os.O_APPEND|os.O_WRONLY, 0644) + } + return &lumberjack.Logger{ Filename: o.Path, MaxAge: o.MaxAge, diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/audit_test.go b/staging/src/k8s.io/apiserver/pkg/server/options/audit_test.go index 78fdc721055..16425d88b57 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/audit_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/audit_test.go @@ -38,10 +38,10 @@ func TestAuditValidOptions(t *testing.T) { auditPath := filepath.Join(tmpDir, "audit") webhookConfig := makeTmpWebhookConfig(t) - defer os.Remove(webhookConfig) + defer func() { _ = os.Remove(webhookConfig) }() policy := makeTmpPolicy(t) - defer os.Remove(policy) + defer func() { _ = os.Remove(policy) }() testCases := []struct { name string @@ -177,14 +177,46 @@ func TestAuditValidOptions(t *testing.T) { if options.LogOptions.Path == "-" { assert.Equal(t, os.Stdout, w) assert.NoFileExists(t, options.LogOptions.Path) - } else { - assert.IsType(t, (*lumberjack.Logger)(nil), w) + } else if options.LogOptions.MaxSize == 0 { + // When MaxSize is 0, we return a raw file writer (os.File) for unlimited size + file, ok := w.(*os.File) + assert.True(t, ok, "Writer should be of type *os.File when MaxSize is 0") assert.FileExists(t, options.LogOptions.Path) + assert.NoError(t, file.Close()) + } else { + logger, ok := w.(*lumberjack.Logger) + assert.True(t, ok, "Writer should be of type *lumberjack.Logger") + assert.FileExists(t, options.LogOptions.Path) + assert.Equal(t, options.LogOptions.MaxSize, logger.MaxSize) } }) } } +func TestAuditLogMaxSizeZero(t *testing.T) { + tmpDir := t.TempDir() + auditPath := filepath.Join(tmpDir, "audit") + policy := makeTmpPolicy(t) + defer func() { _ = os.Remove(policy) }() + + o := NewAuditOptions() + o.LogOptions.Path = auditPath + o.PolicyFile = policy + o.LogOptions.MaxSize = 0 + + w, err := o.LogOptions.getWriter() + require.NoError(t, err) + require.NotNil(t, w) + + // When MaxSize is 0, we return a raw file writer (os.File) for unlimited size + file, ok := w.(*os.File) + require.True(t, ok, "Should be an os.File when MaxSize is 0") + + // Verify that the file was opened correctly + require.NotNil(t, file) + require.NoError(t, file.Close()) +} + func TestAuditInvalidOptions(t *testing.T) { tmpDir := t.TempDir() auditPath := filepath.Join(tmpDir, "audit")