package sources import ( "context" "net/http" "net/http/httptest" "testing" "time" "github.com/salvacybersec/keyhunter/pkg/providers" "github.com/salvacybersec/keyhunter/pkg/recon" ) func doSpacesTestServer() *httptest.Server { mux := http.NewServeMux() // Only testprov-keys bucket in nyc3 region is publicly listable. mux.HandleFunc("/testprov-keys/nyc3/", func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodHead { w.WriteHeader(http.StatusOK) return } w.Header().Set("Content-Type", "application/xml") _, _ = w.Write([]byte(` .env.production app.conf logo.svg `)) }) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) }) return httptest.NewServer(mux) } func TestDOSpaces_Sweep(t *testing.T) { srv := doSpacesTestServer() defer srv.Close() src := &DOSpacesScanner{ Registry: cloudTestRegistry(), BaseURL: srv.URL + "/%s/%s/", client: NewClient(), } out := make(chan recon.Finding, 64) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := src.Sweep(ctx, "", out); err != nil { t.Fatalf("Sweep error: %v", err) } close(out) var findings []recon.Finding for f := range out { findings = append(findings, f) } // .env.production and app.conf match; logo.svg does not. if len(findings) != 2 { t.Fatalf("expected 2 findings, got %d: %+v", len(findings), findings) } for _, f := range findings { if f.SourceType != "recon:spaces" { t.Errorf("unexpected SourceType: %s", f.SourceType) } if f.Confidence != "medium" { t.Errorf("unexpected Confidence: %s", f.Confidence) } } } func TestDOSpaces_EmptyRegistry(t *testing.T) { src := &DOSpacesScanner{ Registry: providers.NewRegistryFromProviders(nil), Limiters: recon.NewLimiterRegistry(), client: NewClient(), } out := make(chan recon.Finding, 4) if err := src.Sweep(context.Background(), "", out); err != nil { t.Fatalf("Sweep error: %v", err) } close(out) if len(out) != 0 { t.Fatal("expected 0 findings") } } func TestDOSpaces_CtxCancelled(t *testing.T) { srv := doSpacesTestServer() defer srv.Close() src := &DOSpacesScanner{ Registry: cloudTestRegistry(), BaseURL: srv.URL + "/%s/%s/", client: NewClient(), } ctx, cancel := context.WithCancel(context.Background()) cancel() out := make(chan recon.Finding, 4) if err := src.Sweep(ctx, "", out); err == nil { t.Fatal("expected ctx error") } } func TestDOSpaces_EnabledAndMeta(t *testing.T) { d := &DOSpacesScanner{} if d.Name() != "spaces" { t.Fatalf("unexpected name: %s", d.Name()) } if !d.Enabled(recon.Config{}) { t.Fatal("expected Enabled=true") } if d.RespectsRobots() { t.Fatal("expected RespectsRobots=false") } if d.Burst() != 3 { t.Fatal("expected Burst=3") } }