From 8d75460c41a0bc7bacd2582ca838ab5558509b0e Mon Sep 17 00:00:00 2001 From: Dogan Can Bakir <65292895+dogancanbakir@users.noreply.github.com> Date: Tue, 30 May 2023 22:32:33 +0300 Subject: [PATCH] Test sources require an API key (#852) * test providers require key * remove redundant tests * ignore failing(often) test * added crtsh to ignore list --------- Co-authored-by: sandeep <8293321+ehsandeep@users.noreply.github.com> --- .github/workflows/build-test.yml | 34 ++++++-- v2/cmd/integration-test/integration-test.go | 86 --------------------- v2/cmd/integration-test/run.sh | 19 ----- v2/cmd/integration-test/source-test.go | 33 -------- v2/pkg/passive/sources_w_auth_test.go | 61 +++++++++++++++ v2/pkg/passive/sources_wo_auth_test.go | 13 ++-- 6 files changed, 96 insertions(+), 150 deletions(-) delete mode 100644 v2/cmd/integration-test/integration-test.go delete mode 100755 v2/cmd/integration-test/run.sh delete mode 100644 v2/cmd/integration-test/source-test.go create mode 100644 v2/pkg/passive/sources_w_auth_test.go diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index cea8627ed..1edb0610a 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -28,19 +28,39 @@ jobs: working-directory: v2/ - name: Run tests + env: + BEVIGIL_API_KEY: ${{secrets.BEVIGIL_API_KEY}} + BINARYEDGE_API_KEY: ${{secrets.BINARYEDGE_API_KEY}} + BUFFEROVER_API_KEY: ${{secrets.BUFFEROVER_API_KEY}} + C99_API_KEY: ${{secrets.C99_API_KEY}} + CENSYS_API_KEY: ${{secrets.CENSYS_API_KEY}} + CERTSPOTTER_API_KEY: ${{secrets.CERTSPOTTER_API_KEY}} + CHAOS_API_KEY: ${{secrets.CHAOS_API_KEY}} + CHINAZ_API_KEY: ${{secrets.CHINAZ_API_KEY}} + DNSDB_API_KEY: ${{secrets.DNSDB_API_KEY}} + DNSREPO_API_KEY: ${{secrets.DNSREPO_API_KEY}} + FOFA_API_KEY: ${{secrets.FOFA_API_KEY}} + FULLHUNT_API_KEY: ${{secrets.FULLHUNT_API_KEY}} + GITHUB_API_KEY: ${{secrets.GITHUB_API_KEY}} + HUNTER_API_KEY: ${{secrets.HUNTER_API_KEY}} + INTELX_API_KEY: ${{secrets.INTELX_API_KEY}} + LEAKIX_API_KEY: ${{secrets.LEAKIX_API_KEY}} + PASSIVETOTAL_API_KEY: ${{secrets.PASSIVETOTAL_API_KEY}} + QUAKE_API_KEY: ${{secrets.QUAKE_API_KEY}} + ROBTEX_API_KEY: ${{secrets.ROBTEX_API_KEY}} + SECURITYTRAILS_API_KEY: ${{secrets.SECURITYTRAILS_API_KEY}} + SHODAN_API_KEY: ${{secrets.SHODAN_API_KEY}} + THREATBOOK_API_KEY: ${{secrets.THREATBOOK_API_KEY}} + VIRUSTOTAL_API_KEY: ${{secrets.VIRUSTOTAL_API_KEY}} + WHOISXMLAPI_API_KEY: ${{secrets.WHOISXMLAPI_API_KEY}} + ZOOMEYE_API_KEY: ${{secrets.ZOOMEYE_API_KEY}} + ZOOMEYEAPI_API_KEY: ${{secrets.ZOOMEYEAPI_API_KEY}} uses: nick-invision/retry@v2 with: timeout_seconds: 360 max_attempts: 3 command: cd v2; go test ./... -v - - name: Integration Tests - env: - GH_ACTION: true - DNSREPO_API_KEY: ${{secrets.DNSREPO_API}} - run: bash run.sh - working-directory: v2/cmd/integration-test/ - - name: Race Condition Tests run: go build -race ./... working-directory: v2/ \ No newline at end of file diff --git a/v2/cmd/integration-test/integration-test.go b/v2/cmd/integration-test/integration-test.go deleted file mode 100644 index 608eceaf2..000000000 --- a/v2/cmd/integration-test/integration-test.go +++ /dev/null @@ -1,86 +0,0 @@ -package main - -import ( - "fmt" - "os" - "strings" - - "github.com/logrusorgru/aurora" - - "github.com/projectdiscovery/subfinder/v2/pkg/testutils" -) - -var ( - debug = os.Getenv("DEBUG") == "true" - githubAction = os.Getenv("GH_ACTION") == "true" - customTests = os.Getenv("TESTS") - - success = aurora.Green("[✓]").String() - failed = aurora.Red("[✘]").String() - - sourceTests = map[string]testutils.TestCase{ - "dnsrepo": dnsrepoTestcases{}, - } -) - -func main() { - failedTestCases := runTests(toMap(toSlice(customTests))) - - if len(failedTestCases) > 0 { - if githubAction { - debug = true - fmt.Println("::group::Failed integration tests in debug mode") - _ = runTests(failedTestCases) - fmt.Println("::endgroup::") - } - os.Exit(1) - } -} - -func runTests(customTestCases map[string]struct{}) map[string]struct{} { - failedTestCases := map[string]struct{}{} - - for source, testCase := range sourceTests { - if len(customTestCases) == 0 { - fmt.Printf("Running test cases for %q source\n", aurora.Blue(source)) - } - if err, failedTemplatePath := execute(source, testCase); err != nil { - failedTestCases[failedTemplatePath] = struct{}{} - } - } - return failedTestCases -} - -func execute(source string, testCase testutils.TestCase) (error, string) { - if err := testCase.Execute(); err != nil { - _, _ = fmt.Fprintf(os.Stderr, "%s Test \"%s\" failed: %s\n", failed, source, err) - return err, source - } - - fmt.Printf("%s Test \"%s\" passed!\n", success, source) - return nil, "" -} - -func expectResultsGreaterThanCount(results []string, expectedNumber int) error { - if len(results) > expectedNumber { - return nil - } - return fmt.Errorf("incorrect number of results: expected a result greater than %d,but got %d", expectedNumber, len(results)) -} -func toSlice(value string) []string { - if strings.TrimSpace(value) == "" { - return []string{} - } - - return strings.Split(value, ",") -} - -func toMap(slice []string) map[string]struct{} { - result := make(map[string]struct{}, len(slice)) - for _, value := range slice { - if _, ok := result[value]; !ok { - result[value] = struct{}{} - } - } - return result -} diff --git a/v2/cmd/integration-test/run.sh b/v2/cmd/integration-test/run.sh deleted file mode 100755 index 2d826de24..000000000 --- a/v2/cmd/integration-test/run.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -echo "::task~> Clean up & Build binaries files" -rm integration-test subfinder 2>/dev/null -cd ../subfinder -go build -mv subfinder ../integration-test/subfinder -cd ../integration-test -go build -echo "::done::" -echo "::task~> Run integration test" -./integration-test -echo "::done::" -if [ $? -eq 0 ] -then - exit 0 -else - exit 1 -fi diff --git a/v2/cmd/integration-test/source-test.go b/v2/cmd/integration-test/source-test.go deleted file mode 100644 index 3b5e4ca0a..000000000 --- a/v2/cmd/integration-test/source-test.go +++ /dev/null @@ -1,33 +0,0 @@ -package main - -import ( - "errors" - "fmt" - "os" - - "github.com/projectdiscovery/subfinder/v2/pkg/testutils" -) - -type dnsrepoTestcases struct{} - -func (h dnsrepoTestcases) Execute() error { - token := os.Getenv("DNSREPO_API_KEY") - if token == "" { - return errors.New("missing dns repo api key") - } - dnsToken := fmt.Sprintf(`dnsrepo: [%s]`, token) - file, err := os.CreateTemp("", "provider.yaml") - if err != nil { - return err - } - defer os.RemoveAll(file.Name()) - _, err = file.WriteString(dnsToken) - if err != nil { - return err - } - results, err := testutils.RunSubfinderAndGetResults(debug, "hackerone.com", "-s", "dnsrepo", "-provider-config", file.Name()) - if err != nil { - return err - } - return expectResultsGreaterThanCount(results, 0) -} diff --git a/v2/pkg/passive/sources_w_auth_test.go b/v2/pkg/passive/sources_w_auth_test.go new file mode 100644 index 000000000..452bde6f5 --- /dev/null +++ b/v2/pkg/passive/sources_w_auth_test.go @@ -0,0 +1,61 @@ +package passive + +import ( + "context" + "fmt" + "os" + "reflect" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/gologger/levels" + "github.com/projectdiscovery/subfinder/v2/pkg/subscraping" +) + +func TestSourcesWithKeys(t *testing.T) { + domain := "hackerone.com" + timeout := 60 + + gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug) + + ctx := context.Background() + session, err := subscraping.NewSession(domain, "", 0, timeout) + assert.Nil(t, err) + + var expected = subscraping.Result{Type: subscraping.Subdomain, Value: domain, Error: nil} + + for _, source := range AllSources { + if !source.NeedsKey() { + continue + } + + apiKey := os.Getenv(fmt.Sprintf("%s_API_KEY", strings.ToUpper(source.Name()))) + if apiKey == "" { + fmt.Printf("Skipping %s as no API key is provided\n", source.Name()) + continue + } + source.AddApiKeys([]string{apiKey}) + + t.Run(source.Name(), func(t *testing.T) { + var results []subscraping.Result + + for result := range source.Run(ctx, domain, session) { + results = append(results, result) + + assert.Equal(t, source.Name(), result.Source, "wrong source name") + + if result.Type != subscraping.Error { + assert.True(t, strings.HasSuffix(strings.ToLower(result.Value), strings.ToLower(expected.Value)), + fmt.Sprintf("result(%s) is not subdomain of %s", strings.ToLower(result.Value), expected.Value)) + } else { + assert.Equal(t, reflect.TypeOf(expected.Error), reflect.TypeOf(result.Error), fmt.Sprintf("%s: %s", result.Source, result.Error)) + } + } + + assert.GreaterOrEqual(t, len(results), 1, fmt.Sprintf("No result found for %s", source.Name())) + }) + } +} diff --git a/v2/pkg/passive/sources_wo_auth_test.go b/v2/pkg/passive/sources_wo_auth_test.go index 14f135b14..d603ae802 100644 --- a/v2/pkg/passive/sources_wo_auth_test.go +++ b/v2/pkg/passive/sources_wo_auth_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "golang.org/x/exp/slices" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/gologger/levels" @@ -15,6 +16,12 @@ import ( ) func TestSourcesWithoutKeys(t *testing.T) { + ignoredSources := []string{ + "commoncrawl", // commoncrawl is under resourced and will likely time-out so step over it for this test https://groups.google.com/u/2/g/common-crawl/c/3QmQjFA_3y4/m/vTbhGqIBBQAJ + "riddler", // Fails with 403: There might be too much traffic or a configuration error + "crtsh", // Fails in GH Action (possibly IP-based ban) causing a timeout. + } + domain := "hackerone.com" timeout := 60 @@ -27,14 +34,10 @@ func TestSourcesWithoutKeys(t *testing.T) { var expected = subscraping.Result{Type: subscraping.Subdomain, Value: domain, Error: nil} for _, source := range AllSources { - if source.NeedsKey() { + if source.NeedsKey() || slices.Contains(ignoredSources, source.Name()) { continue } - if source.Name() == "commoncrawl" { - continue // commoncrawl is under resourced and will likely time-out so step over it for this test https://groups.google.com/u/2/g/common-crawl/c/3QmQjFA_3y4/m/vTbhGqIBBQAJ - } - t.Run(source.Name(), func(t *testing.T) { var results []subscraping.Result