diff --git a/logging/aws.go b/logging/aws.go
index 1ab8ffbc..6e48f34e 100644
--- a/logging/aws.go
+++ b/logging/aws.go
@@ -26,18 +26,58 @@ var UniqueIDRegex = regexp.MustCompile(`(A3T[A-Z0-9]` +
var SensitiveKeyRegex = regexp.MustCompile(`[A-Za-z0-9/+=]{16,}`)
+const (
+ unmaskedFirst = 4
+ unmaskedLast = 4
+)
+
func MaskAWSAccessKey(field string) string {
field = UniqueIDRegex.ReplaceAllStringFunc(field, func(s string) string {
- return partialMaskString(s, 4, 4) //nolint:gomnd
+ return partialMaskString(s, unmaskedFirst, unmaskedLast)
})
return field
}
func MaskAWSSensitiveValues(field string) string {
field = MaskAWSAccessKey(field)
-
- field = SensitiveKeyRegex.ReplaceAllStringFunc(field, func(s string) string {
- return partialMaskString(s, 4, 4) //nolint:gomnd
- })
+ field = MaskAWSSecretKeys(field)
return field
}
+
+// MaskAWSSecretKeys masks likely AWS secret access keys in the input.
+// See https://aws.amazon.com/blogs/security/a-safer-way-to-distribute-aws-credentials-to-ec2/:
+// "Find me 40-character, base-64 strings that don’t have any base 64 characters immediately before or after".
+func MaskAWSSecretKeys(in string) string {
+ const (
+ secretKeyLen = 40
+ )
+ len := len(in)
+ out := make([]byte, len)
+ base64Characters := 0
+
+ for i := 0; i < len; i++ {
+ b := in[i]
+ out[i] = b
+
+ if (b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z') || (b >= '0' && b <= '9') || b == '/' || b == '+' || b == '=' {
+ // base64 character.
+ base64Characters++
+ } else {
+ if base64Characters == secretKeyLen {
+ for j := (i - secretKeyLen) + unmaskedFirst; j < i-unmaskedLast; j++ {
+ out[j] = '*'
+ }
+ }
+
+ base64Characters = 0
+ }
+ }
+
+ if base64Characters == secretKeyLen {
+ for j := (len - secretKeyLen) + unmaskedFirst; j < len-unmaskedLast; j++ {
+ out[j] = '*'
+ }
+ }
+
+ return string(out)
+}
diff --git a/logging/aws_test.go b/logging/aws_test.go
index e760a6e7..1c300c75 100644
--- a/logging/aws_test.go
+++ b/logging/aws_test.go
@@ -17,23 +17,55 @@ func TestMaskAWSSensitiveValues(t *testing.T) {
tests := map[string]testCase{
"mask_simple": {
- input: "4skd4lTSLVBMG/asedterGLKSNMSAlsxiLGfjt=ssD",
- expected: "4skd**********************************=ssD",
+ input: "MfP3tIG15gibzIx7CSbhSNkgD5sSV4k2tWXgN8U8",
+ expected: "MfP3********************************N8U8",
},
"mask_complex_json": {
input: `
{
- "AWSSecretKey": "4skd4lTSLVBMG/asedterGLKSNMSAlsxiLGfjt=ssD",
+ "AWSSecretKey": "LEfH8nZmFN4BGIJnku6lkChHydRN5B/YlWCIjOte",
"BucketName": "test-bucket",
"AWSKeyId": "AIDACKCEVSQ6C2EXAMPLE",
}
`,
expected: `
{
- "AWSSecretKey": "4skd**********************************=ssD",
+ "AWSSecretKey": "LEfH********************************jOte",
"BucketName": "test-bucket",
"AWSKeyId": "AIDA*************MPLE",
}
+`,
+ },
+ "mask_multiple_json": {
+ input: `
+{
+ "AWSSecretKey": "LEfH8nZmFN4BGIJnku6lkChHydRN5B/YlWCIjOte",
+ "BucketName": "test-bucket-1",
+ "AWSKeyId": "AIDACKCEVSQ6C2EXAMPLE",
+},
+{
+ "Key": "ABCDEFGH!JKLMNOPQRSTUVWXYZ012345678901234567890123456789",
+},
+{
+ "AWSSecretKey": "MfP3tIG15gibzIx7CSbhSNkgD5sSV4k2tWXgN8U8",
+ "BucketName": "test-bucket-2",
+ "AWSKeyId": "AKIA5PX2H2S3LHEXAMPLE",
+}
+`,
+ expected: `
+{
+ "AWSSecretKey": "LEfH********************************jOte",
+ "BucketName": "test-bucket-1",
+ "AWSKeyId": "AIDA*************MPLE",
+},
+{
+ "Key": "ABCDEFGH!JKLMNOPQRSTUVWXYZ012345678901234567890123456789",
+},
+{
+ "AWSSecretKey": "MfP3********************************N8U8",
+ "BucketName": "test-bucket-2",
+ "AWSKeyId": "AKIA*************MPLE",
+}
`,
},
"no_mask": {
@@ -42,12 +74,12 @@ func TestMaskAWSSensitiveValues(t *testing.T) {
},
"mask_xml": {
input: `
-4skd4lTSLVBMG/asedterGLKSNMSAlsxiLGfjt=ssD
+8/AiP0ofCD/YOAqXWrungQt/Y4BkTj1UOjZ0MqBs
test-bucket
AIDACKCEVSQ6C2EXAMPLE
`,
expected: `
-4skd**********************************=ssD
+8/Ai********************************MqBs
test-bucket
AIDA*************MPLE
`,