Skip to content

Commit

Permalink
Better Redactors
Browse files Browse the repository at this point in the history
  • Loading branch information
gildas committed May 8, 2024
1 parent 4b0c5e0 commit bee9c19
Show file tree
Hide file tree
Showing 2 changed files with 253 additions and 27 deletions.
230 changes: 212 additions & 18 deletions redact_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
package logger_test

import (
"reflect"
"strings"
"testing"

"github.com/gildas/go-core"
"github.com/gildas/go-logger"
"github.com/stretchr/testify/suite"
)

func (suite *LoggerSuite) TestCanRedactSensitiveStruct() {
type RedactSuite struct {
LoggerSuite
Name string
}

func TestRedactSuite(t *testing.T) {
suite.Run(t, new(RedactSuite))
}

func (suite *RedactSuite) SetupSuite() {
suite.Name = strings.TrimSuffix(reflect.TypeOf(suite).Elem().Name(), "Suite")
}

func (suite *RedactSuite) TestCanRedactSensitiveStruct() {
customer := User{"12345678", "John Doe", nil}
output := CaptureStdout(func() {
log := logger.Create("test", &logger.StdoutStream{Unbuffered: true})
Expand All @@ -28,7 +44,7 @@ func (suite *LoggerSuite) TestCanRedactSensitiveStruct() {
})
}

func (suite *LoggerSuite) TestCanRedactMessage() {
func (suite *RedactSuite) TestCanRedactMessage() {
redactor := core.Must(logger.NewRedactor(`\+[0-9]{11}`))
suite.Require().NotEmpty(redactor.String())
output := CaptureStdout(func() {
Expand All @@ -53,7 +69,7 @@ func (suite *LoggerSuite) TestCanRedactMessage() {
})
}

func (suite *LoggerSuite) TestShouldNotRedactMessageWithNoMatch() {
func (suite *RedactSuite) TestShouldNotRedactMessageWithNoMatch() {
redactor := core.Must(logger.NewRedactor(`\+[0-9]{23}`))
suite.Require().NotEmpty(redactor.String())
output := CaptureStdout(func() {
Expand All @@ -78,7 +94,7 @@ func (suite *LoggerSuite) TestShouldNotRedactMessageWithNoMatch() {
})
}

func (suite *LoggerSuite) TestCanRedactMessageWithSeveralRedactors() {
func (suite *RedactSuite) TestCanRedactMessageWithSeveralRedactors() {
output := CaptureStdout(func() {
log := logger.Create(
"test",
Expand Down Expand Up @@ -116,7 +132,7 @@ func (suite *LoggerSuite) TestCanRedactMessageWithSeveralRedactors() {
})
}

func (suite *LoggerSuite) TestCanRedactAsString() {
func (suite *RedactSuite) TestCanRedactAsString() {
suite.Assert().Equal("", logger.Redact(nil))
suite.Assert().Equal("", logger.Redact(""))
redacted := logger.Redact("John Doe")
Expand All @@ -128,67 +144,113 @@ func (suite *LoggerSuite) TestCanRedactAsString() {
suite.Assert().Equal("Name-6cea57c2fb", logger.RedactWithPrefixedHash("Name", "John Doe"))
}

func (suite *LoggerSuite) TestCanRedactCreditCardCard() {
func (suite *RedactSuite) TestCanRedactCreditCardCard() {
redactor := logger.CreditCardRedactor
redacted, ok := redactor.Redact("message with 30569309025904")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 3700 000001 00018")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 4111 1111 1111 1111")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 3056 9309 0259 04")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 6011 0009 9013 9424")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 5105 1051 0510 5100")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 3569 9900 1009 5841")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactAMEXCard() {
func (suite *RedactSuite) TestCanRedactAMEXCard() {
redactor := logger.AMEXRedactor
redacted, ok := redactor.Redact("message with 370000000100018")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 3700 000001 00018")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactVISACard() {
func (suite *RedactSuite) TestCanRedactVISACard() {
redactor := logger.VISARedactor
redacted, ok := redactor.Redact("message with 4111111111111111")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 4111 1111 1111 1111")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactDinersClubCard() {
func (suite *RedactSuite) TestCanRedactDinersClubCard() {
redactor := logger.DinersClubRedactor
redacted, ok := redactor.Redact("message with 30569309025904")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 3056 9309 0259 04")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactDiscoverCard() {
func (suite *RedactSuite) TestCanRedactDiscoverCard() {
redactor := logger.DiscoverRedactor
redacted, ok := redactor.Redact("message with 6011000990139424")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 6011 0009 9013 9424")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactMasterCardCard() {
func (suite *RedactSuite) TestCanRedactMasterCardCard() {
redactor := logger.MasterCardRedactor
redacted, ok := redactor.Redact("message with 5105105105105100")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 5105 1051 0510 5100")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *RedactSuite) TestCanRedactJCBCard() {
redactor := logger.JCBRedactor
redacted, ok := redactor.Redact("message with 3569990010095841")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 3569 9900 1009 5841")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactPhone() {
func (suite *RedactSuite) TestCanRedactPhone() {
redactor := logger.PhoneRedactor
redacted, ok := redactor.Redact("message with +13178723000")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
Expand All @@ -201,7 +263,7 @@ func (suite *LoggerSuite) TestCanRedactPhone() {
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactEmail() {
func (suite *RedactSuite) TestCanRedactEmail() {
redactor := logger.EmailRedactor
redacted, ok := redactor.Redact("message with [email protected]")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
Expand All @@ -211,7 +273,7 @@ func (suite *LoggerSuite) TestCanRedactEmail() {
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactIP() {
func (suite *RedactSuite) TestCanRedactIP() {
redactor := logger.IPRedactor
redacted, ok := redactor.Redact("message with 192.168.1.1")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
Expand All @@ -224,7 +286,7 @@ func (suite *LoggerSuite) TestCanRedactIP() {
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactIPV4() {
func (suite *RedactSuite) TestCanRedactIPV4() {
redactor := logger.IPV4Redactor
redacted, ok := redactor.Redact("message with 192.168.1.1")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
Expand All @@ -234,7 +296,7 @@ func (suite *LoggerSuite) TestCanRedactIPV4() {
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactIPV6() {
func (suite *RedactSuite) TestCanRedactIPV6() {
redactor := logger.IPV6Redactor
redacted, ok := redactor.Redact("message with 2600:::")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
Expand All @@ -250,7 +312,7 @@ func (suite *LoggerSuite) TestCanRedactIPV6() {
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactMAC() {
func (suite *RedactSuite) TestCanRedactMAC() {
redactor := logger.MACRedactor
redacted, ok := redactor.Redact("message with 2C:54:91:88:C9:E3")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
Expand All @@ -260,7 +322,139 @@ func (suite *LoggerSuite) TestCanRedactMAC() {
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *LoggerSuite) TestCanRedactWithKeysToRedact() {
func (suite *RedactSuite) TestCanMergeEmpty() {
suite.Assert().Equal(logger.VISARedactor.String(), logger.VISARedactor.Merge().String())
}

func (suite *RedactSuite) TestCanMergeWithRedactor() {
expected := `3[47]\d{2}[- ]*\d{6}[- ]*\d{5}|4\d{3}[- ]*\d{4}[- ]*\d{4}[- ]*\d{4}`
redactor := logger.AMEXRedactor.Merge(logger.VISARedactor)
suite.Assert().Equal(expected, redactor.String())
redacted, ok := redactor.Redact("message with 3700 000001 00018")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 4111 1111 1111 1111")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 5105 1051 0510 5100")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with 5105 1051 0510 5100", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *RedactSuite) TestCanMergeWithRedactors() {
expected := `3[47]\d{2}[- ]*\d{6}[- ]*\d{5}|4\d{3}[- ]*\d{4}[- ]*\d{4}[- ]*\d{4}|(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[- ]*\d{4}[- ]*\d{4}[- ]*\d{4}`
redactor := logger.AMEXRedactor.Merge(logger.VISARedactor, logger.MasterCardRedactor)
suite.Assert().Equal(expected, redactor.String())
redacted, ok := redactor.Redact("message with 3700 000001 00018")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 4111 1111 1111 1111")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 5105 1051 0510 5100")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *RedactSuite) TestCanMergeWithPipedRedactors() {
expected := `3[47]\d{2}[- ]*\d{6}[- ]*\d{5}|4\d{3}[- ]*\d{4}[- ]*\d{4}[- ]*\d{4}|(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[- ]*\d{4}[- ]*\d{4}[- ]*\d{4}`
redactor := logger.AMEXRedactor.Merge(logger.VISARedactor).Merge(logger.MasterCardRedactor)
suite.Assert().Equal(expected, redactor.String())
redacted, ok := redactor.Redact("message with 3700 000001 00018")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 4111 1111 1111 1111")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 5105 1051 0510 5100")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

func (suite *RedactSuite) TestCanMergeWithString() {
expected := `3[47]\d{2}[- ]*\d{6}[- ]*\d{5}|4\d{3}[- ]*\d{4}[- ]*\d{4}[- ]*\d{4}`
redactor := logger.AMEXRedactor.Merge(logger.VISARedactor.String())
suite.Assert().Equal(expected, redactor.String())
redacted, ok := redactor.Redact("message with 3700 000001 00018")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with 4111 1111 1111 1111")
suite.Assert().Truef(ok, "Redactor %T should have matched", redactor)
suite.Assert().Equal("message with REDACTED", redacted)
redacted, ok = redactor.Redact("message with nothing")
suite.Assert().Falsef(ok, "Redactor %T should not have matched", redactor)
suite.Assert().Equal("message with nothing", redacted)
}

type stringer logger.Redactor
func (s stringer) String() string {
return logger.Redactor(s).String()
}

func (suite *RedactSuite) TestCanMergeWithStringer() {
expected := `3[47]\d{2}[- ]*\d{6}[- ]*\d{5}|4\d{3}[- ]*\d{4}[- ]*\d{4}[- ]*\d{4}`
redactor := logger.AMEXRedactor.Merge(stringer(*logger.VISARedactor))
suite.Assert().Equal(expected, redactor.String())
}

func (suite *RedactSuite) TestMergeShouldPanicWithWrongType() {
suite.Require().Panics(func() {
_ = logger.VISARedactor.Merge(42)
})
}

func (suite *RedactSuite) TestCanUseSeveralRedactors() {
output := CaptureStdout(func() {
mainLog := logger.Create(
"test",
&logger.StdoutStream{Unbuffered: true},
)
log := mainLog.Child(
nil,
nil,
logger.PhoneRedactor,
logger.EmailRedactor,
)
log.Infof("message with sensitive (+13178723000) data")
log.Infof("message with sensitive ([email protected]) data")
})
lines := strings.Split(output, "\n")[0:2]
suite.LogLineEqual(lines[0], map[string]string{
"hostname": `[a-zA-Z_0-9\-\.]+`,
"level": "30",
"msg": `message with sensitive \(REDACTED\) data`,
"name": "test",
"pid": "[0-9]+",
"scope": "main",
"tid": "[0-9]+",
"time": `[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+Z`,
"topic": "main",
"v": "0",
})
suite.LogLineEqual(lines[1], map[string]string{
"hostname": `[a-zA-Z_0-9\-\.]+`,
"level": "30",
"msg": `message with sensitive \(REDACTED\) data`,
"name": "test",
"pid": "[0-9]+",
"scope": "main",
"tid": "[0-9]+",
"time": `[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+Z`,
"topic": "main",
"v": "0",
})
}

func (suite *RedactSuite) TestCanRedactWithKeysToRedact() {
metadata := Metadata{"12345678", "Taro Yamamoto", "Tokyo"}
output := CaptureStdout(func() {
log := logger.Create("test", &logger.StdoutStream{Unbuffered: true})
Expand Down
Loading

0 comments on commit bee9c19

Please sign in to comment.