diff --git a/docker-compose.yml b/docker-compose.yml index 8271245e..ad92837d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,7 +20,7 @@ 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: @@ -28,7 +28,7 @@ services: - 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: diff --git a/src/redis/driver_impl.go b/src/redis/driver_impl.go index 280a7cbb..f1516da2 100644 --- a/src/redis/driver_impl.go +++ b/src/redis/driver_impl.go @@ -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 { @@ -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 @@ -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)) } diff --git a/src/utils/utilities.go b/src/utils/utilities.go index c8001b03..f9ecf856 100644 --- a/src/utils/utilities.go +++ b/src/utils/utilities.go @@ -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" ) @@ -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, ",") +} diff --git a/test/utils/utilities_test.go b/test/utils/utilities_test.go new file mode 100644 index 00000000..aa3768d4 --- /dev/null +++ b/test/utils/utilities_test.go @@ -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)) +}