mirror of
https://github.com/davidallendj/magellan.git
synced 2025-12-20 03:27:03 -07:00
Initial commit
This commit is contained in:
commit
b6fe201f66
9 changed files with 789 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
magellan
|
||||||
52
README.md
Normal file
52
README.md
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Magellan
|
||||||
|
|
||||||
|
Magellan is a small tool designed to collect BMC information and load the data
|
||||||
|
into `hms-smd`. It is able to probe hosts for specific open ports using the `dora`
|
||||||
|
API or it's own simplier, built-in scanner and query BMC information via `bmclib`.
|
||||||
|
Once the data is received, it is then stored into `hms-smd` using its API.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To build the project, run the following:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod tidy && go bulid
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Magellan can be used to load inventory components using redfish or IMPI interfaces.
|
||||||
|
It can scan subnets or specific hosts to find...
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./magellan --help
|
||||||
|
Usage of ./magellan:
|
||||||
|
--cert-pool string path to an file containing x509 CAs. An empty string uses the system CAs. Only takes effect when --secure-tls=true
|
||||||
|
--driver strings set the BMC driver to use (default [redfish])
|
||||||
|
--host strings set additional hosts
|
||||||
|
--pass string set the BMC pass (default "root_password")
|
||||||
|
--port ints set the ports to scan
|
||||||
|
--secure-tls enable secure TLS
|
||||||
|
--subnet strings set additional subnets (default [127.0.0.0])
|
||||||
|
--threads int set the number of threads (default -1)
|
||||||
|
--timeout int set the timeout (default 1)
|
||||||
|
--user string set the BMC user (default "root")
|
||||||
|
|
||||||
|
# example usage
|
||||||
|
magellan \
|
||||||
|
--subnet 127.0.0.0 \
|
||||||
|
--host 127.0.0.1 \
|
||||||
|
--port 5000 \
|
||||||
|
--timeout 10 \
|
||||||
|
--user root \
|
||||||
|
--pass root_password \
|
||||||
|
--threads 255 \
|
||||||
|
```
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
List of things left to fix or do...
|
||||||
|
|
||||||
|
* [ ] Switch to internal scanner if `dora` fails
|
||||||
|
* [ ] Test using different `bmclib` supported drivers (mainly 'redfish')
|
||||||
|
* [ ] Confirm loading different components into `hms-smd`
|
||||||
74
api/dora/dora.go
Normal file
74
api/dora/dora.go
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
package dora
|
||||||
|
|
||||||
|
import (
|
||||||
|
"davidallendj/magellan/api"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Host = "http://localhost"
|
||||||
|
DbType = "sqlite3"
|
||||||
|
DbPath = "../data/assets.db"
|
||||||
|
BaseEndpoint = "/v1"
|
||||||
|
Port = 8000
|
||||||
|
)
|
||||||
|
|
||||||
|
type ScannedResult struct {
|
||||||
|
id string
|
||||||
|
site any
|
||||||
|
cidr string
|
||||||
|
ip string
|
||||||
|
port int
|
||||||
|
protocol string
|
||||||
|
scanner string
|
||||||
|
state string
|
||||||
|
updated string
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeEndpointUrl(endpoint string) string {
|
||||||
|
return Host + ":" + fmt.Sprint(Port) + BaseEndpoint + endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan for BMC assets uing dora scanner
|
||||||
|
func ScanForAssets() error {
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query dora API to get scanned ports
|
||||||
|
func QueryScannedPorts() error {
|
||||||
|
// Perform scan and collect from dora server
|
||||||
|
url := makeEndpointUrl("/scanned_ports")
|
||||||
|
_, body, err := api.MakeRequest(url, "GET", nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not discover assets: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get data from JSON
|
||||||
|
var res map[string]any
|
||||||
|
if err := json.Unmarshal(body, &res); err != nil {
|
||||||
|
return fmt.Errorf("could not unmarshal response body: %v", err)
|
||||||
|
}
|
||||||
|
data := res["data"]
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads scanned ports directly from DB
|
||||||
|
func LoadScannedPortsFromDB(dbPath string, dbType string) {
|
||||||
|
db, _ := sqlx.Open(dbType, dbPath)
|
||||||
|
sql := `SELECT * FROM scanned_port WHERE state='open'`
|
||||||
|
rows, _ := db.Query(sql)
|
||||||
|
for rows.Next() {
|
||||||
|
var r ScannedResult
|
||||||
|
rows.Scan(
|
||||||
|
&r.id, &r.site, &r.cidr, &r.ip, &r.port, &r.protocol, &r.scanner,
|
||||||
|
&r.state, &r.updated,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
57
api/smd/smd.go
Normal file
57
api/smd/smd.go
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
package smd
|
||||||
|
|
||||||
|
// See ref for API docs:
|
||||||
|
// https://github.com/Cray-HPE/hms-smd/blob/master/docs/examples.adoc
|
||||||
|
// https://github.com/alexlovelltroy/hms-smd
|
||||||
|
import (
|
||||||
|
"davidallendj/magellan/api"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Host = "http://localhost"
|
||||||
|
BaseEndpoint = "/hsm/v2"
|
||||||
|
Port = 27779
|
||||||
|
)
|
||||||
|
|
||||||
|
func makeEndpointUrl(endpoint string) string {
|
||||||
|
return Host + ":" + fmt.Sprint(Port) + BaseEndpoint + endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRedfishEndpoints() error {
|
||||||
|
url := makeEndpointUrl("/Inventory/RedfishEndpoints")
|
||||||
|
_, body, err := api.MakeRequest(url, "GET", nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not get endpoint: %v", err)
|
||||||
|
}
|
||||||
|
// fmt.Println(res)
|
||||||
|
fmt.Println(string(body))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetComponentEndpoint(xname string) error {
|
||||||
|
url := makeEndpointUrl("/Inventory/ComponentsEndpoints/" + xname)
|
||||||
|
res, body, err := api.MakeRequest(url, "GET", nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not get endpoint: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println(res)
|
||||||
|
fmt.Println(string(body))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddRedfishEndpoint(inventory []byte) error {
|
||||||
|
if inventory == nil {
|
||||||
|
return fmt.Errorf("could not add redfish endpoint: no data found")
|
||||||
|
}
|
||||||
|
// Add redfish endpoint via POST `/hsm/v2/Inventory/RedfishEndpoints` endpoint
|
||||||
|
url := makeEndpointUrl("/Inventory/RedfishEndpoints")
|
||||||
|
res, body, _ := api.MakeRequest(url, "POST", inventory)
|
||||||
|
fmt.Println("res: ", res)
|
||||||
|
fmt.Println("body: ", string(body))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateRedfishEndpoint() {
|
||||||
|
// Update redfish endpoint via PUT `/hsm/v2/Inventory/RedfishEndpoints` endpoint
|
||||||
|
}
|
||||||
25
api/util.go
Normal file
25
api/util.go
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func MakeRequest(url string, httpMethod string, body []byte) (*http.Response, []byte, error) {
|
||||||
|
// url := getSmdEndpointUrl(endpoint)
|
||||||
|
req, _ := http.NewRequest(httpMethod, url, bytes.NewBuffer(body))
|
||||||
|
req.Header.Add("User-Agent", "magellan")
|
||||||
|
res, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("could not make request: %v", err)
|
||||||
|
}
|
||||||
|
b, err := io.ReadAll(res.Body)
|
||||||
|
res.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("could not read response body: %v", err)
|
||||||
|
}
|
||||||
|
return res, b, err
|
||||||
|
}
|
||||||
33
go.mod
Normal file
33
go.mod
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
module davidallendj/magellan
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
|
replace github.com/bmc-toolbox/dora => ../../dora
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/bmc-toolbox/bmclib v0.5.7
|
||||||
|
github.com/bombsimon/logrusr/v2 v2.0.1
|
||||||
|
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548
|
||||||
|
github.com/go-logr/logr v1.2.4
|
||||||
|
github.com/jacobweinstock/registrar v0.4.7
|
||||||
|
github.com/jmoiron/sqlx v1.3.5
|
||||||
|
github.com/sirupsen/logrus v1.9.3
|
||||||
|
github.com/spf13/pflag v1.0.5
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/bmc-toolbox/common v0.0.0-20230717121556-5eb9915a8a5a // indirect
|
||||||
|
github.com/go-playground/locales v0.13.0 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
github.com/stmcginnis/gofish v0.14.0 // indirect
|
||||||
|
github.com/stretchr/testify v1.8.3 // indirect
|
||||||
|
golang.org/x/crypto v0.12.0 // indirect
|
||||||
|
golang.org/x/net v0.14.0 // indirect
|
||||||
|
golang.org/x/sys v0.11.0 // indirect
|
||||||
|
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
|
||||||
|
)
|
||||||
96
go.sum
Normal file
96
go.sum
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
github.com/bmc-toolbox/bmclib v0.5.7 h1:v3CqOJCMUuH+kA+xi7CdY5EuzUhMH9gsBkYTQMYlbog=
|
||||||
|
github.com/bmc-toolbox/bmclib v0.5.7/go.mod h1:jSCb2/o2bZhTTg3IgShckCfFxkX4yqQC065tuYh2pKk=
|
||||||
|
github.com/bmc-toolbox/common v0.0.0-20230717121556-5eb9915a8a5a h1:SjtoU9dE3bYfYnPXODCunMztjoDgnE3DVJCPLBqwz6Q=
|
||||||
|
github.com/bmc-toolbox/common v0.0.0-20230717121556-5eb9915a8a5a/go.mod h1:SY//n1PJjZfbFbmAsB6GvEKbc7UXz3d30s3kWxfJQ/c=
|
||||||
|
github.com/bombsimon/logrusr/v2 v2.0.1 h1:1VgxVNQMCvjirZIYaT9JYn6sAVGVEcNtRE0y4mvaOAM=
|
||||||
|
github.com/bombsimon/logrusr/v2 v2.0.1/go.mod h1:ByVAX+vHdLGAfdroiMg6q0zgq2FODY2lc5YJvzmOJio=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=
|
||||||
|
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
|
github.com/go-logr/logr v1.0.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||||
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||||
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
|
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||||
|
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||||
|
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||||
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||||
|
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
|
github.com/jacobweinstock/registrar v0.4.7 h1:s4dOExccgD+Pc7rJC+f3Mc3D+NXHcXUaOibtcEsPxOc=
|
||||||
|
github.com/jacobweinstock/registrar v0.4.7/go.mod h1:PWmkdGFG5/ZdCqgMo7pvB3pXABOLHc5l8oQ0sgmBNDU=
|
||||||
|
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
||||||
|
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
|
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||||
|
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||||
|
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||||
|
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||||
|
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
||||||
|
github.com/stmcginnis/gofish v0.14.0 h1:geECNAiG33JDB2x2xDkerpOOuXFqxp5YP3EFE3vd5iM=
|
||||||
|
github.com/stmcginnis/gofish v0.14.0/go.mod h1:BLDSFTp8pDlf/xDbLZa+F7f7eW0E/CHCboggsu8CznI=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||||
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||||
|
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||||
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
|
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||||
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
||||||
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||||
|
gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
|
||||||
|
gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||||
|
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
338
internal/magellan.go
Normal file
338
internal/magellan.go
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
package magellan
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
bmclib "github.com/bmc-toolbox/bmclib"
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
"github.com/jacobweinstock/registrar"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IPMI_PORT = 623
|
||||||
|
SSH_PORT = 22
|
||||||
|
TLS_PORT = 443
|
||||||
|
REDFISH_PORT = 5000
|
||||||
|
)
|
||||||
|
|
||||||
|
type bmcProbeResult struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
Protocol string
|
||||||
|
State bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: ...params were getting too long...
|
||||||
|
type QueryParams struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
User string
|
||||||
|
Pass string
|
||||||
|
Drivers []string
|
||||||
|
Timeout int
|
||||||
|
WithSecureTLS bool
|
||||||
|
CertPoolFile string
|
||||||
|
}
|
||||||
|
|
||||||
|
func rawConnect(host string, ports []int, timeout int, keepOpenOnly bool) []bmcProbeResult {
|
||||||
|
results := []bmcProbeResult{}
|
||||||
|
for _, p := range ports {
|
||||||
|
result := bmcProbeResult{
|
||||||
|
Host: host,
|
||||||
|
Port: p,
|
||||||
|
Protocol: "tcp",
|
||||||
|
State: false,
|
||||||
|
}
|
||||||
|
t := time.Second * time.Duration(timeout)
|
||||||
|
port := fmt.Sprint(p)
|
||||||
|
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), t)
|
||||||
|
if err != nil {
|
||||||
|
result.State = false
|
||||||
|
// fmt.Println("Connecting error:", err)
|
||||||
|
}
|
||||||
|
if conn != nil {
|
||||||
|
result.State = true
|
||||||
|
defer conn.Close()
|
||||||
|
// fmt.Println("Opened", net.JoinHostPort(host, port))
|
||||||
|
}
|
||||||
|
if keepOpenOnly {
|
||||||
|
if result.State {
|
||||||
|
results = append(results, result)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
results = append(results, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateHosts(subnet string, begin uint8, end uint8) []string {
|
||||||
|
hosts := []string{}
|
||||||
|
ip := net.ParseIP(subnet).To4()
|
||||||
|
for i := begin; i < end; i++ {
|
||||||
|
ip[3] = byte(i)
|
||||||
|
hosts = append(hosts, fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]))
|
||||||
|
}
|
||||||
|
return hosts
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanForAssets(hosts []string, ports []int, threads int, timeout int) []bmcProbeResult {
|
||||||
|
states := []bmcProbeResult{}
|
||||||
|
done := make(chan struct{}, threads+1)
|
||||||
|
chanHost := make(chan string, threads+1)
|
||||||
|
// chanPort := make(chan int, threads+1)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(threads)
|
||||||
|
for i := 0; i < threads; i++ {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
host, ok := <-chanHost
|
||||||
|
if !ok {
|
||||||
|
wg.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s := rawConnect(host, ports, timeout, true)
|
||||||
|
states = append(states, s...)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, host := range hosts {
|
||||||
|
chanHost <- host
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
wg.Done()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
time.Sleep(1000)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
close(chanHost)
|
||||||
|
wg.Wait()
|
||||||
|
close(done)
|
||||||
|
return states
|
||||||
|
}
|
||||||
|
|
||||||
|
func StoreStates(path string, states *[]bmcProbeResult) error {
|
||||||
|
if states == nil {
|
||||||
|
return fmt.Errorf("states == nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// create database if it doesn't already exist
|
||||||
|
schema := `
|
||||||
|
CREATE IF NOT EXISTS TABLE scanned_ports (
|
||||||
|
host text,
|
||||||
|
port integer,
|
||||||
|
protocol text,
|
||||||
|
state integer
|
||||||
|
)
|
||||||
|
`
|
||||||
|
db, err := sqlx.Open("sqlite3", path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not open database: %v", err)
|
||||||
|
}
|
||||||
|
db.MustExec(schema)
|
||||||
|
|
||||||
|
// insert all probe states into db
|
||||||
|
tx := db.MustBegin()
|
||||||
|
for _, state := range *states {
|
||||||
|
tx.NamedExec(`INSERT INTO scanned_ports (host, port, protocol, state)
|
||||||
|
VALUES (:Host, :Port, :Protocol, :State)`, &state)
|
||||||
|
}
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStates(path string) ([]bmcProbeResult, error) {
|
||||||
|
db, err := sqlx.Open("sqlite3", path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not open database: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
results := []bmcProbeResult{}
|
||||||
|
err = db.Select(&results, "SELECT * FROM scanned_ports ORDER BY host ASC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not retrieve probes: %v", err)
|
||||||
|
}
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDefaultPorts() []int {
|
||||||
|
return []int{SSH_PORT, TLS_PORT, IPMI_PORT, REDFISH_PORT}
|
||||||
|
}
|
||||||
|
|
||||||
|
func QueryInventory(l *logr.Logger, q *QueryParams) ([]byte, error) {
|
||||||
|
// discover.ScanAndConnect(url, user, pass, clientOpts)
|
||||||
|
client, err := makeClient(l, q)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not make query: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// open BMC session and update driver registry
|
||||||
|
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(q.Timeout))
|
||||||
|
client.Registry.FilterForCompatible(ctx)
|
||||||
|
err = client.Open(ctx)
|
||||||
|
if err != nil {
|
||||||
|
ctxCancel()
|
||||||
|
return nil, fmt.Errorf("could not open BMC client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer client.Close(ctx)
|
||||||
|
|
||||||
|
inventory, err := client.Inventory(ctx)
|
||||||
|
if err != nil {
|
||||||
|
ctxCancel()
|
||||||
|
return nil, fmt.Errorf("could not get inventory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve inventory data
|
||||||
|
b, err := json.MarshalIndent(inventory, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
ctxCancel()
|
||||||
|
return nil, fmt.Errorf("could not marshal JSON: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// return b, nil
|
||||||
|
ctxCancel()
|
||||||
|
return []byte(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func QueryUsers(l *logr.Logger, q *QueryParams) ([]byte, error) {
|
||||||
|
// discover.ScanAndConnect(url, user, pass, clientOpts)
|
||||||
|
client, err := makeClient(l, q)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not make query: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// open BMC session and update driver registry
|
||||||
|
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(q.Timeout))
|
||||||
|
client.Registry.FilterForCompatible(ctx)
|
||||||
|
err = client.Open(ctx)
|
||||||
|
if err != nil {
|
||||||
|
ctxCancel()
|
||||||
|
return nil, fmt.Errorf("could not open BMC client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer client.Close(ctx)
|
||||||
|
|
||||||
|
users, err := client.ReadUsers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
ctxCancel()
|
||||||
|
return nil, fmt.Errorf("could not get users: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve inventory data
|
||||||
|
b, err := json.MarshalIndent(users, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
ctxCancel()
|
||||||
|
return nil, fmt.Errorf("could not marshal JSON: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// return b, nil
|
||||||
|
ctxCancel()
|
||||||
|
fmt.Printf("users: %v\n", string(b))
|
||||||
|
return []byte(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// func QueryBios(l *logr.Logger, q *QueryParams) ([]byte, error){
|
||||||
|
// client, err := makeClient(l, q)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, fmt.Errorf("could not make query: %v", err)
|
||||||
|
// }
|
||||||
|
// return makeRequest(client, client.GetBiosConfiguration, q.Timeout)
|
||||||
|
// }
|
||||||
|
|
||||||
|
func makeClient(l *logr.Logger, q *QueryParams) (*bmclib.Client, error) {
|
||||||
|
// NOTE: bmclib.NewClient(host, port, user, pass)
|
||||||
|
// ...seems like the `port` params doesn't work like expected depending on interface
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
httpClient := http.Client{
|
||||||
|
Transport: tr,
|
||||||
|
}
|
||||||
|
|
||||||
|
// init client
|
||||||
|
clientOpts := []bmclib.Option{
|
||||||
|
// bmclib.WithSecureTLS(),
|
||||||
|
bmclib.WithHTTPClient(&httpClient),
|
||||||
|
bmclib.WithLogger(*l),
|
||||||
|
// bmclib.WithRedfishHTTPClient(&httpClient),
|
||||||
|
// bmclib.WithRedfishPort(fmt.Sprint(q.Port)),
|
||||||
|
// bmclib.WithRedfishUseBasicAuth(true),
|
||||||
|
// bmclib.WithDellRedfishUseBasicAuth(true),
|
||||||
|
// bmclib.WithIpmitoolPort(fmt.Sprint(q.Port)),
|
||||||
|
}
|
||||||
|
|
||||||
|
// only work if valid cert is provided
|
||||||
|
if q.WithSecureTLS {
|
||||||
|
var pool *x509.CertPool
|
||||||
|
if q.CertPoolFile != "" {
|
||||||
|
pool = x509.NewCertPool()
|
||||||
|
data, err := os.ReadFile(q.CertPoolFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read cert pool file: %v", err)
|
||||||
|
}
|
||||||
|
pool.AppendCertsFromPEM(data)
|
||||||
|
}
|
||||||
|
// a nil pool uses the system certs
|
||||||
|
clientOpts = append(clientOpts, bmclib.WithSecureTLS(pool))
|
||||||
|
}
|
||||||
|
// url := fmt.Sprintf("https://%s:%s@%s", q.User, q.Pass, q.Host)
|
||||||
|
url := fmt.Sprintf("https://%s:%s@%s:%d", q.User, q.Pass, q.Host, q.Port)
|
||||||
|
fmt.Println("url: ", url)
|
||||||
|
client := bmclib.NewClient(url, fmt.Sprint(q.Port), q.User, q.Pass, clientOpts...)
|
||||||
|
ds := registrar.Drivers{}
|
||||||
|
for _, driver := range q.Drivers {
|
||||||
|
ds = append(ds, client.Registry.Using(driver)...) // ipmi, gofish, redfish
|
||||||
|
}
|
||||||
|
client.Registry.Drivers = ds
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeRequest[T interface{}](client *bmclib.Client, fn func(context.Context) (T, error), timeout int) ([]byte, error){
|
||||||
|
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(timeout))
|
||||||
|
client.Registry.FilterForCompatible(ctx)
|
||||||
|
err := client.Open(ctx)
|
||||||
|
if err != nil {
|
||||||
|
ctxCancel()
|
||||||
|
return nil, fmt.Errorf("could not open BMC client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer client.Close(ctx)
|
||||||
|
|
||||||
|
response, err := fn(ctx)
|
||||||
|
if err != nil {
|
||||||
|
ctxCancel()
|
||||||
|
return nil, fmt.Errorf("could not get response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxCancel()
|
||||||
|
return makeJson(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeJson(object interface{}) ([]byte, error) {
|
||||||
|
b, err := json.MarshalIndent(object, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not marshal JSON: %v", err)
|
||||||
|
}
|
||||||
|
return []byte(b), nil
|
||||||
|
}
|
||||||
113
main.go
Normal file
113
main.go
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
smd "davidallendj/magellan/api/smd"
|
||||||
|
magellan "davidallendj/magellan/internal"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
// smd "github.com/alexlovelltroy/hms-smd/pkg/redfish"
|
||||||
|
|
||||||
|
logrusr "github.com/bombsimon/logrusr/v2"
|
||||||
|
"github.com/cznic/mathutil"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
timeout int
|
||||||
|
threads int
|
||||||
|
ports []int
|
||||||
|
subnets []string
|
||||||
|
hosts []string
|
||||||
|
withSecureTLS bool
|
||||||
|
certPoolFile string
|
||||||
|
user string
|
||||||
|
pass string
|
||||||
|
dbpath string
|
||||||
|
drivers []string
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: discover bmc's on network (dora)
|
||||||
|
// TODO: query bmc component information and store in db (?)
|
||||||
|
// TODO: send bmc component information to smd
|
||||||
|
func main() {
|
||||||
|
pflag.StringVar(&user, "user", "root", "set the BMC user")
|
||||||
|
pflag.StringVar(&pass, "pass", "root_password", "set the BMC pass")
|
||||||
|
pflag.StringSliceVar(&subnets, "subnet", []string{"127.0.0.0"}, "set additional subnets")
|
||||||
|
pflag.StringSliceVar(&hosts, "host", []string{}, "set additional hosts")
|
||||||
|
pflag.IntVar(&threads, "threads", -1, "set the number of threads")
|
||||||
|
pflag.IntVar(&timeout, "timeout", 1, "set the timeout")
|
||||||
|
pflag.IntSliceVar(&ports, "port", []int{}, "set the ports to scan")
|
||||||
|
pflag.StringSliceVar(&drivers, "driver", []string{"redfish"}, "set the BMC driver to use")
|
||||||
|
pflag.StringVar(&dbpath, "dbpath", ":memory:", "set the probe storage path")
|
||||||
|
pflag.BoolVar(&withSecureTLS, "secure-tls", false, "enable secure TLS")
|
||||||
|
pflag.StringVar(&certPoolFile, "cert-pool", "", "path to an file containing x509 CAs. An empty string uses the system CAs. Only takes effect when --secure-tls=true")
|
||||||
|
pflag.Parse()
|
||||||
|
|
||||||
|
// make application logger
|
||||||
|
l := logrus.New()
|
||||||
|
l.Level = logrus.DebugLevel
|
||||||
|
logger := logrusr.New(l)
|
||||||
|
|
||||||
|
// set hosts to use for scanning
|
||||||
|
hostsToScan := []string{}
|
||||||
|
if len(hosts) > 0 {
|
||||||
|
hostsToScan = hosts
|
||||||
|
} else {
|
||||||
|
for _, subnet := range subnets {
|
||||||
|
hostsToScan = append(hostsToScan, magellan.GenerateHosts(subnet, 1, 5)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set ports to use for scanning
|
||||||
|
portsToScan := []int{}
|
||||||
|
if len(ports) > 0 {
|
||||||
|
portsToScan = ports
|
||||||
|
} else {
|
||||||
|
portsToScan = append(magellan.GetDefaultPorts(), ports...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// scan and store probe data in dbPath
|
||||||
|
if threads <= 0 {
|
||||||
|
threads = mathutil.Clamp(len(hostsToScan), 1, 255)
|
||||||
|
}
|
||||||
|
probeStates := magellan.ScanForAssets(hostsToScan, portsToScan, threads, timeout)
|
||||||
|
fmt.Printf("probe states: %v\n", probeStates)
|
||||||
|
magellan.StoreStates(dbpath, &probeStates)
|
||||||
|
|
||||||
|
// use the found results to query bmc information
|
||||||
|
inventories := [][]byte{}
|
||||||
|
for _, ps := range probeStates {
|
||||||
|
if !ps.State {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
logrus.Infof("querying bmc %v\n", ps)
|
||||||
|
q := magellan.QueryParams{
|
||||||
|
Host: ps.Host,
|
||||||
|
Port: ps.Port,
|
||||||
|
User: user,
|
||||||
|
Pass: pass,
|
||||||
|
Drivers: drivers,
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
inventory, err := magellan.QueryInventory(&logger, &q)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("could not query BMC information: %v\n", err)
|
||||||
|
}
|
||||||
|
inventories = append(inventories, inventory)
|
||||||
|
}
|
||||||
|
|
||||||
|
// add all endpoints to smd
|
||||||
|
for _, inventory := range inventories {
|
||||||
|
err := smd.AddRedfishEndpoint(inventory)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("could not add redfish endpoint: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// confirm the inventories were added
|
||||||
|
err := smd.GetRedfishEndpoints()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("could not get redfish endpoints: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue