From 7e09d903fe5c127c6f07e6292e65afbcc73f38d3 Mon Sep 17 00:00:00 2001 From: Justen Walker Date: Fri, 11 Jun 2021 17:20:20 -0400 Subject: [PATCH] feat: redact --token and --password arguments When printing kubectl commands for debug logs, redact the --token and --password arguments so that it doesn't leak credentials into logs. --- internal/app/command.go | 29 +++++++++++++++++++++- internal/app/command_test.go | 47 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/internal/app/command.go b/internal/app/command.go index fd1db320..76a09d7a 100644 --- a/internal/app/command.go +++ b/internal/app/command.go @@ -35,7 +35,34 @@ func (e ExitStatus) String() string { } func (c *Command) String() string { - return c.Cmd + " " + strings.Join(c.Args, " ") + var sb strings.Builder + sb.WriteString(c.Cmd) + for i := 0; i < len(c.Args); i++ { + arg := c.Args[i] + sb.WriteRune(' ') + if strings.HasPrefix(arg, "--token=") { + sb.WriteString("--token=******") + continue + } + if strings.HasPrefix(arg, "--password=") { + sb.WriteString("--password=******") + continue + } + if arg == "--token" { + sb.WriteString(arg) + sb.WriteString("=******") + i++ + continue + } + if arg == "--password" { + sb.WriteString(arg) + sb.WriteString("=******") + i++ + continue + } + sb.WriteString(arg) + } + return sb.String() } // RetryExec runs exec command with retry diff --git a/internal/app/command_test.go b/internal/app/command_test.go index 7c9e596d..b54fc4df 100644 --- a/internal/app/command_test.go +++ b/internal/app/command_test.go @@ -215,3 +215,50 @@ func TestPipeExec(t *testing.T) { }) } } + +func TestCommand_String(t *testing.T) { + tests := []struct { + name string + cmd Command + expected string + }{ + { + "regular", + kubectl([]string{"config", "set-cluster", "CONTEXT", "--server=http://localhost:8080", "--certificate-authority=cacert.crt"}, ""), + "kubectl config set-cluster CONTEXT --server=http://localhost:8080 --certificate-authority=cacert.crt", + }, + { + "cert-key", + kubectl([]string{"config", "set-credentials", "USER", "--client-key=client.key", "--client-certificate=client.crt"}, ""), + "kubectl config set-credentials USER --client-key=client.key --client-certificate=client.crt", + }, + { + "password", + kubectl([]string{"config", "set-credentials", "USER", "--username=foo", "--password=secret"}, ""), + "kubectl config set-credentials USER --username=foo --password=******", + }, + { + "password2", + kubectl([]string{"config", "set-credentials", "USER", "--username", "foo", "--password", "secret"}, ""), + "kubectl config set-credentials USER --username foo --password=******", + }, + { + "token", + kubectl([]string{"config", "set-credentials", "USER", "--token=secret"}, ""), + "kubectl config set-credentials USER --token=******", + }, + { + "token2", + kubectl([]string{"config", "set-credentials", "USER", "--token", "secret"}, ""), + "kubectl config set-credentials USER --token=******", + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actual := test.cmd.String() + if actual != test.expected { + t.Errorf("command.String() unexpected got = %s, want = %s\n", actual, test.expected) + } + }) + } +}