diff --git a/.secrets.baseline b/.secrets.baseline index c976f8b..85a9b64 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "package-lock.json|go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2021-08-03T22:01:08Z", + "generated_at": "2021-10-23T22:14:07Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -96,7 +96,7 @@ "hashed_secret": "bc2f74c22f98f7b6ffbc2f67453dbfa99bce9a32", "is_secret": false, "is_verified": false, - "line_number": 519, + "line_number": 554, "type": "Secret Keyword", "verified_result": null } @@ -106,7 +106,7 @@ "hashed_secret": "1f5e25be9b575e9f5d39c82dfd1d9f4d73f1975c", "is_secret": false, "is_verified": false, - "line_number": 1116, + "line_number": 1161, "type": "Secret Keyword", "verified_result": null }, @@ -114,7 +114,7 @@ "hashed_secret": "84ba4ce8a59ed2d6e90726d57cdc4a927d3672b2", "is_secret": false, "is_verified": false, - "line_number": 1353, + "line_number": 1398, "type": "Secret Keyword", "verified_result": null }, @@ -122,7 +122,7 @@ "hashed_secret": "62cdb7020ff920e5aa642c3d4066950dd1f01f4d", "is_secret": false, "is_verified": false, - "line_number": 1396, + "line_number": 1441, "type": "Secret Keyword", "verified_result": null }, @@ -130,7 +130,7 @@ "hashed_secret": "ec7ec9d8ff520250fd5ca955c6474c6d70022407", "is_secret": false, "is_verified": false, - "line_number": 1404, + "line_number": 1449, "type": "JSON Web Token", "verified_result": null }, @@ -138,7 +138,7 @@ "hashed_secret": "40ce4379f5763c05b71c88f9a371809fdbce6a21", "is_secret": false, "is_verified": false, - "line_number": 1498, + "line_number": 1543, "type": "Secret Keyword", "verified_result": null }, @@ -146,7 +146,7 @@ "hashed_secret": "9addbf544119efa4a64223b649750a510f0d463f", "is_secret": false, "is_verified": false, - "line_number": 1524, + "line_number": 1569, "type": "Secret Keyword", "verified_result": null } @@ -248,7 +248,7 @@ "hashed_secret": "fed915afaba64ebcdfeb805d59ea09a33275c423", "is_secret": false, "is_verified": false, - "line_number": 159, + "line_number": 157, "type": "Secret Keyword", "verified_result": null }, @@ -256,7 +256,7 @@ "hashed_secret": "c1bd026029d704c1543f56c9b0817395bec76165", "is_secret": false, "is_verified": false, - "line_number": 163, + "line_number": 161, "type": "Secret Keyword", "verified_result": null } @@ -354,7 +354,7 @@ "hashed_secret": "f75b33f87ffeacb3a4f793a09693e672e07449ff", "is_secret": false, "is_verified": false, - "line_number": 100, + "line_number": 101, "type": "Secret Keyword", "verified_result": null }, @@ -362,7 +362,7 @@ "hashed_secret": "84ed7427f222c7a1f43567e1bb3058365a81bbcb", "is_secret": false, "is_verified": false, - "line_number": 266, + "line_number": 267, "type": "Secret Keyword", "verified_result": null }, @@ -370,7 +370,7 @@ "hashed_secret": "d4a9d12d425a0edaf333f49c6004b6d417eeb87b", "is_secret": false, "is_verified": false, - "line_number": 267, + "line_number": 268, "type": "Secret Keyword", "verified_result": null } @@ -380,7 +380,7 @@ "hashed_secret": "ec7ec9d8ff520250fd5ca955c6474c6d70022407", "is_secret": false, "is_verified": false, - "line_number": 39, + "line_number": 42, "type": "JSON Web Token", "verified_result": null }, @@ -388,7 +388,7 @@ "hashed_secret": "f624446964a455348d97335a75468555c4375a8d", "is_secret": false, "is_verified": false, - "line_number": 41, + "line_number": 44, "type": "JSON Web Token", "verified_result": null }, @@ -396,7 +396,7 @@ "hashed_secret": "576e3a0ad157f3cf3c6c64dd574c6d86ebe09210", "is_secret": false, "is_verified": false, - "line_number": 47, + "line_number": 50, "type": "JSON Web Token", "verified_result": null }, @@ -404,7 +404,7 @@ "hashed_secret": "2e43f72bbea78272c019fb7f4abd2529e3c8ef43", "is_secret": false, "is_verified": false, - "line_number": 49, + "line_number": 52, "type": "JSON Web Token", "verified_result": null }, @@ -412,7 +412,7 @@ "hashed_secret": "b94e9f3d7e001981b2dd49f2a70822a8ac8f3e68", "is_secret": false, "is_verified": false, - "line_number": 352, + "line_number": 369, "type": "Secret Keyword", "verified_result": null }, @@ -420,7 +420,7 @@ "hashed_secret": "10db2b8939e12fa3259bf89a63eab34ee3c281b2", "is_secret": false, "is_verified": false, - "line_number": 572, + "line_number": 599, "type": "Secret Keyword", "verified_result": null }, @@ -428,7 +428,7 @@ "hashed_secret": "84ba4ce8a59ed2d6e90726d57cdc4a927d3672b2", "is_secret": false, "is_verified": false, - "line_number": 615, + "line_number": 642, "type": "Secret Keyword", "verified_result": null }, @@ -436,7 +436,7 @@ "hashed_secret": "4080eeeaf54faf879b9e8d99c49a8503f7e855bb", "is_secret": false, "is_verified": false, - "line_number": 630, + "line_number": 657, "type": "Secret Keyword", "verified_result": null }, @@ -444,7 +444,7 @@ "hashed_secret": "32e8612d8ca77c7ea8374aa7918db8e5df9252ed", "is_secret": false, "is_verified": false, - "line_number": 745, + "line_number": 776, "type": "Secret Keyword", "verified_result": null } @@ -464,7 +464,7 @@ "hashed_secret": "7a5d27bcb7a1e98b6e1bfca4df223ed578a47283", "is_secret": false, "is_verified": false, - "line_number": 88, + "line_number": 89, "type": "Secret Keyword", "verified_result": null }, @@ -472,7 +472,7 @@ "hashed_secret": "c2df5d3d760ff42f33fb38e2534d4c1b7ddde3ab", "is_secret": false, "is_verified": false, - "line_number": 88, + "line_number": 89, "type": "Secret Keyword", "verified_result": null }, @@ -480,7 +480,7 @@ "hashed_secret": "f75b33f87ffeacb3a4f793a09693e672e07449ff", "is_secret": false, "is_verified": false, - "line_number": 95, + "line_number": 96, "type": "Secret Keyword", "verified_result": null }, @@ -488,7 +488,7 @@ "hashed_secret": "7ea6be9eecb6605329a1b1870c2fd2af9b896991", "is_secret": false, "is_verified": false, - "line_number": 98, + "line_number": 99, "type": "Secret Keyword", "verified_result": null } @@ -498,7 +498,7 @@ "hashed_secret": "c8f0df25bade89c1873f5f01b85bcfb921443ac6", "is_secret": false, "is_verified": false, - "line_number": 30, + "line_number": 33, "type": "JSON Web Token", "verified_result": null }, @@ -506,7 +506,7 @@ "hashed_secret": "42de4dc186286dbdc2381b3e09a054f96e1995bc", "is_secret": false, "is_verified": false, - "line_number": 563, + "line_number": 589, "type": "Secret Keyword", "verified_result": null }, @@ -514,7 +514,7 @@ "hashed_secret": "1f5e25be9b575e9f5d39c82dfd1d9f4d73f1975c", "is_secret": false, "is_verified": false, - "line_number": 704, + "line_number": 734, "type": "Secret Keyword", "verified_result": null }, @@ -522,7 +522,7 @@ "hashed_secret": "333f0f8814d63e7268f80e1e65e7549137d2350c", "is_secret": false, "is_verified": false, - "line_number": 718, + "line_number": 748, "type": "Secret Keyword", "verified_result": null }, @@ -530,7 +530,7 @@ "hashed_secret": "84ba4ce8a59ed2d6e90726d57cdc4a927d3672b2", "is_secret": false, "is_verified": false, - "line_number": 721, + "line_number": 751, "type": "Secret Keyword", "verified_result": null }, @@ -538,7 +538,7 @@ "hashed_secret": "32e8612d8ca77c7ea8374aa7918db8e5df9252ed", "is_secret": false, "is_verified": false, - "line_number": 740, + "line_number": 770, "type": "Secret Keyword", "verified_result": null } @@ -577,6 +577,16 @@ "verified_result": null } ], + "v5/core/utils_test.go": [ + { + "hashed_secret": "0266262f439c732a31b9353ced05c9e777a07c54", + "is_secret": false, + "is_verified": false, + "line_number": 599, + "type": "Secret Keyword", + "verified_result": null + } + ], "v5/resources/ibm-credentials.env": [ { "hashed_secret": "62cdb7020ff920e5aa642c3d4066950dd1f01f4d", @@ -712,7 +722,7 @@ } ] }, - "version": "0.13.1+ibm.40.dss", + "version": "0.13.1+ibm.46.dss", "word_list": { "file": null, "hash": null diff --git a/v5/core/base_service.go b/v5/core/base_service.go index 04130f9..53aa037 100644 --- a/v5/core/base_service.go +++ b/v5/core/base_service.go @@ -342,7 +342,7 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta if GetLogger().IsLogLevelEnabled(LevelDebug) { buf, dumpErr := httputil.DumpRequestOut(req, req.Body != nil) if dumpErr == nil { - GetLogger().Debug("Request:\n%s\n", string(buf)) + GetLogger().Debug("Request:\n%s\n", RedactSecrets(string(buf))) } else { GetLogger().Debug("error while attempting to log outbound request: %s", dumpErr.Error()) } @@ -378,7 +378,7 @@ func (service *BaseService) Request(req *http.Request, result interface{}) (deta if GetLogger().IsLogLevelEnabled(LevelDebug) { buf, dumpErr := httputil.DumpResponse(httpResponse, httpResponse.Body != nil) if err == nil { - GetLogger().Debug("Response:\n%s\n", string(buf)) + GetLogger().Debug("Response:\n%s\n", RedactSecrets(string(buf))) } else { GetLogger().Debug("error while attempting to log inbound response: %s", dumpErr.Error()) } @@ -609,7 +609,10 @@ type httpLogger struct { } func (l *httpLogger) Printf(format string, inserts ...interface{}) { - GetLogger().Log(LevelDebug, format, inserts...) + if GetLogger().IsLogLevelEnabled(LevelDebug) { + msg := fmt.Sprintf(format, inserts...) + GetLogger().Log(LevelDebug, RedactSecrets(msg)) + } } // NewRetryableHTTPClient returns a new instance of go-retryablehttp.Client diff --git a/v5/core/container_authenticator.go b/v5/core/container_authenticator.go index 2b63c08..973dcdc 100644 --- a/v5/core/container_authenticator.go +++ b/v5/core/container_authenticator.go @@ -92,8 +92,8 @@ type ContainerAuthenticator struct { } const ( - defaultCRTokenFilename = "/var/run/secrets/tokens/vault-token" // #nosec G101 - iamGrantTypeCRToken = "urn:ibm:params:oauth:grant-type:cr-token" // #nosec G101 + defaultCRTokenFilename = "/var/run/secrets/tokens/vault-token" // #nosec G101 + iamGrantTypeCRToken = "urn:ibm:params:oauth:grant-type:cr-token" // #nosec G101 ) var craRequestTokenMutex sync.Mutex @@ -415,7 +415,7 @@ func (authenticator *ContainerAuthenticator) RequestToken() (*IamTokenServerResp if GetLogger().IsLogLevelEnabled(LevelDebug) { buf, dumpErr := httputil.DumpRequestOut(req, req.Body != nil) if dumpErr == nil { - GetLogger().Debug("Request:\n%s\n", string(buf)) + GetLogger().Debug("Request:\n%s\n", RedactSecrets(string(buf))) } else { GetLogger().Debug(fmt.Sprintf("error while attempting to log outbound request: %s", dumpErr.Error())) } @@ -432,7 +432,7 @@ func (authenticator *ContainerAuthenticator) RequestToken() (*IamTokenServerResp if GetLogger().IsLogLevelEnabled(LevelDebug) { buf, dumpErr := httputil.DumpResponse(resp, req.Body != nil) if dumpErr == nil { - GetLogger().Debug("Response:\n%s\n", string(buf)) + GetLogger().Debug("Response:\n%s\n", RedactSecrets(string(buf))) } else { GetLogger().Debug(fmt.Sprintf("error while attempting to log inbound response: %s", dumpErr.Error())) } diff --git a/v5/core/cp4d_authenticator.go b/v5/core/cp4d_authenticator.go index 2de1fbf..2dab382 100644 --- a/v5/core/cp4d_authenticator.go +++ b/v5/core/cp4d_authenticator.go @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/http/httputil" "strconv" "sync" "time" @@ -309,10 +310,32 @@ func (authenticator *CloudPakForDataAuthenticator) requestToken() (tokenResponse } } + // If debug is enabled, then dump the request. + if GetLogger().IsLogLevelEnabled(LevelDebug) { + buf, dumpErr := httputil.DumpRequestOut(req, req.Body != nil) + if dumpErr == nil { + GetLogger().Debug("Request:\n%s\n", RedactSecrets(string(buf))) + } else { + GetLogger().Debug(fmt.Sprintf("error while attempting to log outbound request: %s", dumpErr.Error())) + } + } + + GetLogger().Debug("Invoking CP4D token service operation: %s", builder.URL) resp, err := authenticator.Client.Do(req) if err != nil { return } + GetLogger().Debug("Returned from CP4D token service operation, received status code %d", resp.StatusCode) + + // If debug is enabled, then dump the response. + if GetLogger().IsLogLevelEnabled(LevelDebug) { + buf, dumpErr := httputil.DumpResponse(resp, req.Body != nil) + if dumpErr == nil { + GetLogger().Debug("Response:\n%s\n", RedactSecrets(string(buf))) + } else { + GetLogger().Debug(fmt.Sprintf("error while attempting to log inbound response: %s", dumpErr.Error())) + } + } if resp.StatusCode < 200 || resp.StatusCode >= 300 { buff := new(bytes.Buffer) diff --git a/v5/core/cp4d_authenticator_test.go b/v5/core/cp4d_authenticator_test.go index 335e006..76fe85f 100644 --- a/v5/core/cp4d_authenticator_test.go +++ b/v5/core/cp4d_authenticator_test.go @@ -30,6 +30,9 @@ import ( ) const ( + // To enable debug logging during test execution, set this to "LevelDebug" + cp4dAuthTestLogLevel LogLevel = LevelError + // These access tokens were obtained by running curl to invoke the POST /v1/authorize against a CP4D environment. // Username/password @@ -121,6 +124,8 @@ func TestCp4dConfigErrorsAPIKey(t *testing.T) { } func TestCp4dAuthenticateFailure(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) _, _ = w.Write([]byte("Sorry you are not authorized")) @@ -166,6 +171,8 @@ func verifyAuthRequest(t *testing.T, r *http.Request, } func TestCp4dGetTokenSuccessPW(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -200,6 +207,8 @@ func TestCp4dGetTokenSuccessPW(t *testing.T) { } func TestCp4dGetTokenSuccessAPIKey(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -234,6 +243,8 @@ func TestCp4dGetTokenSuccessAPIKey(t *testing.T) { } func TestCp4dGetCachedTokenSuccessPW(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -271,6 +282,8 @@ func TestCp4dGetCachedTokenSuccessPW(t *testing.T) { } func TestCp4dGetCachedTokenAPIKey(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -308,6 +321,8 @@ func TestCp4dGetCachedTokenAPIKey(t *testing.T) { } func TestCp4dGetTokenAuthFailure(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusForbidden) _, _ = w.Write([]byte("Forbidden!")) @@ -340,6 +355,8 @@ func TestCp4dGetTokenAuthFailure(t *testing.T) { } func TestCp4dGetTokenDeserFailure(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte("Bad access token response!")) @@ -363,6 +380,8 @@ func TestCp4dGetTokenDeserFailure(t *testing.T) { } func TestCp4dBackgroundTokenRefreshSuccess(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -410,6 +429,8 @@ func TestCp4dBackgroundTokenRefreshSuccess(t *testing.T) { } func TestCp4dBackgroundTokenRefreshAuthFailure(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -462,6 +483,8 @@ func TestCp4dBackgroundTokenRefreshAuthFailure(t *testing.T) { } func TestCp4dBackgroundTokenRefreshIdle(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -523,6 +546,8 @@ func TestCp4dBackgroundTokenRefreshIdle(t *testing.T) { } func TestCp4dDisableSSL(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { verifyAuthRequest(t, r, "mookie", "betts", "") @@ -550,6 +575,8 @@ func TestCp4dDisableSSL(t *testing.T) { } func TestCp4dUserHeaders(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { verifyAuthRequest(t, r, "mookie", "", "King of the North") assert.Equal(t, "Value1", r.Header.Get("Header1")) @@ -641,6 +668,8 @@ func TestNewCloudPakForDataAuthenticatorFromMap(t *testing.T) { } func TestCp4dGetTokenTimeoutError(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -683,6 +712,8 @@ func TestCp4dGetTokenTimeoutError(t *testing.T) { } func TestCp4dGetTokenServerError(t *testing.T) { + GetLogger().SetLogLevel(cp4dAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -751,6 +782,8 @@ func TestCp4dGetTokenServerError(t *testing.T) { // // func TestCp4dLiveTokenServer(t *testing.T) { +// GetLogger().SetLogLevel(cp4dAuthTestLogLevel) +// // var request *http.Request // var err error // var authHeader string diff --git a/v5/core/iam_authenticator.go b/v5/core/iam_authenticator.go index afaa950..4a04d0f 100644 --- a/v5/core/iam_authenticator.go +++ b/v5/core/iam_authenticator.go @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/http/httputil" "strconv" "strings" "sync" @@ -84,7 +85,7 @@ var iamNeedsRefreshMutex sync.Mutex const ( // The default (prod) IAM token server base endpoint address. - defaultIamTokenServerEndpoint = "https://iam.cloud.ibm.com" // #nosec G101 + defaultIamTokenServerEndpoint = "https://iam.cloud.ibm.com" // #nosec G101 iamGrantTypeApiKey = "urn:ibm:params:oauth:grant-type:apikey" // #nosec G101 ) @@ -315,10 +316,32 @@ func (authenticator *IamAuthenticator) RequestToken() (*IamTokenServerResponse, } } + // If debug is enabled, then dump the request. + if GetLogger().IsLogLevelEnabled(LevelDebug) { + buf, dumpErr := httputil.DumpRequestOut(req, req.Body != nil) + if dumpErr == nil { + GetLogger().Debug("Request:\n%s\n", RedactSecrets(string(buf))) + } else { + GetLogger().Debug(fmt.Sprintf("error while attempting to log outbound request: %s", dumpErr.Error())) + } + } + + GetLogger().Debug("Invoking IAM 'get token' operation: %s", builder.URL) resp, err := authenticator.Client.Do(req) if err != nil { return nil, err } + GetLogger().Debug("Returned from IAM 'get token' operation, received status code %d", resp.StatusCode) + + // If debug is enabled, then dump the response. + if GetLogger().IsLogLevelEnabled(LevelDebug) { + buf, dumpErr := httputil.DumpResponse(resp, req.Body != nil) + if dumpErr == nil { + GetLogger().Debug("Response:\n%s\n", RedactSecrets(string(buf))) + } else { + GetLogger().Debug(fmt.Sprintf("error while attempting to log inbound response: %s", dumpErr.Error())) + } + } if resp.StatusCode < 200 || resp.StatusCode >= 300 { buff := new(bytes.Buffer) diff --git a/v5/core/iam_authenticator_test.go b/v5/core/iam_authenticator_test.go index 83233e2..918fa70 100644 --- a/v5/core/iam_authenticator_test.go +++ b/v5/core/iam_authenticator_test.go @@ -27,6 +27,9 @@ import ( ) var ( + // To enable debug logging during test execution, set this to "LevelDebug" + iamAuthTestLogLevel LogLevel = LevelError + AccessToken1 string = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImhlbGxvIiwicm9sZSI6InVzZXIiLCJwZXJtaXNzaW9ucyI6WyJhZG1pbmlzdHJhdG9yIiwiZGVwbG95bWVudF9hZG1pbiJdLCJzdWIiOiJoZWxsbyIsImlzcyI6IkpvaG4iLCJhdWQiOiJEU1giLCJ1aWQiOiI5OTkiLCJpYXQiOjE1NjAyNzcwNTEsImV4cCI6MTU2MDI4MTgxOSwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4In0.cIodB4I6CCcX8vfIImz7Cytux3GpWyObt9Gkur5g1QI" AccessToken2 string = "3yJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImhlbGxvIiwicm9sZSI6InVzZXIiLCJwZXJtaXNzaW9ucyI6WyJhZG1pbmlzdHJhdG9yIiwiZGVwbG95bWVudF9hZG1pbiJdLCJzdWIiOiJoZWxsbyIsImlzcyI6IkpvaG4iLCJhdWQiOiJEU1giLCJ1aWQiOiI5OTkiLCJpYXQiOjE1NjAyNzcwNTEsImV4cCI6MTU2MDI4MTgxOSwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4In0.cIodB4I6CCcX8vfIImz7Cytux3GpWyObt9Gkur5g1QI" RefreshToken string = "Xj7Gle500MachEOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImhlbGxvIiwicm9sZSI6InVzZXIiLCJwZXJtaXNzaW9ucyI6WyJhZG1pbmlzdHJhdG9yIiwiZGVwbG95bWVudF9hZG1pbiJdLCJzdWIiOiJoZWxsbyIsImlzcyI6IkpvaG4iLCJhdWQiOiJEU1giLCJ1aWQiOiI5OTkiLCJpYXQiOjE1NjAyNzcwNTEsImV4cCI6MTU2MDI4MTgxOSwianRpIjoiMDRkMjBiMjUtZWUyZC00MDBmLTg2MjMtOGNkODA3MGI1NDY4In0.cIodB4I6CCcX8vfIImz7Cytux3GpWyObt9Gkur5g1QI" @@ -53,6 +56,8 @@ func TestIamConfigErrors(t *testing.T) { } func TestIamAuthenticateFail(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) _, _ = w.Write([]byte("Sorry you are not authorized")) @@ -84,6 +89,8 @@ func TestIamAuthenticateFail(t *testing.T) { } func TestIamGetTokenSuccess(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() @@ -149,6 +156,8 @@ func TestIamGetTokenSuccess(t *testing.T) { } func TestIamGetTokenSuccessWithScope(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() @@ -209,6 +218,8 @@ func TestIamGetTokenSuccessWithScope(t *testing.T) { assert.Equal(t, AccessToken2, authenticator.getTokenData().AccessToken) } func TestIamGetCachedToken(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) @@ -256,6 +267,8 @@ func TestIamGetCachedToken(t *testing.T) { } func TestIamBackgroundTokenRefresh(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { expiration := GetCurrentTime() + 3600 @@ -315,6 +328,8 @@ func TestIamBackgroundTokenRefresh(t *testing.T) { } func TestIamBackgroundTokenRefreshFailure(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { expiration := GetCurrentTime() + 3600 @@ -367,6 +382,8 @@ func TestIamBackgroundTokenRefreshFailure(t *testing.T) { } func TestIamBackgroundTokenRefreshIdle(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // CurrentTime + 1 hour @@ -440,10 +457,11 @@ func TestIamBackgroundTokenRefreshIdle(t *testing.T) { assert.Equal(t, AccessToken2, token) assert.NotNil(t, authenticator.getTokenData()) assert.NotEqual(t, newRefreshTime, authenticator.getTokenData().RefreshTime) - } func TestIamClientIdAndSecret(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + expiration := GetCurrentTime() + 3600 accessToken := "oAeisG8yqPY7sFR_x66Z15" server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -474,6 +492,8 @@ func TestIamClientIdAndSecret(t *testing.T) { } func TestIamRefreshTimeCalculation(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + const timeToLive int64 = 3600 const expireTime int64 = 1563911183 const expected int64 = expireTime - 720 // 720 is 20% of 3600 @@ -491,6 +511,8 @@ func TestIamRefreshTimeCalculation(t *testing.T) { } func TestIamDisableSSL(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + expiration := GetCurrentTime() + 3600 accessToken := "oAeisG8yqPY7sFR_x66Z15" server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -521,6 +543,8 @@ func TestIamDisableSSL(t *testing.T) { } func TestIamUserHeaders(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + expiration := GetCurrentTime() + 3600 accessToken := "oAeisG8yqPY7sFR_x66Z15" server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -553,6 +577,8 @@ func TestIamUserHeaders(t *testing.T) { } func TestIamGetTokenFailure(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusForbidden) _, _ = w.Write([]byte("Sorry you are forbidden")) @@ -584,6 +610,8 @@ func TestIamGetTokenFailure(t *testing.T) { } func TestIamGetTokenTimeoutError(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + firstCall := true server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) @@ -637,6 +665,8 @@ func TestIamGetTokenTimeoutError(t *testing.T) { } func TestIamGetTokenServerError(t *testing.T) { + GetLogger().SetLogLevel(iamAuthTestLogLevel) + firstCall := true expiration := GetCurrentTime() + 3600 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -746,6 +776,8 @@ func TestNewIamAuthenticatorFromMap(t *testing.T) { // // // func TestIamLiveTokenServer(t *testing.T) { +// GetLogger().SetLogLevel(iamAuthTestLogLevel) +// // var request *http.Request // var err error // var authHeader string diff --git a/v5/core/utils.go b/v5/core/utils.go index 90feff2..43645ad 100644 --- a/v5/core/utils.go +++ b/v5/core/utils.go @@ -33,7 +33,6 @@ import ( // Validate is a shared validator instance used to perform validation of structs. var Validate *validator.Validate -var re = regexp.MustCompile(`(?s)\[(\S*)\]`) func init() { Validate = validator.New() @@ -189,7 +188,11 @@ func GetCurrentTime() int64 { return time.Now().Unix() } -// ConvertSlice Marshals 'slice' to a json string, performs +// Pre-compiled regular expression used to remove the surrounding +// [] characters from a JSON string containing a slice (e.g. `["str1", "str2", "str3"]`). +var reJsonSlice = regexp.MustCompile(`(?s)\[(\S*)\]`) + +// ConvertSlice marshals 'slice' to a json string, performs // string manipulation on the resulting string, and converts // the string to a '[]string'. If 'slice' is nil, not a 'slice' type, // or an error occurred during conversion, an error will be returned @@ -228,7 +231,7 @@ func ConvertSlice(slice interface{}) (s []string, err error) { jsonString := string(jsonBuffer) // Use regex to convert the json string to a string slice - match := re.FindStringSubmatch(jsonString) + match := reJsonSlice.FindStringSubmatch(jsonString) if match != nil && match[1] != "" { newString := match[1] s = strings.Split(newString, ",") @@ -263,8 +266,8 @@ func SliceContains(slice []string, contains string) bool { return false } -// return a pointer to the value of query parameter `param` from url, -// or nil when not found +// GetQueryParam() returns a pointer to the value of query parameter `param` from urlStr, +// or nil if not found. func GetQueryParam(urlStr *string, param string) (*string, error) { if urlStr == nil || *urlStr == "" { return nil, nil @@ -286,3 +289,20 @@ func GetQueryParam(urlStr *string, param string) (*string, error) { } return &v, nil } + +// Pre-compiled regular expressions used by RedactSecrets(). +var reAuthHeader = regexp.MustCompile(`(?m)^(Authorization|X-Auth\S*): .*`) +var rePassword1 = regexp.MustCompile(`(?i)(password|token|apikey|api_key|passcode)=[^&]*(&|$)`) +var rePassword2 = regexp.MustCompile(`(?i)"([^"]*(password|token|apikey|api_key)[^"_]*)":\s*"[^\,]*"`) + +// RedactSecrets() returns the input string with secrets redacted. +func RedactSecrets(input string) string { + var redacted = "[redacted]" + + redactedString := input + redactedString = reAuthHeader.ReplaceAllString(redactedString, "$1: "+redacted) + redactedString = rePassword1.ReplaceAllString(redactedString, "$1="+redacted+"$2") + redactedString = rePassword2.ReplaceAllString(redactedString, fmt.Sprintf(`"$1":"%s"`, redacted)) + + return redactedString +} diff --git a/v5/core/utils_test.go b/v5/core/utils_test.go index 107ac62..76496ab 100644 --- a/v5/core/utils_test.go +++ b/v5/core/utils_test.go @@ -491,7 +491,7 @@ func TestConvertSliceBadInput(t *testing.T) { assert.Nil(t, convertedSlice) // map[string]byte - myByteMap := map[string][]byte{"myByteArray": []byte{01, 02, 03, 04}} + myByteMap := map[string][]byte{"myByteArray": {01, 02, 03, 04}} convertedSlice, err = ConvertSlice(myByteMap) assert.NotNil(t, err) assert.Nil(t, convertedSlice) @@ -589,3 +589,17 @@ func TestGetQueryParam(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "foo", *next) } + +func TestRedactSecrets(t *testing.T) { + assert.NotContains(t, RedactSecrets("Authorization: Bearer secret"), "secret") + assert.NotContains(t, RedactSecrets("Authorization: Basic secret"), "secret") + assert.NotContains(t, RedactSecrets("X-Authorization: secret"), "secret") + + assert.NotContains(t, RedactSecrets("PASSword=secret"), "secret") + assert.NotContains(t, RedactSecrets("ApIKey=secret"), "secret") + assert.NotContains(t, RedactSecrets("toKen=secret"), "secret") + assert.NotContains(t, RedactSecrets("passCode=secret"), "secret") + + assert.NotContains(t, RedactSecrets(`"token": "secret",`), "secret") + assert.NotContains(t, RedactSecrets(`xxx "apIKEy": "secret",xxx`), "secret") +}