From 28e8f812c9e73eb68ce9acdc4777bfa94b47723b Mon Sep 17 00:00:00 2001 From: Dane Hammer Date: Wed, 16 Mar 2022 01:53:41 +0200 Subject: [PATCH 1/3] Redacted URL in logs / errors So that basic auth creds, if any, won't show up in logs --- client.go | 14 +++++++------- client_test.go | 19 +++++++++++++++++-- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/client.go b/client.go index 7a073d8..f3eb09b 100644 --- a/client.go +++ b/client.go @@ -556,9 +556,9 @@ func (c *Client) Do(req *Request) (*http.Response, error) { if logger != nil { switch v := logger.(type) { case LeveledLogger: - v.Debug("performing request", "method", req.Method, "url", req.URL) + v.Debug("performing request", "method", req.Method, "url", req.URL.Redacted()) case Logger: - v.Printf("[DEBUG] %s %s", req.Method, req.URL) + v.Printf("[DEBUG] %s %s", req.Method, req.URL.Redacted()) } } @@ -604,9 +604,9 @@ func (c *Client) Do(req *Request) (*http.Response, error) { if doErr != nil { switch v := logger.(type) { case LeveledLogger: - v.Error("request failed", "error", doErr, "method", req.Method, "url", req.URL) + v.Error("request failed", "error", doErr, "method", req.Method, "url", req.URL.Redacted()) case Logger: - v.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL, doErr) + v.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL.Redacted(), doErr) } } else { // Call this here to maintain the behavior of logging all requests, @@ -642,7 +642,7 @@ func (c *Client) Do(req *Request) (*http.Response, error) { wait := c.Backoff(c.RetryWaitMin, c.RetryWaitMax, i, resp) if logger != nil { - desc := fmt.Sprintf("%s %s", req.Method, req.URL) + desc := fmt.Sprintf("%s %s", req.Method, req.URL.Redacted()) if resp != nil { desc = fmt.Sprintf("%s (status: %d)", desc, resp.StatusCode) } @@ -694,11 +694,11 @@ func (c *Client) Do(req *Request) (*http.Response, error) { // communicate why if err == nil { return nil, fmt.Errorf("%s %s giving up after %d attempt(s)", - req.Method, req.URL, attempt) + req.Method, req.URL.Redacted(), attempt) } return nil, fmt.Errorf("%s %s giving up after %d attempt(s): %w", - req.Method, req.URL, attempt, err) + req.Method, req.URL.Redacted(), attempt, err) } // Try to read the response body so we can reuse this connection. diff --git a/client_test.go b/client_test.go index 901c86d..092d593 100644 --- a/client_test.go +++ b/client_test.go @@ -256,17 +256,32 @@ func TestClient_Do_fails(t *testing.T) { })) defer ts.Close() + serverUrlWithBasicAuth, err := url.Parse(ts.URL) + if err != nil { + t.Fatalf("failed parsing test server url: %s", ts.URL) + } + serverUrlWithBasicAuth.User = url.UserPassword("user", "pasten") + tests := []struct { + url string name string cr CheckRetry err string }{ { + url: ts.URL, name: "default_retry_policy", cr: DefaultRetryPolicy, err: "giving up after 3 attempt(s)", }, { + url: serverUrlWithBasicAuth.String(), + name: "default_retry_policy_url_with_basic_auth", + cr: DefaultRetryPolicy, + err: serverUrlWithBasicAuth.Redacted() + " giving up after 3 attempt(s)", + }, + { + url: ts.URL, name: "error_propagated_retry_policy", cr: ErrorPropagatedRetryPolicy, err: "giving up after 3 attempt(s): unexpected HTTP status 500 Internal Server Error", @@ -283,7 +298,7 @@ func TestClient_Do_fails(t *testing.T) { client.RetryMax = 2 // Create the request - req, err := NewRequest("POST", ts.URL, nil) + req, err := NewRequest("POST", tt.url, nil) if err != nil { t.Fatalf("err: %v", err) } @@ -291,7 +306,7 @@ func TestClient_Do_fails(t *testing.T) { // Send the request. _, err = client.Do(req) if err == nil || !strings.HasSuffix(err.Error(), tt.err) { - t.Fatalf("expected giving up error, got: %#v", err) + t.Fatalf("expected %#v, got: %#v", tt.err, err) } }) } From 65e8765114ba1d9241fa0d5a87dd55699d4c4b38 Mon Sep 17 00:00:00 2001 From: Danny Shemesh Date: Wed, 16 Mar 2022 01:58:01 +0200 Subject: [PATCH 2/3] Apparently Redacted() was added in go 1.15 --- .circleci/config.yml | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c58e7ba..2b21122 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -51,5 +51,5 @@ workflows: - run-tests: matrix: parameters: - go-version: ["1.14.2"] + go-version: ["1.15.15"] name: test-go-<< matrix.go-version >> diff --git a/go.mod b/go.mod index 7cc02b7..9e08f52 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,4 @@ require ( github.com/hashicorp/go-hclog v0.9.2 ) -go 1.13 +go 1.15 From b2aee5005449da59dc00efd9c30d91556e739c79 Mon Sep 17 00:00:00 2001 From: Danny Shemesh Date: Wed, 16 Mar 2022 09:47:37 +0200 Subject: [PATCH 3/3] Copied Redacted() implementation from go 1.15 --- .circleci/config.yml | 2 +- client.go | 28 +++++++++++++++++++++------- client_test.go | 2 +- go.mod | 2 +- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2b21122..c58e7ba 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -51,5 +51,5 @@ workflows: - run-tests: matrix: parameters: - go-version: ["1.15.15"] + go-version: ["1.14.2"] name: test-go-<< matrix.go-version >> diff --git a/client.go b/client.go index f3eb09b..90a738c 100644 --- a/client.go +++ b/client.go @@ -556,9 +556,9 @@ func (c *Client) Do(req *Request) (*http.Response, error) { if logger != nil { switch v := logger.(type) { case LeveledLogger: - v.Debug("performing request", "method", req.Method, "url", req.URL.Redacted()) + v.Debug("performing request", "method", req.Method, "url", redactURL(req.URL)) case Logger: - v.Printf("[DEBUG] %s %s", req.Method, req.URL.Redacted()) + v.Printf("[DEBUG] %s %s", req.Method, redactURL(req.URL)) } } @@ -604,9 +604,9 @@ func (c *Client) Do(req *Request) (*http.Response, error) { if doErr != nil { switch v := logger.(type) { case LeveledLogger: - v.Error("request failed", "error", doErr, "method", req.Method, "url", req.URL.Redacted()) + v.Error("request failed", "error", doErr, "method", req.Method, "url", redactURL(req.URL)) case Logger: - v.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL.Redacted(), doErr) + v.Printf("[ERR] %s %s request failed: %v", req.Method, redactURL(req.URL), doErr) } } else { // Call this here to maintain the behavior of logging all requests, @@ -642,7 +642,7 @@ func (c *Client) Do(req *Request) (*http.Response, error) { wait := c.Backoff(c.RetryWaitMin, c.RetryWaitMax, i, resp) if logger != nil { - desc := fmt.Sprintf("%s %s", req.Method, req.URL.Redacted()) + desc := fmt.Sprintf("%s %s", req.Method, redactURL(req.URL)) if resp != nil { desc = fmt.Sprintf("%s (status: %d)", desc, resp.StatusCode) } @@ -694,11 +694,11 @@ func (c *Client) Do(req *Request) (*http.Response, error) { // communicate why if err == nil { return nil, fmt.Errorf("%s %s giving up after %d attempt(s)", - req.Method, req.URL.Redacted(), attempt) + req.Method, redactURL(req.URL), attempt) } return nil, fmt.Errorf("%s %s giving up after %d attempt(s): %w", - req.Method, req.URL.Redacted(), attempt, err) + req.Method, redactURL(req.URL), attempt, err) } // Try to read the response body so we can reuse this connection. @@ -779,3 +779,17 @@ func (c *Client) StandardClient() *http.Client { Transport: &RoundTripper{Client: c}, } } + +// Taken from url.URL#Redacted() which was introduced in go 1.15. +// We can switch to using it directly if we'll bump the minimum required go version. +func redactURL(u *url.URL) string { + if u == nil { + return "" + } + + ru := *u + if _, has := ru.User.Password(); has { + ru.User = url.UserPassword(ru.User.Username(), "xxxxx") + } + return ru.String() +} diff --git a/client_test.go b/client_test.go index 092d593..9438648 100644 --- a/client_test.go +++ b/client_test.go @@ -278,7 +278,7 @@ func TestClient_Do_fails(t *testing.T) { url: serverUrlWithBasicAuth.String(), name: "default_retry_policy_url_with_basic_auth", cr: DefaultRetryPolicy, - err: serverUrlWithBasicAuth.Redacted() + " giving up after 3 attempt(s)", + err: redactURL(serverUrlWithBasicAuth) + " giving up after 3 attempt(s)", }, { url: ts.URL, diff --git a/go.mod b/go.mod index 9e08f52..7cc02b7 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,4 @@ require ( github.com/hashicorp/go-hclog v0.9.2 ) -go 1.15 +go 1.13