- cmd/root.go: Cobra root with all 11 subcommands, viper config loading - cmd/stubs.go: 8 stub commands for future phases (verify, import, recon, keys, serve, dorks, hook, schedule) - cmd/scan.go: scan command wiring engine + storage + output with per-installation salt - cmd/providers.go: providers list/info/stats subcommands - cmd/config.go: config init/set/get subcommands - pkg/config/config.go: Config struct with Load() and defaults - pkg/output/table.go: lipgloss terminal table for PrintFindings - pkg/storage/settings.go: GetSetting/SetSetting for settings table CRUD
99 lines
2.6 KiB
Go
99 lines
2.6 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/charmbracelet/lipgloss"
|
|
"github.com/spf13/cobra"
|
|
"github.com/salvacybersec/keyhunter/pkg/providers"
|
|
)
|
|
|
|
var providersCmd = &cobra.Command{
|
|
Use: "providers",
|
|
Short: "Manage and inspect provider definitions",
|
|
}
|
|
|
|
var providersListCmd = &cobra.Command{
|
|
Use: "list",
|
|
Short: "List all loaded provider definitions",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
reg, err := providers.NewRegistry()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
bold := lipgloss.NewStyle().Bold(true)
|
|
fmt.Fprintf(os.Stdout, "%-20s %-6s %-8s %s\n",
|
|
bold.Render("NAME"), bold.Render("TIER"), bold.Render("PATTERNS"), bold.Render("KEYWORDS"))
|
|
fmt.Println(strings.Repeat("-", 70))
|
|
for _, p := range reg.List() {
|
|
fmt.Fprintf(os.Stdout, "%-20s %-6d %-8d %s\n",
|
|
p.Name, p.Tier, len(p.Patterns), strings.Join(p.Keywords, ", "))
|
|
}
|
|
stats := reg.Stats()
|
|
fmt.Printf("\nTotal: %d providers\n", stats.Total)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var providersInfoCmd = &cobra.Command{
|
|
Use: "info <name>",
|
|
Short: "Show detailed info for a provider",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
reg, err := providers.NewRegistry()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p, ok := reg.Get(args[0])
|
|
if !ok {
|
|
return fmt.Errorf("provider %q not found", args[0])
|
|
}
|
|
fmt.Printf("Name: %s\n", p.Name)
|
|
fmt.Printf("Display Name: %s\n", p.DisplayName)
|
|
fmt.Printf("Tier: %d\n", p.Tier)
|
|
fmt.Printf("Last Verified: %s\n", p.LastVerified)
|
|
fmt.Printf("Keywords: %s\n", strings.Join(p.Keywords, ", "))
|
|
fmt.Printf("Patterns: %d\n", len(p.Patterns))
|
|
for i, pat := range p.Patterns {
|
|
fmt.Printf(" [%d] regex=%s confidence=%s entropy_min=%.1f\n",
|
|
i+1, pat.Regex, pat.Confidence, pat.EntropyMin)
|
|
}
|
|
if p.Verify.URL != "" {
|
|
fmt.Printf("Verify URL: %s %s\n", p.Verify.Method, p.Verify.URL)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var providersStatsCmd = &cobra.Command{
|
|
Use: "stats",
|
|
Short: "Show provider statistics",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
reg, err := providers.NewRegistry()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
stats := reg.Stats()
|
|
fmt.Printf("Total providers: %d\n", stats.Total)
|
|
fmt.Printf("By tier:\n")
|
|
for tier := 1; tier <= 9; tier++ {
|
|
if count := stats.ByTier[tier]; count > 0 {
|
|
fmt.Printf(" Tier %d: %d\n", tier, count)
|
|
}
|
|
}
|
|
fmt.Printf("By confidence:\n")
|
|
for conf, count := range stats.ByConfidence {
|
|
fmt.Printf(" %s: %d\n", conf, count)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
providersCmd.AddCommand(providersListCmd)
|
|
providersCmd.AddCommand(providersInfoCmd)
|
|
providersCmd.AddCommand(providersStatsCmd)
|
|
}
|