diff --git a/README.md b/README.md index 4f4aae8..b2d9e4c 100644 --- a/README.md +++ b/README.md @@ -180,3 +180,12 @@ top # go inside of function memory usage list main.callPasswordSafeAPI ``` + +## Fuzzing Testing + +Run Fuzz Tests + +```bash +go test -fuzz=FuzzGetManagedAccount -fuzztime=10s ./fuzzing//managed_accounts +go test -fuzz=FuzzGetSecret -fuzztime=10s ./fuzzing/secrets +``` \ No newline at end of file diff --git a/api/managed_account/managed_account.go b/api/managed_account/managed_account.go index 9c88487..4df88f3 100644 --- a/api/managed_account/managed_account.go +++ b/api/managed_account/managed_account.go @@ -5,6 +5,7 @@ package managed_accounts import ( "bytes" "encoding/json" + "errors" "fmt" "io" "net/url" @@ -54,6 +55,10 @@ func (managedAccountObj *ManagedAccountstObj) ManageAccountFlow(secretsToRetriev secretDictionary := make(map[string]string) var saveLastErr error = nil + if len(secretsToRetrieve) == 0 { + return secretDictionary, errors.New("empty managed account list") + } + for _, secretToRetrieve := range secretsToRetrieve { retrievalData := strings.Split(secretToRetrieve, separator) systemName := retrievalData[0] diff --git a/api/secrets/secrets.go b/api/secrets/secrets.go index 45634a6..9a46ff9 100644 --- a/api/secrets/secrets.go +++ b/api/secrets/secrets.go @@ -58,6 +58,10 @@ func (secretObj *SecretObj) GetSecretFlow(secretsToRetrieve []string, separator secretDictionary := make(map[string]string) var saveLastErr error = nil + if len(secretsToRetrieve) == 0 { + return secretDictionary, errors.New("empty secret list") + } + for _, secretToRetrieve := range secretsToRetrieve { retrievalData := strings.Split(secretToRetrieve, separator) secretTitle := retrievalData[len(retrievalData)-1] diff --git a/fuzzing/managed_accounts/get_managed_accounts_fuzz_test.go b/fuzzing/managed_accounts/get_managed_accounts_fuzz_test.go new file mode 100644 index 0000000..1de9ab0 --- /dev/null +++ b/fuzzing/managed_accounts/get_managed_accounts_fuzz_test.go @@ -0,0 +1,123 @@ +package fuzzing_managed_account + +import ( + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" + "time" + + "github.com/BeyondTrust/go-client-library-passwordsafe/api/authentication" + "github.com/BeyondTrust/go-client-library-passwordsafe/api/logging" + managed_accounts "github.com/BeyondTrust/go-client-library-passwordsafe/api/managed_account" + "github.com/BeyondTrust/go-client-library-passwordsafe/api/utils" + backoff "github.com/cenkalti/backoff/v4" + "go.uber.org/zap" +) + +type TestConfig struct { + name string + server *httptest.Server + response string +} + +func FuzzGetManagedAccount(f *testing.F) { + + testConfig := TestConfig{ + name: "FuzzGetManagedAccount", + server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Mocking Response according to the endpoint path + switch r.URL.Path { + + case "/Auth/SignAppin": + _, err := w.Write([]byte(`{"UserId":1, "EmailAddress":"Felipe"}`)) + if err != nil { + f.Error("Test case Failed") + } + + case "/Auth/Signout": + _, err := w.Write([]byte(``)) + if err != nil { + f.Error("Test case Failed") + } + + case "/ManagedAccounts": + _, err := w.Write([]byte(`{"SystemId":1,"AccountId":10}`)) + if err != nil { + f.Error("Test case Failed") + } + + case "/Requests": + _, err := w.Write([]byte(`124`)) + if err != nil { + f.Error("Test case Failed") + } + + case "/Credentials/124": + _, err := w.Write([]byte(`"fake_credential"`)) + if err != nil { + f.Error("Test case Failed") + } + + case "/Requests/124/checkin": + _, err := w.Write([]byte(``)) + if err != nil { + f.Error("Test case Failed") + } + + default: + http.NotFound(w, r) + } + })), + response: "fake_credential", + } + + logger, _ := zap.NewDevelopment() + + // create a zap logger wrapper + zapLogger := logging.NewZapLogger(logger) + + httpClientObj, _ := utils.GetHttpClient(5, false, "", "", zapLogger) + + backoffDefinition := backoff.NewExponentialBackOff() + backoffDefinition.MaxElapsedTime = time.Second + + // instantiating authenticate obj, injecting httpClient object + var authenticate, _ = authentication.Authenticate(*httpClientObj, backoffDefinition, "https://fake.api.com:443/BeyondTrust/api/public/v3/", "fakeone_a654+9sdf7+8we4f", "fakeone_aasd156465sfdef", zapLogger, 300) + + apiUrl, _ := url.Parse(testConfig.server.URL + "/") + authenticate.ApiUrl = *apiUrl + + // instantiating managed account obj + manageAccountObj, _ := managed_accounts.NewManagedAccountObj(*authenticate, zapLogger) + + f.Add("fake1/account01", "/") + f.Add("fake2/account02", "#") + f.Add("fake3/account03", "*") + f.Add("fake4/account04", "-") + f.Add("fake5/account05", "/") + + f.Add("fake6/account06/test/test", "*//") + f.Add("fake6/account06", "_") + f.Add("fake6/account06/test/test", "*//***************") + + f.Fuzz(func(t *testing.T, a string, b string) { + + managedAccount, err := manageAccountObj.GetSecret(a, b) + if err != nil { + if !strings.Contains(err.Error(), "empty managed account list") { + t.Errorf("Unexpected error: %s", err.Error()) + } + } + + if err != nil && managedAccount != "" { + t.Errorf("Unexpected error: %s", err.Error()) + } + + }) + + // signing out + _ = authenticate.SignOut() + +} diff --git a/fuzzing/secrets/get_secrets_fuzz_test.go b/fuzzing/secrets/get_secrets_fuzz_test.go new file mode 100644 index 0000000..e58b1d9 --- /dev/null +++ b/fuzzing/secrets/get_secrets_fuzz_test.go @@ -0,0 +1,110 @@ +package fuzzing_secrets + +import ( + "net/http" + "net/http/httptest" + "net/url" + "testing" + "time" + + "github.com/BeyondTrust/go-client-library-passwordsafe/api/authentication" + "github.com/BeyondTrust/go-client-library-passwordsafe/api/logging" + "github.com/BeyondTrust/go-client-library-passwordsafe/api/secrets" + "github.com/BeyondTrust/go-client-library-passwordsafe/api/utils" + + "go.uber.org/zap" + + backoff "github.com/cenkalti/backoff/v4" +) + +type TestConfig struct { + name string + server *httptest.Server + response string +} + +func FuzzGetSecret(f *testing.F) { + + testConfig := TestConfig{ + name: "FuzzGetSecret", + server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Mocking Response according to the endpoint path + switch r.URL.Path { + + case "/Auth/SignAppin": + _, err := w.Write([]byte(`{"UserId":1, "EmailAddress":"Felipe"}`)) + if err != nil { + f.Error("Test case Failed") + } + + case "/Auth/Signout": + _, err := w.Write([]byte(``)) + if err != nil { + f.Error("Test case Failed") + } + + case "/secrets-safe/secrets": + _, err := w.Write([]byte(`[{"SecretType": "TEXT", "Password": "credential_in_sub_3_password","Id": "9152f5b6-07d6-4955-175a-08db047219ce","Title": "credential_in_sub_3"}]`)) + if err != nil { + f.Error("Test case Failed") + } + + case "/secrets-safe/secrets/9152f5b6-07d6-4955-175a-08db047219ce/file/download": + _, err := w.Write([]byte(`fake_password`)) + if err != nil { + f.Error("Test case Failed") + } + + default: + http.NotFound(w, r) + } + })), + response: "fake_password", + } + + logger, _ := zap.NewDevelopment() + + // create a zap logger wrapper + zapLogger := logging.NewZapLogger(logger) + + httpClientObj, _ := utils.GetHttpClient(5, false, "", "", zapLogger) + + backoffDefinition := backoff.NewExponentialBackOff() + backoffDefinition.MaxElapsedTime = time.Second + + // instantiating authenticate obj, injecting httpClient object + var authenticate, _ = authentication.Authenticate(*httpClientObj, backoffDefinition, "https://fake.api.com:443/BeyondTrust/api/public/v3/", "fakeone_a654+9sdf7+8we4f", "fakeone_aasd156465sfdef", zapLogger, 300) + + apiUrl, _ := url.Parse(testConfig.server.URL + "/") + authenticate.ApiUrl = *apiUrl + secretObj, _ := secrets.NewSecretObj(*authenticate, zapLogger, 4000) + + f.Add("fake/Test1", "/") + f.Add("fake/Test2", "*") + f.Add("fake/Test3", "-") + f.Add("fake/Test4", "+") + + f.Add("fake1/Test1/Test4", "//") + f.Add("fake1/Test2/Test5", "") + f.Add("fake1/Test1/Test4/Test5/Title", "-") + f.Add("fake1/Test4", "+") + + f.Fuzz(func(t *testing.T, a string, b string) { + + secret, err := secretObj.GetSecret(a, b) + if err != nil { + if err.Error() != "empty secret list" { + t.Errorf("Unexpected error: %s", err.Error()) + } + + if err != nil && secret != "" { + t.Errorf("Unexpected error: %s", err.Error()) + } + } + + }) + + // signing out + _ = authenticate.SignOut() + +}