-
Notifications
You must be signed in to change notification settings - Fork 444
/
log_redacter.go
82 lines (65 loc) · 2.37 KB
/
log_redacter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package syncutil
import (
"encoding/json"
"fmt"
"reflect"
"strings"
"github.com/golang/protobuf/proto"
v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1"
"github.com/solo-io/protoc-gen-ext/pkg/redaction"
)
const (
Redacted = "[REDACTED]"
)
// stringify the contents of the snapshot
//
// NOTE that if any of the top-level fields of the snapshot is a SecretList, then the secrets will be
// stringified by printing just their name and namespace, and "REDACTED" for their data. Secrets may
// contain sensitive data like TLS private keys, so be sure to use this whenever you'd like to
// stringify a snapshot rather than Go's %v formatter
func StringifySnapshot(snapshot interface{}) string {
snapshotStruct := reflect.ValueOf(snapshot).Elem()
stringBuilder := strings.Builder{}
for i := 0; i < snapshotStruct.NumField(); i++ {
fieldName := snapshotStruct.Type().Field(i).Name
fieldValue := snapshotStruct.Field(i).Interface()
stringBuilder.Write([]byte(fieldName))
stringBuilder.Write([]byte(":"))
if secretList, ok := fieldValue.(v1.SecretList); ok {
stringBuilder.Write([]byte("["))
var redactedSecrets []string
secretList.Each(func(s *v1.Secret) {
redactedSecret := fmt.Sprintf(
"%v{name: %s namespace: %s data: %s}",
reflect.TypeOf(s),
s.GetMetadata().GetName(),
s.GetMetadata().GetNamespace(),
Redacted,
)
redactedSecrets = append(redactedSecrets, redactedSecret)
})
stringBuilder.Write([]byte(strings.Join(redactedSecrets, " '")))
stringBuilder.Write([]byte("]"))
} else {
stringBuilder.Write([]byte(fmt.Sprintf("%v", fieldValue)))
}
stringBuilder.Write([]byte("\n"))
}
return stringBuilder.String()
}
type ProtoRedactor interface {
// Build a JSON string representation of the proto message, zeroing-out all fields in the proto that match some criteria
BuildRedactedJsonString(message proto.Message) (string, error)
}
// build a ProtoRedactor that zeroes out fields that have the given struct tag set to the given value
func NewProtoRedactor() ProtoRedactor {
return &protoRedactor{}
}
type protoRedactor struct{}
func (p *protoRedactor) BuildRedactedJsonString(message proto.Message) (string, error) {
// make a clone so that we can mutate it and zero-out fields
clone := proto.Clone(message)
redaction.Redact(proto.MessageReflect(clone))
bytes, err := json.Marshal(clone)
return string(bytes), err
}