sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/logrusutil/logrusutil_test.go (about)

     1  /*
     2  Copyright 2019 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 logrusutil
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  
    23  	"github.com/google/go-cmp/cmp"
    24  	"github.com/sirupsen/logrus"
    25  	"sigs.k8s.io/prow/pkg/secretutil"
    26  
    27  	"k8s.io/apimachinery/pkg/util/sets"
    28  )
    29  
    30  func TestCensoringFormatter(t *testing.T) {
    31  
    32  	testCases := []struct {
    33  		description string
    34  		entry       *logrus.Entry
    35  		expected    string
    36  	}{
    37  		{
    38  			description: "all occurrences of a single secret in a message are censored",
    39  			entry:       &logrus.Entry{Message: "A SECRET is a SECRET if it is secret"},
    40  			expected:    "level=panic msg=\"A XXXXXX is a XXXXXX if it is secret\"\n",
    41  		},
    42  		{
    43  			description: "occurrences of a multiple secrets in a message are censored",
    44  			entry:       &logrus.Entry{Message: "A SECRET is a MYSTERY"},
    45  			expected:    "level=panic msg=\"A XXXXXX is a XXXXXXX\"\n",
    46  		},
    47  		{
    48  			description: "occurrences of multiple secrets in a field",
    49  			entry:       &logrus.Entry{Message: "message", Data: logrus.Fields{"key": "A SECRET is a MYSTERY"}},
    50  			expected:    "level=panic msg=message key=\"A XXXXXX is a XXXXXXX\"\n",
    51  		},
    52  		{
    53  			description: "occurrences of a secret in a non-string field",
    54  			entry:       &logrus.Entry{Message: "message", Data: logrus.Fields{"key": fmt.Errorf("A SECRET is a MYSTERY")}},
    55  			expected:    "level=panic msg=message key=\"A XXXXXX is a XXXXXXX\"\n",
    56  		},
    57  	}
    58  
    59  	baseFormatter := &logrus.TextFormatter{
    60  		DisableColors:    true,
    61  		DisableTimestamp: true,
    62  	}
    63  	formatter := NewCensoringFormatter(baseFormatter, func() sets.Set[string] {
    64  		return sets.New[string]("MYSTERY", "SECRET")
    65  	})
    66  
    67  	for _, tc := range testCases {
    68  		t.Run(tc.description, func(t *testing.T) {
    69  			censored, err := formatter.Format(tc.entry)
    70  			if err != nil {
    71  				t.Errorf("Unexpected error: %v", err)
    72  			}
    73  			if string(censored) != tc.expected {
    74  				t.Errorf("Expected '%s', got '%s'", tc.expected, string(censored))
    75  			}
    76  		})
    77  	}
    78  }
    79  
    80  func TestCensoringFormatterDelegateFormatter(t *testing.T) {
    81  	delegate := &logrus.JSONFormatter{}
    82  	censorer := secretutil.NewCensorer()
    83  	message := `COMPLEX 
    84  secret
    85  with "chars" that need fixing in JSON`
    86  	censorer.Refresh(message)
    87  	formatter := NewFormatterWithCensor(delegate, censorer)
    88  	censored, err := formatter.Format(&logrus.Entry{Message: message})
    89  	if err != nil {
    90  		t.Fatalf("got an error from censoring: %v", err)
    91  	}
    92  	if diff := cmp.Diff(string(censored), `{"level":"panic","msg":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","time":"0001-01-01T00:00:00Z"}
    93  `); diff != "" {
    94  		t.Errorf("got incorrect output after censoring: %v", diff)
    95  	}
    96  }
    97  
    98  func TestCensoringFormatterWithCornerCases(t *testing.T) {
    99  	entry := &logrus.Entry{Message: "message", Data: logrus.Fields{"key": fmt.Errorf("A SECRET is a secret")}}
   100  	expectedEntry := "level=panic msg=message key=\"A XXXXXX is a secret\"\n"
   101  
   102  	testCases := []struct {
   103  		description string
   104  		secrets     sets.Set[string]
   105  		expected    string
   106  	}{
   107  		{
   108  			description: "empty string",
   109  			secrets:     sets.New[string]("SECRET", ""),
   110  			expected:    expectedEntry,
   111  		},
   112  		{
   113  			description: "leading line break",
   114  			secrets:     sets.New[string]("\nSECRET", ""),
   115  			expected:    expectedEntry,
   116  		},
   117  		{
   118  			description: "tailing line break",
   119  			secrets:     sets.New[string]("SECRET\n", ""),
   120  			expected:    expectedEntry,
   121  		},
   122  		{
   123  			description: "leading space and tailing space",
   124  			secrets:     sets.New[string](" SECRET ", ""),
   125  			expected:    expectedEntry,
   126  		},
   127  	}
   128  
   129  	baseFormatter := &logrus.TextFormatter{
   130  		DisableColors:    true,
   131  		DisableTimestamp: true,
   132  	}
   133  
   134  	for _, tc := range testCases {
   135  		t.Run(tc.description, func(t *testing.T) {
   136  			formatter := NewCensoringFormatter(baseFormatter, func() sets.Set[string] {
   137  				return tc.secrets
   138  			})
   139  
   140  			censored, err := formatter.Format(entry)
   141  			if err != nil {
   142  				t.Errorf("Unexpected error: %v", err)
   143  			}
   144  			if string(censored) != tc.expected {
   145  				t.Errorf("Expected '%s', got '%s'", tc.expected, string(censored))
   146  			}
   147  		})
   148  	}
   149  }
   150  
   151  func TestCensoringFormatterDoesntDeadLockWhenUsedWithStandardLogger(t *testing.T) {
   152  	// The whitespace makes the censoring fornmatter emit a warning. If it uses the same global
   153  	// logger, that results in a deadlock.
   154  	logrus.SetFormatter(NewCensoringFormatter(logrus.StandardLogger().Formatter, func() sets.Set[string] {
   155  		return sets.New[string](" untrimmed")
   156  	}))
   157  	logrus.Info("test")
   158  }