Skip to content

Commit

Permalink
Mask redis credentials in logs (#347)
Browse files Browse the repository at this point in the history
* use golang 1.18 in docker images

Signed-off-by: Marcel Wiederer <[email protected]>

* mask redis credentials when logging the connection strings

Signed-off-by: Marcel Wiederer <[email protected]>

Co-authored-by: Marcel Wiederer <[email protected]>
  • Loading branch information
m-rcl and Marcel Wiederer authored Jul 26, 2022
1 parent 1f4ea68 commit db150da
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 4 deletions.
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ services:

# minimal container that builds the ratelimit service binary and exits.
ratelimit-build:
image: golang:1.14-alpine
image: golang:1.18-alpine
working_dir: /go/src/github.com/envoyproxy/ratelimit
command: go build -o /usr/local/bin/ratelimit ./src/service_cmd/main.go
volumes:
- .:/go/src/github.com/envoyproxy/ratelimit
- binary:/usr/local/bin/

ratelimit-client-build:
image: golang:1.14-alpine
image: golang:1.18-alpine
working_dir: /go/src/github.com/envoyproxy/ratelimit
command: go build -o /usr/local/bin/ratelimit_client ./src/client_cmd/main.go
volumes:
Expand Down
6 changes: 4 additions & 2 deletions src/redis/driver_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
logger "github.com/sirupsen/logrus"

"github.com/envoyproxy/ratelimit/src/server"
"github.com/envoyproxy/ratelimit/src/utils"
)

type poolStats struct {
Expand Down Expand Up @@ -65,7 +66,8 @@ func checkError(err error) {

func NewClientImpl(scope stats.Scope, useTls bool, auth, redisSocketType, redisType, url string, poolSize int,
pipelineWindow time.Duration, pipelineLimit int, tlsConfig *tls.Config, healthCheckActiveConnection bool, srv server.Server) Client {
logger.Warnf("connecting to redis on %s with pool size %d", url, poolSize)
maskedUrl := utils.MaskCredentialsInUrl(url)
logger.Warnf("connecting to redis on %s with pool size %d", maskedUrl, poolSize)

df := func(network, addr string) (radix.Conn, error) {
var dialOpts []radix.DialOpt
Expand All @@ -75,7 +77,7 @@ func NewClientImpl(scope stats.Scope, useTls bool, auth, redisSocketType, redisT
}

if auth != "" {
logger.Warnf("enabling authentication to redis on %s", url)
logger.Warnf("enabling authentication to redis on %s", maskedUrl)

dialOpts = append(dialOpts, radix.DialAuthPass(auth))
}
Expand Down
20 changes: 20 additions & 0 deletions src/utils/utilities.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package utils

import (
"strings"

pb "github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v3"
"github.com/golang/protobuf/ptypes/duration"
)
Expand Down Expand Up @@ -41,3 +43,21 @@ func Max(a uint32, b uint32) uint32 {
}
return b
}

// Mask credentials from a redis connection string like
// foo,redis://user:pass@redisurl1,redis://user:pass@redisurl2
// resulting in
// foo,redis://*****@redisurl1,redis://*****@redisurl2
func MaskCredentialsInUrl(url string) string {
urls := strings.Split(url, ",")

for i := 0; i < len(urls); i++ {
url := urls[i]
authUrlParts := strings.Split(url, "@")
if len(authUrlParts) > 1 && strings.HasPrefix(authUrlParts[0], "redis://") {
urls[i] = "redis://*****@" + authUrlParts[len(authUrlParts)-1]
}
}

return strings.Join(urls, ",")
}
41 changes: 41 additions & 0 deletions test/utils/utilities_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package utils_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/envoyproxy/ratelimit/src/utils"
)

func TestMaskCredentialsInUrl(t *testing.T) {
url := "redis:6379"
assert.Equal(t, url, utils.MaskCredentialsInUrl(url))

url = "redis://foo:bar@redis:6379"
expected := "redis://*****@redis:6379"
assert.Equal(t, expected, utils.MaskCredentialsInUrl(url))
}

func TestMaskCredentialsInUrlCluster(t *testing.T) {
url := "redis1:6379,redis2:6379"
assert.Equal(t, url, utils.MaskCredentialsInUrl(url))

url = "redis://foo:bar@redis1:6379,redis://foo:bar@redis2:6379"
expected := "redis://*****@redis1:6379,redis://*****@redis2:6379"
assert.Equal(t, expected, utils.MaskCredentialsInUrl(url))

url = "redis://foo:b@r@redis1:6379,redis://foo:b@r@redis2:6379"
expected = "redis://*****@redis1:6379,redis://*****@redis2:6379"
assert.Equal(t, expected, utils.MaskCredentialsInUrl(url))
}

func TestMaskCredentialsInUrlSentinel(t *testing.T) {
url := "foobar,redis://foo:bar@redis1:6379,redis://foo:bar@redis2:6379"
expected := "foobar,redis://*****@redis1:6379,redis://*****@redis2:6379"
assert.Equal(t, expected, utils.MaskCredentialsInUrl(url))

url = "foob@r,redis://foo:b@r@redis1:6379,redis://foo:b@r@redis2:6379"
expected = "foob@r,redis://*****@redis1:6379,redis://*****@redis2:6379"
assert.Equal(t, expected, utils.MaskCredentialsInUrl(url))
}

0 comments on commit db150da

Please sign in to comment.