Skip to content

Commit

Permalink
Merge pull request #144 from garethjevans/masked
Browse files Browse the repository at this point in the history
chore: mask auth token in debug logs
  • Loading branch information
garethjevans authored Mar 9, 2021
2 parents c9b15b4 + 8c4f79d commit a97ba79
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 3 deletions.
37 changes: 34 additions & 3 deletions pkg/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"io/ioutil"
"net/http"
"os"
"regexp"

"strings"

Expand All @@ -18,6 +19,8 @@ import (
"github.com/plumming/dx/pkg/version"
)

const masked = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

// ClientOption represents an argument to NewClient.
type ClientOption = func(http.RoundTripper) http.RoundTripper

Expand All @@ -42,11 +45,11 @@ func AddHeader(name, value string) ClientOption {
log.Logger().Debugf("sending request to host '%s'", host)
if name == "Authorization" {
if host == "api.github.com" {
log.Logger().Debugf("Adding Authorization Header %s=%s", name, value)
log.Logger().Debugf("Adding Authorization Header %s=%s", name, Mask(value))
req.Header.Add(name, value)
}
} else {
log.Logger().Debugf("Adding Header %s=%s", name, value)
log.Logger().Debugf("Adding Header %s=%s", name, Mask(value))
req.Header.Add(name, value)
}

Expand Down Expand Up @@ -263,9 +266,37 @@ func BasicClient() (*Client, error) {

if c, err := ParseDefaultConfig(ConfigFile(), HostsFile()); err == nil {
if token := c.GetToken(defaultHostname); token != "" {
log.Logger().Debugf("Using Auth %s", token)
log.Logger().Debugf("Using Auth %s", Mask(token))
opts = append(opts, AddHeader("Authorization", fmt.Sprintf("token %s", token)))
}
}
return NewClient(opts...), nil
}

func Mask(in string) string {
re := regexp.MustCompile(`([0-9a-f]{4})([0-9a-f]{32})([0-9a-f]{4})`)
if re.MatchString(in) {
results := ReplaceAllGroupFunc(re, in, func(groups []string) string {
return groups[1] + masked + groups[3]
})
return results
}
return in
}

func ReplaceAllGroupFunc(re *regexp.Regexp, str string, repl func([]string) string) string {
result := ""
lastIndex := 0

for _, v := range re.FindAllSubmatchIndex([]byte(str), -1) {
groups := []string{}
for i := 0; i < len(v); i += 2 {
groups = append(groups, str[v[i]:v[i+1]])
}

result += str[lastIndex:v[0]] + repl(groups)
lastIndex = v[1]
}

return result + str[lastIndex:]
}
48 changes: 48 additions & 0 deletions pkg/api/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import (
"bytes"
"io"
"io/ioutil"
"math/rand"
"reflect"
"testing"

"github.com/stretchr/testify/assert"

"github.com/plumming/dx/pkg/httpmock"
)

Expand Down Expand Up @@ -67,3 +70,48 @@ func TestRESTGetDelete(t *testing.T) {
err := client.REST("DELETE", "applications/CLIENTID/grant", r, nil)
eq(t, err, nil)
}

const letterBytes = "0123456789abcdef"

func TestFilterToken(t *testing.T) {
token := generateRandomString()
masked := Mask(token)

t.Logf(masked)
assert.Equal(t, len(token), len(masked))
assert.NotEqual(t, token, masked)
}

func TestFilterToken_WithPrefix(t *testing.T) {
token := "token " + generateRandomString()
masked := Mask(token)

t.Logf(masked)
assert.Equal(t, len(token), len(masked))
assert.NotEqual(t, token, masked)
}

func TestFilterToken_WithSuffix(t *testing.T) {
token := generateRandomString() + " something at the end"
masked := Mask(token)

t.Logf(masked)
assert.Equal(t, len(token), len(masked))
assert.NotEqual(t, token, masked)
}

func TestFilterToken_NotToken(t *testing.T) {
token := "not a token"
masked := Mask(token)

assert.Equal(t, len(token), len(masked))
assert.Equal(t, token, masked)
}

func generateRandomString() string {
b := make([]byte, 40)
for i := range b {
b[i] = letterBytes[rand.Intn(len(letterBytes))]
}
return string(b)
}

0 comments on commit a97ba79

Please sign in to comment.