Some source use client libraries that can emit errors that contain sensitive information - in particular, git-facing libraries that embed tokens into repository URLs. This PR introduces a way of redacting them - starting with GitLab (where we've seen this most recently), but in theory extensible to other sources as needed. This implementation uses a custom zap core; this might also be possible with a custom zap encoder, but I didn't test it out. (The deleted core.go file was entirely unused.)
51 lines
1.2 KiB
Go
51 lines
1.2 KiB
Go
package log
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
)
|
|
|
|
type dynamicRedactor struct {
|
|
denySet map[string]struct{}
|
|
denySlice []string
|
|
denyMu sync.Mutex
|
|
|
|
replacer atomic.Pointer[strings.Replacer]
|
|
}
|
|
|
|
var globalRedactor *dynamicRedactor
|
|
|
|
func init() {
|
|
globalRedactor = &dynamicRedactor{denySet: make(map[string]struct{})}
|
|
globalRedactor.replacer.CompareAndSwap(nil, strings.NewReplacer())
|
|
}
|
|
|
|
// RedactGlobally configures the global log redactor to redact the provided value during log emission. The value will be
|
|
// redacted in log messages and values that are strings, but not in log keys or values of other types.
|
|
func RedactGlobally(sensitiveValue string) {
|
|
globalRedactor.configureForRedaction(sensitiveValue)
|
|
}
|
|
|
|
func (r *dynamicRedactor) configureForRedaction(sensitiveValue string) {
|
|
if sensitiveValue == "" {
|
|
return
|
|
}
|
|
|
|
r.denyMu.Lock()
|
|
defer r.denyMu.Unlock()
|
|
|
|
if _, ok := r.denySet[sensitiveValue]; ok {
|
|
return
|
|
}
|
|
|
|
r.denySet[sensitiveValue] = struct{}{}
|
|
r.denySlice = append(r.denySlice, sensitiveValue, "*****")
|
|
|
|
r.replacer.Store(strings.NewReplacer(r.denySlice...))
|
|
}
|
|
|
|
func (r *dynamicRedactor) redact(s string) string {
|
|
return r.replacer.Load().Replace(s)
|
|
}
|