diff --git a/cmd/scan.go b/cmd/scan.go index 5f3147c..d03e734 100644 --- a/cmd/scan.go +++ b/cmd/scan.go @@ -16,6 +16,7 @@ var ( begin uint8 end uint8 subnets []string + disableProbing bool ) var scanCmd = &cobra.Command{ @@ -44,7 +45,7 @@ var scanCmd = &cobra.Command{ if threads <= 0 { threads = mathutil.Clamp(len(hostsToScan), 1, 255) } - probeStates := magellan.ScanForAssets(hostsToScan, portsToScan, threads, timeout) + probeStates := magellan.ScanForAssets(hostsToScan, portsToScan, threads, timeout, disableProbing) for _, r := range probeStates { fmt.Printf("%s:%d (%s)\n", r.Host, r.Port, r.Protocol) } @@ -60,11 +61,12 @@ var scanCmd = &cobra.Command{ } func init() { - scanCmd.PersistentFlags().StringSliceVar(&hosts, "host", []string{}, "set additional hosts to scan") - scanCmd.PersistentFlags().IntSliceVar(&ports, "port", []int{}, "set the ports to scan") + scanCmd.Flags().StringSliceVar(&hosts, "host", []string{}, "set additional hosts to scan") + scanCmd.Flags().IntSliceVar(&ports, "port", []int{}, "set the ports to scan") scanCmd.Flags().Uint8Var(&begin, "begin", 0, "set the starting point for range of IP addresses") scanCmd.Flags().Uint8Var(&end, "end", 255, "set the ending point for range of IP addresses") scanCmd.Flags().StringSliceVar(&subnets, "subnet", []string{}, "set additional subnets") + scanCmd.Flags().BoolVar(&disableProbing, "disable-probing", false, "disable probing scanned results for BMC nodes") rootCmd.AddCommand(scanCmd) } diff --git a/internal/collect.go b/internal/collect.go index 3c6941c..ba95970 100644 --- a/internal/collect.go +++ b/internal/collect.go @@ -33,12 +33,6 @@ const ( HTTPS_PORT = 443 ) -type BMCProbeResult struct { - Host string `json:"host"` - Port int `json:"port"` - Protocol string `json:"protocol"` - State bool `json:"state"` -} // NOTE: ...params were getting too long... type QueryParams struct { @@ -108,7 +102,7 @@ func NewClient(l *log.Logger, q *QueryParams) (*bmclib.Client, error) { return client, nil } -func CollectInfo(probeStates *[]BMCProbeResult, l *log.Logger, q *QueryParams) error { +func CollectInfo(probeStates *[]ScannedResult, l *log.Logger, q *QueryParams) error { // check for available probe states if probeStates == nil { return fmt.Errorf("no probe states found") @@ -126,7 +120,7 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *log.Logger, q *QueryParams) e found := make([]string, 0, len(*probeStates)) done := make(chan struct{}, q.Threads+1) - chanProbeState := make(chan BMCProbeResult, q.Threads+1) + chanProbeState := make(chan ScannedResult, q.Threads+1) // generate custom xnames for bmcs node := xnames.Node{ @@ -630,9 +624,10 @@ func connectGofish(q *QueryParams) (*gofish.APIClient, error) { config := makeGofishConfig(q) c, err := gofish.Connect(config) if err != nil { - return nil, err + + return nil, fmt.Errorf("could not connect to redfish endpoint: %v", err) } - if c.Service != nil { + if c != nil { c.Service.ProtocolFeaturesSupported = gofish.ProtocolFeaturesSupported{ ExpandQuery: gofish.Expand{ ExpandAll: true, diff --git a/internal/db/sqlite/sqlite.go b/internal/db/sqlite/sqlite.go index 0122b0f..586a73d 100644 --- a/internal/db/sqlite/sqlite.go +++ b/internal/db/sqlite/sqlite.go @@ -78,13 +78,13 @@ func DeleteProbeResults(path string, results *[]magellan.BMCProbeResult) error { return nil } -func GetProbeResults(path string) ([]magellan.BMCProbeResult, error) { +func GetProbeResults(path string) ([]magellan.ScannedResult, error) { db, err := sqlx.Open("sqlite3", path) if err != nil { return nil, fmt.Errorf("could not open database: %v", err) } - results := []magellan.BMCProbeResult{} + results := []magellan.ScannedResult{} err = db.Select(&results, "SELECT * FROM magellan_scanned_ports ORDER BY host ASC, port ASC;") if err != nil { return nil, fmt.Errorf("could not retrieve probes: %v", err) diff --git a/internal/scan.go b/internal/scan.go index 330a019..beee775 100644 --- a/internal/scan.go +++ b/internal/scan.go @@ -3,14 +3,24 @@ package magellan import ( "fmt" "net" + "net/http" "sync" "time" + + "github.com/bikeshack/magellan/internal/util" ) -func rawConnect(host string, ports []int, timeout int, keepOpenOnly bool) []BMCProbeResult { - results := []BMCProbeResult{} +type ScannedResult struct { + Host string `json:"host"` + Port int `json:"port"` + Protocol string `json:"protocol"` + State bool `json:"state"` +} + +func rawConnect(host string, ports []int, timeout int, keepOpenOnly bool) []ScannedResult { + results := []ScannedResult{} for _, p := range ports { - result := BMCProbeResult{ + result := ScannedResult{ Host: host, Port: p, Protocol: "tcp", @@ -50,8 +60,8 @@ func GenerateHosts(subnet string, begin uint8, end uint8) []string { return hosts } -func ScanForAssets(hosts []string, ports []int, threads int, timeout int) []BMCProbeResult { - results := make([]BMCProbeResult, 0, len(hosts)) +func ScanForAssets(hosts []string, ports []int, threads int, timeout int, disableProbing bool) []ScannedResult { + results := make([]ScannedResult, 0, len(hosts)) done := make(chan struct{}, threads+1) chanHost := make(chan string, threads+1) // chanPort := make(chan int, threads+1) @@ -66,8 +76,25 @@ func ScanForAssets(hosts []string, ports []int, threads int, timeout int) []BMCP wg.Done() return } - s := rawConnect(host, ports, timeout, true) - results = append(results, s...) + scannedResults := rawConnect(host, ports, timeout, true) + if !disableProbing { + probeResults := []ScannedResult{} + for _, result := range scannedResults { + url := fmt.Sprintf("https://%s:%d/redfish/v1/", result.Host, result.Port) + res, _, err := util.MakeRequest(url, "GET", nil, nil) + if err != nil || res == nil { + continue + } else if res.StatusCode != http.StatusOK { + continue + } else { + probeResults = append(probeResults, result) + } + } + results = append(results, probeResults...) + } else { + results = append(results, scannedResults...) + } + } }() }