Files
keyhunter/cmd/providers.go
salvacybersec 9da0b68129 feat(01-05): add CLI root command, config package, output table, and settings helpers
- 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
2026-04-05 12:26:36 +03:00

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)
}