Merge pull request #107207 from ehashman/deprecate-log-sanitization

Deprecate dynamic log sanitization
This commit is contained in:
Kubernetes Prow Robot 2022-01-15 15:19:26 -08:00 committed by GitHub
commit 22a03f893d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 6 additions and 551 deletions

View File

@ -218,7 +218,6 @@ var (
"Logging.Options.JSON.InfoBufferSize.Quantity.i.value", "Logging.Options.JSON.InfoBufferSize.Quantity.i.value",
"Logging.Options.JSON.InfoBufferSize.Quantity.s", "Logging.Options.JSON.InfoBufferSize.Quantity.s",
"Logging.Options.JSON.SplitStream", "Logging.Options.JSON.SplitStream",
"Logging.Sanitization",
"Logging.VModule[*].FilePattern", "Logging.VModule[*].FilePattern",
"Logging.VModule[*].Verbosity", "Logging.VModule[*].Verbosity",
"Logging.Verbosity", "Logging.Verbosity",

View File

@ -235,7 +235,6 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
Logging: componentbaseconfigv1alpha1.LoggingConfiguration{ Logging: componentbaseconfigv1alpha1.LoggingConfiguration{
Format: "", Format: "",
FlushFrequency: 5 * time.Second, FlushFrequency: 5 * time.Second,
Sanitization: false,
}, },
EnableSystemLogHandler: utilpointer.Bool(false), EnableSystemLogHandler: utilpointer.Bool(false),
ShutdownGracePeriod: zeroDuration, ShutdownGracePeriod: zeroDuration,
@ -333,7 +332,6 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
Logging: componentbaseconfigv1alpha1.LoggingConfiguration{ Logging: componentbaseconfigv1alpha1.LoggingConfiguration{
Format: "text", Format: "text",
FlushFrequency: 5 * time.Second, FlushFrequency: 5 * time.Second,
Sanitization: false,
}, },
EnableSystemLogHandler: utilpointer.Bool(false), EnableSystemLogHandler: utilpointer.Bool(false),
ReservedMemory: []v1beta1.MemoryReservation{}, ReservedMemory: []v1beta1.MemoryReservation{},
@ -476,7 +474,6 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
Logging: componentbaseconfigv1alpha1.LoggingConfiguration{ Logging: componentbaseconfigv1alpha1.LoggingConfiguration{
Format: "json", Format: "json",
FlushFrequency: 5 * time.Second, FlushFrequency: 5 * time.Second,
Sanitization: true,
}, },
EnableSystemLogHandler: utilpointer.Bool(true), EnableSystemLogHandler: utilpointer.Bool(true),
ShutdownGracePeriod: metav1.Duration{Duration: 60 * time.Second}, ShutdownGracePeriod: metav1.Duration{Duration: 60 * time.Second},
@ -623,7 +620,6 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
Logging: componentbaseconfigv1alpha1.LoggingConfiguration{ Logging: componentbaseconfigv1alpha1.LoggingConfiguration{
Format: "json", Format: "json",
FlushFrequency: 5 * time.Second, FlushFrequency: 5 * time.Second,
Sanitization: true,
}, },
EnableSystemLogHandler: utilpointer.Bool(true), EnableSystemLogHandler: utilpointer.Bool(true),
ShutdownGracePeriod: metav1.Duration{Duration: 60 * time.Second}, ShutdownGracePeriod: metav1.Duration{Duration: 60 * time.Second},

View File

@ -104,9 +104,6 @@ type LoggingConfiguration struct {
// VModule overrides the verbosity threshold for individual files. // VModule overrides the verbosity threshold for individual files.
// Only supported for "text" log format. // Only supported for "text" log format.
VModule VModuleConfiguration VModule VModuleConfiguration
// [Experimental] When enabled prevents logging of fields tagged as sensitive (passwords, keys, tokens).
// Runtime log sanitization may introduce significant computation overhead and therefore should not be enabled in production.`)
Sanitization bool
// [Experimental] Options holds additional parameters that are specific // [Experimental] Options holds additional parameters that are specific
// to the different logging formats. Only the options for the selected // to the different logging formats. Only the options for the selected
// format get used, but all of them get validated. // format get used, but all of them get validated.

View File

@ -101,9 +101,6 @@ type LoggingConfiguration struct {
// VModule overrides the verbosity threshold for individual files. // VModule overrides the verbosity threshold for individual files.
// Only supported for "text" log format. // Only supported for "text" log format.
VModule VModuleConfiguration `json:"vmodule,omitempty"` VModule VModuleConfiguration `json:"vmodule,omitempty"`
// [Experimental] When enabled prevents logging of fields tagged as sensitive (passwords, keys, tokens).
// Runtime log sanitization may introduce significant computation overhead and therefore should not be enabled in production.`)
Sanitization bool `json:"sanitization,omitempty"`
// [Experimental] Options holds additional parameters that are specific // [Experimental] Options holds additional parameters that are specific
// to the different logging formats. Only the options for the selected // to the different logging formats. Only the options for the selected
// format get used, but all of them get validated. // format get used, but all of them get validated.

View File

@ -226,7 +226,6 @@ func autoConvert_v1alpha1_LoggingConfiguration_To_config_LoggingConfiguration(in
out.FlushFrequency = time.Duration(in.FlushFrequency) out.FlushFrequency = time.Duration(in.FlushFrequency)
out.Verbosity = config.VerbosityLevel(in.Verbosity) out.Verbosity = config.VerbosityLevel(in.Verbosity)
out.VModule = *(*config.VModuleConfiguration)(unsafe.Pointer(&in.VModule)) out.VModule = *(*config.VModuleConfiguration)(unsafe.Pointer(&in.VModule))
out.Sanitization = in.Sanitization
if err := Convert_v1alpha1_FormatOptions_To_config_FormatOptions(&in.Options, &out.Options, s); err != nil { if err := Convert_v1alpha1_FormatOptions_To_config_FormatOptions(&in.Options, &out.Options, s); err != nil {
return err return err
} }
@ -238,7 +237,6 @@ func autoConvert_config_LoggingConfiguration_To_v1alpha1_LoggingConfiguration(in
out.FlushFrequency = time.Duration(in.FlushFrequency) out.FlushFrequency = time.Duration(in.FlushFrequency)
out.Verbosity = uint32(in.Verbosity) out.Verbosity = uint32(in.Verbosity)
out.VModule = *(*VModuleConfiguration)(unsafe.Pointer(&in.VModule)) out.VModule = *(*VModuleConfiguration)(unsafe.Pointer(&in.VModule))
out.Sanitization = in.Sanitization
if err := Convert_config_FormatOptions_To_v1alpha1_FormatOptions(&in.Options, &out.Options, s); err != nil { if err := Convert_config_FormatOptions_To_v1alpha1_FormatOptions(&in.Options, &out.Options, s); err != nil {
return err return err
} }

View File

@ -71,8 +71,6 @@ func BindLoggingFlags(c *config.LoggingConfiguration, fs *pflag.FlagSet) {
fs.DurationVar(&c.FlushFrequency, logFlushFreqFlagName, logFlushFreq, "Maximum number of seconds between log flushes") fs.DurationVar(&c.FlushFrequency, logFlushFreqFlagName, logFlushFreq, "Maximum number of seconds between log flushes")
fs.VarP(&c.Verbosity, "v", "v", "number for the log level verbosity") fs.VarP(&c.Verbosity, "v", "v", "number for the log level verbosity")
fs.Var(&c.VModule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)") fs.Var(&c.VModule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)")
fs.BoolVar(&c.Sanitization, "experimental-logging-sanitization", c.Sanitization, `[Experimental] When enabled prevents logging of fields tagged as sensitive (passwords, keys, tokens).
Runtime log sanitization may introduce significant computation overhead and therefore should not be enabled in production.`)
// JSON options. We only register them if "json" is a valid format. The // JSON options. We only register them if "json" is a valid format. The
// config file API however always has them. // config file API however always has them.

View File

@ -36,21 +36,6 @@ Expected output:
{"ts":1624215726270.8428,"caller":"cmd/logger.go:64","msg":"Log with sensitive key, data: {\"secret\"}\n","v":0} {"ts":1624215726270.8428,"caller":"cmd/logger.go:64","msg":"Log with sensitive key, data: {\"secret\"}\n","v":0}
``` ```
## Logging sanitization
```console
go run ./staging/src/k8s.io/component-base/logs/example/cmd/logger.go --experimental-logging-sanitization
```
Expected output:
```
I0605 22:04:02.019609 3229645 logger.go:58] Log using Infof, key: value
I0605 22:04:02.019677 3229645 logger.go:59] "Log using InfoS" key="value"
E0605 22:04:02.019698 3229645 logger.go:61] Log using Errorf, err: fail
E0605 22:04:02.019709 3229645 logger.go:62] "Log using ErrorS" err="fail"
I0605 22:04:02.019714 3229645 logger.go:64] Log message has been redacted. Log argument #0 contains: [secret-key]
```
## Verbosity ## Verbosity
```console ```console

View File

@ -26,7 +26,6 @@ import (
"k8s.io/component-base/config" "k8s.io/component-base/config"
"k8s.io/component-base/config/v1alpha1" "k8s.io/component-base/config/v1alpha1"
"k8s.io/component-base/logs/registry" "k8s.io/component-base/logs/registry"
"k8s.io/component-base/logs/sanitization"
"k8s.io/klog/v2" "k8s.io/klog/v2"
) )
@ -86,9 +85,6 @@ func (o *Options) apply() {
klog.SetLogger(log) klog.SetLogger(log)
logrFlush = flush logrFlush = flush
} }
if o.Config.Sanitization {
klog.SetLogFilter(&sanitization.SanitizingFilter{})
}
if err := loggingFlags.Lookup("v").Value.Set(o.Config.Verbosity.String()); err != nil { if err := loggingFlags.Lookup("v").Value.Set(o.Config.Verbosity.String()); err != nil {
panic(fmt.Errorf("internal error while setting klog verbosity: %v", err)) panic(fmt.Errorf("internal error while setting klog verbosity: %v", err))
} }

View File

@ -33,14 +33,12 @@ func TestFlags(t *testing.T) {
o.AddFlags(fs) o.AddFlags(fs)
fs.SetOutput(&output) fs.SetOutput(&output)
fs.PrintDefaults() fs.PrintDefaults()
want := ` --experimental-logging-sanitization [Experimental] When enabled prevents logging of fields tagged as sensitive (passwords, keys, tokens). want := ` --log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
Runtime log sanitization may introduce significant computation overhead and therefore should not be enabled in production. --logging-format string Sets the log format. Permitted formats: "text".
--log-flush-frequency duration Maximum number of seconds between log flushes (default 5s) Non-default formats don't honor these flags: --add-dir-header, --alsologtostderr, --log-backtrace-at, --log-dir, --log-file, --log-file-max-size, --logtostderr, --one-output, --skip-headers, --skip-log-headers, --stderrthreshold, --vmodule.
--logging-format string Sets the log format. Permitted formats: "text". Non-default choices are currently alpha and subject to change without warning. (default "text")
Non-default formats don't honor these flags: --add-dir-header, --alsologtostderr, --log-backtrace-at, --log-dir, --log-file, --log-file-max-size, --logtostderr, --one-output, --skip-headers, --skip-log-headers, --stderrthreshold, --vmodule. -v, --v Level number for the log level verbosity
Non-default choices are currently alpha and subject to change without warning. (default "text") --vmodule pattern=N,... comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)
-v, --v Level number for the log level verbosity
--vmodule pattern=N,... comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)
` `
if !assert.Equal(t, want, output.String()) { if !assert.Equal(t, want, output.String()) {
t.Errorf("Wrong list of flags. expect %q, got %q", want, output.String()) t.Errorf("Wrong list of flags. expect %q, got %q", want, output.String())
@ -64,15 +62,6 @@ func TestOptions(t *testing.T) {
args: []string{"--logging-format=text"}, args: []string{"--logging-format=text"},
want: newOptions, want: newOptions,
}, },
{
name: "log sanitization",
args: []string{"--experimental-logging-sanitization"},
want: func() *Options {
c := newOptions.Config.DeepCopy()
c.Sanitization = true
return &Options{*c}
}(),
},
{ {
name: "Unsupported log format", name: "Unsupported log format",
args: []string{"--logging-format=test"}, args: []string{"--logging-format=test"},

View File

@ -1,230 +0,0 @@
/*
Copyright 2020 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 sanitization
import (
"bytes"
"errors"
"flag"
"fmt"
"regexp"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"k8s.io/klog/v2"
)
func TestKlogIntegration(t *testing.T) {
fs := flag.FlagSet{}
klog.InitFlags(&fs)
err := fs.Set("v", "1")
if err != nil {
t.Fatalf("Failed to set verbosity")
}
err = fs.Set("logtostderr", "false")
if err != nil {
t.Fatalf("Failed to set verbosity")
}
tcs := []struct {
name string
fun func()
format string
}{
{
name: "Info",
fun: func() {
klog.Info("test ", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "V(1).Info",
fun: func() {
klog.V(1).Info("test ", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "Infof",
fun: func() {
klog.Infof("test %v", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #0 contains: [password]`,
},
{
name: "V(1).Infof",
fun: func() {
klog.V(1).Infof("test %v", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #0 contains: [password]`,
},
{
name: "Infoln",
fun: func() {
klog.Infoln("test", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "V(1).Infoln",
fun: func() {
klog.V(1).Infoln("test", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "InfoDepth",
fun: func() {
klog.InfoDepth(1, "test ", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "InfoS",
fun: func() {
klog.InfoS("test", "data", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] "Log message has been redacted." key="data" types=[password]`,
},
{
name: "V(1).InfoS",
fun: func() {
klog.V(1).InfoS("test", "data", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] "Log message has been redacted." key="data" types=[password]`,
},
{
name: "InfoSDepth",
fun: func() {
klog.InfoSDepth(1, "test", "data", datapolItem())
},
format: `I%s %s %d klog_test.go:%d] "Log message has been redacted." key="data" types=[password]`,
},
{
name: "Warning",
fun: func() {
klog.Warning("test ", datapolItem())
},
format: `W%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "WarningDepth",
fun: func() {
klog.WarningDepth(1, "test ", datapolItem())
},
format: `W%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "Warningln",
fun: func() {
klog.Warningln("test", datapolItem())
},
format: `W%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "Warningf",
fun: func() {
klog.Warningf("test %d", datapolItem())
},
format: `W%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #0 contains: [password]`,
},
{
name: "Error",
fun: func() {
klog.Error("test ", datapolItem())
},
format: `E%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "ErrorDepth",
fun: func() {
klog.ErrorDepth(1, "test ", datapolItem())
},
format: `E%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "Errorln",
fun: func() {
klog.Errorln("test", datapolItem())
},
format: `E%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #1 contains: [password]`,
},
{
name: "Errorf",
fun: func() {
klog.Errorf("test %d", datapolItem())
},
format: `E%s %s %d klog_test.go:%d] Log message has been redacted. Log argument #0 contains: [password]`,
},
{
name: "ErrorS",
fun: func() {
err := errors.New("fail")
klog.ErrorS(err, "test", "data", datapolItem())
},
format: `E%s %s %d klog_test.go:%d] "Log message has been redacted." err="fail" key="data" types=[password]`,
},
{
name: "ErrorSDepth",
fun: func() {
err := errors.New("fail")
klog.ErrorSDepth(1, err, "test", "data", datapolItem())
},
format: `E%s %s %d klog_test.go:%d] "Log message has been redacted." err="fail" key="data" types=[password]`,
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
var buffer bytes.Buffer
klog.SetOutputBySeverity("INFO", &buffer)
defer klog.SetOutputBySeverity("INFO", nil)
klog.SetLogFilter(&SanitizingFilter{})
defer klog.SetLogFilter(nil)
tc.fun()
var date string
var time string
var pid uint64
var lineNum uint64
logString := normalizeKlogLine(strings.TrimSuffix(buffer.String(), "\n"))
n, err := fmt.Sscanf(logString, tc.format, &date, &time, &pid, &lineNum)
if n != 4 || err != nil {
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, logString)
}
expect := fmt.Sprintf(tc.format, date, time, pid, lineNum)
if !assert.Equal(t, expect, logString) {
t.Errorf("Info has wrong format \n expect:%s\n got:%s", expect, logString)
}
})
}
}
var (
re = regexp.MustCompile(`\s{2,}`)
)
// normalizeKlogLine removes duplicate whitespaces to make lines match no matter the environment.
// Klog padds the log header to try to maintain same width. Depending on how high the process
// pid is it make lead to additional whitespaces.
func normalizeKlogLine(s string) string {
return re.ReplaceAllString(s, " ")
}

View File

@ -1,69 +0,0 @@
/*
Copyright 2020 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 sanitization
import (
"fmt"
"k8s.io/component-base/logs/datapol"
)
const (
datapolMsgFmt = "Log message has been redacted. Log argument #%d contains: %v"
datapolMsg = "Log message has been redacted."
)
// SanitizingFilter implements the LogFilter interface from klog with a set of functions that inspects the arguments with the datapol library
type SanitizingFilter struct{}
// Filter is the filter function for the non-formatting logging functions of klog.
func (sf *SanitizingFilter) Filter(args []interface{}) []interface{} {
for i, v := range args {
types := datapol.Verify(v)
if len(types) > 0 {
return []interface{}{fmt.Sprintf(datapolMsgFmt, i, types)}
}
}
return args
}
// FilterF is the filter function for the formatting logging functions of klog
func (sf *SanitizingFilter) FilterF(fmt string, args []interface{}) (string, []interface{}) {
for i, v := range args {
types := datapol.Verify(v)
if len(types) > 0 {
return datapolMsgFmt, []interface{}{i, types}
}
}
return fmt, args
}
// FilterS is the filter for the structured logging functions of klog.
func (sf *SanitizingFilter) FilterS(msg string, keysAndValues []interface{}) (string, []interface{}) {
for i, v := range keysAndValues {
types := datapol.Verify(v)
if len(types) > 0 {
if i%2 == 0 {
return datapolMsg, []interface{}{"key_index", i, "types", types}
}
// since we scanned linearly we can safely log the key.
return datapolMsg, []interface{}{"key", keysAndValues[i-1], "types", types}
}
}
return msg, keysAndValues
}

View File

@ -1,199 +0,0 @@
/*
Copyright 2020 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 sanitization
import (
"testing"
"github.com/stretchr/testify/assert"
)
type withDatapolTag struct {
Key string `json:"key" datapolicy:"password"`
}
func datapolItem() interface{} {
return withDatapolTag{Key: "hunter2"}
}
func TestFilter(t *testing.T) {
filter := &SanitizingFilter{}
testcases := []struct {
input []interface{}
output []interface{}
}{{
input: []interface{}{},
output: []interface{}{},
}, {
input: []interface{}{
"nothing special", "really",
},
output: []interface{}{
"nothing special", "really",
},
}, {
input: []interface{}{
datapolItem(),
},
output: []interface{}{
"Log message has been redacted. Log argument #0 contains: [password]",
},
}, {
input: []interface{}{
"nothing special", datapolItem(),
},
output: []interface{}{
"Log message has been redacted. Log argument #1 contains: [password]",
},
}}
for _, tc := range testcases {
output := filter.Filter(tc.input)
if !assert.ElementsMatch(t, tc.output, output) {
t.Errorf("Unexpected filter output for %v, want: %v, got %v", tc.input, tc.output, output)
}
}
}
func TestFilterF(t *testing.T) {
filter := &SanitizingFilter{}
testcases := []struct {
inputFmt string
input []interface{}
outputFmt string
output []interface{}
}{{
inputFmt: "",
input: []interface{}{},
outputFmt: "",
output: []interface{}{},
}, {
inputFmt: "%s: %s",
input: []interface{}{
"nothing special", "really",
},
outputFmt: "%s: %s",
output: []interface{}{
"nothing special", "really",
},
}, {
inputFmt: "%v",
input: []interface{}{
datapolItem(),
},
outputFmt: "Log message has been redacted. Log argument #%d contains: %v",
output: []interface{}{
0, []string{"password"},
},
}, {
inputFmt: "%v",
input: []interface{}{
"nothing special", datapolItem(),
},
outputFmt: "Log message has been redacted. Log argument #%d contains: %v",
output: []interface{}{
1, []string{"password"},
},
}}
for _, tc := range testcases {
outputFmt, output := filter.FilterF(tc.inputFmt, tc.input)
correctFmt := outputFmt == tc.outputFmt
correctArgs := assert.ElementsMatch(t, tc.output, output)
if !correctFmt || !correctArgs {
t.Errorf("Error while executing testcase %s, %v", tc.inputFmt, tc.input)
}
if !correctFmt {
t.Errorf("Unexpected output format string want %v, got %v", tc.outputFmt, outputFmt)
}
if !correctArgs {
t.Errorf("Unexpected filter output arguments want: %v, got %v", tc.output, output)
}
}
}
func TestFilterS(t *testing.T) {
filter := &SanitizingFilter{}
testcases := []struct {
inputMsg string
input []interface{}
outputMsg string
output []interface{}
}{{
inputMsg: "",
input: []interface{}{},
outputMsg: "",
output: []interface{}{},
}, {
inputMsg: "Message",
input: []interface{}{
"nothing special", "really",
},
outputMsg: "Message",
output: []interface{}{
"nothing special", "really",
},
}, {
inputMsg: "%v",
input: []interface{}{
datapolItem(), "value1", "key2", "value2",
},
outputMsg: "Log message has been redacted.",
output: []interface{}{
"key_index", 0, "types", []string{"password"},
},
}, {
inputMsg: "%v",
input: []interface{}{
"key1", "value1", datapolItem(), "value2",
},
outputMsg: "Log message has been redacted.",
output: []interface{}{
"key_index", 2, "types", []string{"password"},
},
}, {
inputMsg: "%v",
input: []interface{}{
"key1", datapolItem(), "key2", "value2",
},
outputMsg: "Log message has been redacted.",
output: []interface{}{
"key", "key1", "types", []string{"password"},
},
}, {
inputMsg: "%v",
input: []interface{}{
"key1", "value1", "key2", datapolItem(),
},
outputMsg: "Log message has been redacted.",
output: []interface{}{
"key", "key2", "types", []string{"password"},
},
}}
for _, tc := range testcases {
outputMsg, output := filter.FilterS(tc.inputMsg, tc.input)
correctMsg := outputMsg == tc.outputMsg
correctArgs := assert.ElementsMatch(t, tc.output, output)
if !correctMsg || !correctArgs {
t.Errorf("Error while executing testcase %s, %v", tc.inputMsg, tc.input)
}
if !correctMsg {
t.Errorf("Unexpected output format string want %v, got %v", tc.outputMsg, outputMsg)
}
if !correctArgs {
t.Errorf("Unexpected filter output arguments want: %v, got %v", tc.output, output)
}
}
}

2
vendor/modules.txt vendored
View File

@ -1939,12 +1939,10 @@ k8s.io/component-base/configz
k8s.io/component-base/featuregate k8s.io/component-base/featuregate
k8s.io/component-base/featuregate/testing k8s.io/component-base/featuregate/testing
k8s.io/component-base/logs k8s.io/component-base/logs
k8s.io/component-base/logs/datapol
k8s.io/component-base/logs/json k8s.io/component-base/logs/json
k8s.io/component-base/logs/json/register k8s.io/component-base/logs/json/register
k8s.io/component-base/logs/logreduction k8s.io/component-base/logs/logreduction
k8s.io/component-base/logs/registry k8s.io/component-base/logs/registry
k8s.io/component-base/logs/sanitization
k8s.io/component-base/logs/testinit k8s.io/component-base/logs/testinit
k8s.io/component-base/metrics k8s.io/component-base/metrics
k8s.io/component-base/metrics/legacyregistry k8s.io/component-base/metrics/legacyregistry