-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
389 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package log | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"sync" | ||
|
||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
// SecretsHook is a Logrus hook for hiding secrets from entries before they get logged | ||
type SecretsHook struct { | ||
secrets []string | ||
mx sync.RWMutex | ||
replacer *strings.Replacer | ||
} | ||
|
||
// NewSecretsRedactionHook makes a new secrets hook that is used to redact secrets | ||
// from the logs before other parts can log them | ||
func NewSecretsRedactionHook() *SecretsHook { | ||
return &SecretsHook{} | ||
} | ||
|
||
// Levels is part of the [logrus.Hook] | ||
func (s *SecretsHook) Levels() []logrus.Level { return logrus.AllLevels } | ||
|
||
// Add is used to add a new secret to be redacted. | ||
// Adding the same secret multiple times will not error, but is not recommended. | ||
// It is users job to not keep adding the same secret over time but only once. | ||
func (s *SecretsHook) Add(secret string) { | ||
s.mx.Lock() | ||
defer s.mx.Unlock() | ||
s.secrets = append(s.secrets, secret, "***SECRET_REDACTED***") | ||
s.replacer = strings.NewReplacer(s.secrets...) | ||
} | ||
|
||
// Fire is part of the [logrus.Hook] | ||
func (s *SecretsHook) Fire(entry *logrus.Entry) error { | ||
s.mx.Lock() | ||
// there is no way for us to get a secret after we got a log for it so we can use that to cache the replacer | ||
replacer := s.replacer | ||
s.mx.Unlock() | ||
if replacer == nil { // no secrets no work | ||
return nil | ||
} | ||
entry.Message = replacer.Replace(entry.Message) | ||
|
||
// replace both keys and values with | ||
for k, v := range entry.Data { | ||
newk := replacer.Replace(k) | ||
if newk != k { | ||
entry.Data[newk] = v | ||
delete(entry.Data, k) | ||
k = newk | ||
} | ||
entry.Data[k] = recursiveReplace(v, replacer) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func recursiveReplace(v any, replacer *strings.Replacer) any { | ||
switch s := v.(type) { | ||
case string: | ||
return replacer.Replace(s) | ||
case int, uint, int64, int32, int16, int8, uint64, uint32, uint16, uint8: | ||
// if the secret is encodable in 64 bits ... it is probably not a great secret | ||
return v | ||
} | ||
// replace this with a log after more testing | ||
panic(fmt.Sprintf("Had a logrus.fields value with type %T, please report that this is unsupported", v)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package file | ||
|
||
import ( | ||
"bufio" | ||
"errors" | ||
"fmt" | ||
"strings" | ||
|
||
"go.k6.io/k6/secretsource" | ||
) | ||
|
||
func init() { | ||
secretsource.RegisterExtension("file", func(params secretsource.Params) (secretsource.SecretSource, error) { | ||
f, err := params.FS.Open(params.ConfigArgument) | ||
if err != nil { | ||
return nil, err | ||
} | ||
scanner := bufio.NewScanner(f) | ||
|
||
r := make(map[string]string) | ||
for scanner.Scan() { | ||
line := scanner.Text() | ||
k, v, ok := strings.Cut(line, "=") | ||
if !ok { | ||
return nil, fmt.Errorf("parsing %q, needs =", line) | ||
} | ||
|
||
r[k] = v | ||
} | ||
return &fileSecretSource{ | ||
internal: r, | ||
}, nil | ||
}) | ||
} | ||
|
||
type fileSecretSource struct { | ||
internal map[string]string | ||
filename string | ||
} | ||
|
||
func (mss *fileSecretSource) Name() string { | ||
return "file" // TODO(@mstoykov): make this configurable | ||
} | ||
|
||
func (mss *fileSecretSource) Description() string { | ||
return fmt.Sprintf("file source from %s", mss.filename) | ||
} | ||
|
||
func (mss *fileSecretSource) Get(key string) (string, error) { | ||
v, ok := mss.internal[key] | ||
if !ok { | ||
return "", errors.New("no value") | ||
} | ||
return v, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package secretsource | ||
|
||
// TODO(@mstoykov): do we want this? or do we want to have a function like createOutputs? | ||
import ( | ||
_ "go.k6.io/k6/internal/secretsource/file" //nolint:revive | ||
_ "go.k6.io/k6/internal/secretsource/mock" //nolint:revive | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package mock | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"strings" | ||
|
||
"go.k6.io/k6/secretsource" | ||
) | ||
|
||
func init() { | ||
secretsource.RegisterExtension("mock", func(params secretsource.Params) (secretsource.SecretSource, error) { | ||
list := strings.Split(params.ConfigArgument, ":") | ||
r := make(map[string]string, len(list)) | ||
for _, kv := range list { | ||
k, v, ok := strings.Cut(kv, "=") | ||
if !ok { | ||
return nil, fmt.Errorf("parsing %q, needs =", kv) | ||
} | ||
|
||
r[k] = v | ||
} | ||
return &mockSecretSource{ | ||
internal: r, | ||
}, nil | ||
}) | ||
} | ||
|
||
// TODO remove - this was only for quicker testing | ||
type mockSecretSource struct { | ||
internal map[string]string | ||
} | ||
|
||
func (mss *mockSecretSource) Name() string { | ||
return "some" | ||
} | ||
|
||
func (mss *mockSecretSource) Description() string { | ||
return "something cool for description" | ||
} | ||
|
||
func (mss *mockSecretSource) Get(key string) (string, error) { | ||
v, ok := mss.internal[key] | ||
if !ok { | ||
return "", errors.New("no value") | ||
} | ||
return v, nil | ||
} |
Oops, something went wrong.