Added more API documentation

This commit is contained in:
David Allen 2024-07-23 16:18:21 -06:00
parent 2bc3c74277
commit f7b08da064
No known key found for this signature in database
GPG key ID: 717C593FF60A2ACC
8 changed files with 150 additions and 90 deletions

View file

@ -7,15 +7,19 @@ import (
"github.com/spf13/viper"
)
// LoadConfig() will load a YAML config file at the specified path. There are some general
// considerations about how this is done with spf13/viper:
//
// 1. There are intentionally no search paths set, so config path has to be set explicitly
// 2. No data will be written to the config file from the tool
// 3. Parameters passed as CLI flags and envirnoment variables should always have
// precedence over values set in the config.
func LoadConfig(path string) error {
dir, filename, ext := util.SplitPathForViper(path)
// fmt.Printf("dir: %s\nfilename: %s\nextension: %s\n", dir, filename, ext)
viper.AddConfigPath(dir)
viper.SetConfigName(filename)
viper.SetConfigType(ext)
// ...no search paths set intentionally, so config has to be set explicitly
// ...also, the config file will not save anything
// ...and finally, parameters passed to CLI have precedence over config values
viper.AutomaticEnv()
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {

View file

@ -8,6 +8,17 @@ import (
"github.com/pkg/browser"
)
// Login() initiates the process to retrieve an access token from an identity provider.
// This function is especially designed to work by OPAAL, but will propably be changed
// in the future to be more agnostic.
//
// The 'targetHost' and 'targetPort' parameters should point to the target host/port
// to create a temporary server to receive the access token. If an empty 'targetHost'
// or an invalid port range is passed, then neither of the parameters will be used
// and no server will be started.
//
// Returns an access token as a string if successful and nil error. Otherwise, returns
// an empty string with an error set.
func Login(loginUrl string, targetHost string, targetPort int) (string, error) {
var accessToken string

View file

@ -19,94 +19,31 @@ type ScannedResult struct {
Timestamp time.Time `json:"timestamp"`
}
func rawConnect(host string, ports []int, timeout int, keepOpenOnly bool) []ScannedResult {
results := []ScannedResult{}
for _, p := range ports {
result := ScannedResult{
Host: host,
Port: p,
Protocol: "tcp",
State: false,
Timestamp: time.Now(),
}
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, subnetMask *net.IP) []string {
if subnet == "" || subnetMask == nil {
return nil
}
// convert subnets from string to net.IP
subnetIp := net.ParseIP(subnet)
if subnetIp == nil {
// try parse CIDR instead
ip, network, err := net.ParseCIDR(subnet)
if err != nil {
return nil
}
subnetIp = ip
if network != nil {
t := net.IP(network.Mask)
subnetMask = &t
}
}
mask := net.IPMask(subnetMask.To4())
// if no subnet mask, use a default 24-bit mask (for now)
return generateHosts(&subnetIp, &mask)
}
func generateHosts(ip *net.IP, mask *net.IPMask) []string {
// get all IP addresses in network
ones, _ := mask.Size()
hosts := []string{}
end := int(math.Pow(2, float64((32-ones)))) - 1
for i := 0; i < end; i++ {
// ip[3] = byte(i)
ip = util.GetNextIP(ip, 1)
if ip == nil {
continue
}
// host := fmt.Sprintf("%v.%v.%v.%v", (*ip)[0], (*ip)[1], (*ip)[2], (*ip)[3])
// fmt.Printf("host: %v\n", ip.String())
hosts = append(hosts, ip.String())
}
return hosts
}
func ScanForAssets(hosts []string, ports []int, threads int, timeout int, disableProbing bool, verbose bool) []ScannedResult {
// ScanForAssets() performs a net scan on a network to find available services
// running. The function expects a list of hosts and ports to make requests.
// Note that each all ports will be used per host.
//
// This function runs in a goroutine with the "concurrency" flag setting the
// number of concurrent requests. Only one request is made to each BMC node
// at a time, but setting a value greater than 1 with enable the requests
// to be made concurrently.
//
// If the "disableProbing" flag is set, then the function will skip the extra
// HTTP request made to check if the response was from a Redfish service.
// Otherwise, not receiving a 200 OK response code from the HTTP request will
// remove the service from being stored in the list of scanned results.
//
// Returns a list of scanned results to be stored in cache (but isn't doing here).
func ScanForAssets(hosts []string, ports []int, concurrency int, timeout int, disableProbing bool, verbose bool) []ScannedResult {
var (
results = make([]ScannedResult, 0, len(hosts))
done = make(chan struct{}, threads+1)
chanHost = make(chan string, threads+1)
done = make(chan struct{}, concurrency+1)
chanHost = make(chan string, concurrency+1)
)
var wg sync.WaitGroup
wg.Add(threads)
for i := 0; i < threads; i++ {
wg.Add(concurrency)
for i := 0; i < concurrency; i++ {
go func() {
for {
host, ok := <-chanHost
@ -161,6 +98,92 @@ func ScanForAssets(hosts []string, ports []int, threads int, timeout int, disabl
return results
}
// GenerateHosts() builds a list of hosts to scan using the "subnet"
// and "subnetMask" arguments passed. The function is capable of
// distinguishing between IP formats: a subnet with just an IP address (172.16.0.0) and
// a subnet with IP address and CIDR (172.16.0.0/24).
//
// NOTE: If a IP address is provided with CIDR, then the "subnetMask"
// parameter will be ignored. If neither is provided, then the default
// subnet mask will be used instead.
func GenerateHosts(subnet string, subnetMask *net.IP) []string {
if subnet == "" || subnetMask == nil {
return nil
}
// convert subnets from string to net.IP
subnetIp := net.ParseIP(subnet)
if subnetIp == nil {
// try parse CIDR instead
ip, network, err := net.ParseCIDR(subnet)
if err != nil {
return nil
}
subnetIp = ip
if network != nil {
t := net.IP(network.Mask)
subnetMask = &t
}
}
mask := net.IPMask(subnetMask.To4())
// if no subnet mask, use a default 24-bit mask (for now)
return generateHosts(&subnetIp, &mask)
}
func GetDefaultPorts() []int {
return []int{HTTPS_PORT}
}
func rawConnect(host string, ports []int, timeout int, keepOpenOnly bool) []ScannedResult {
results := []ScannedResult{}
for _, p := range ports {
result := ScannedResult{
Host: host,
Port: p,
Protocol: "tcp",
State: false,
Timestamp: time.Now(),
}
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(ip *net.IP, mask *net.IPMask) []string {
// get all IP addresses in network
ones, _ := mask.Size()
hosts := []string{}
end := int(math.Pow(2, float64((32-ones)))) - 1
for i := 0; i < end; i++ {
// ip[3] = byte(i)
ip = util.GetNextIP(ip, 1)
if ip == nil {
continue
}
// host := fmt.Sprintf("%v.%v.%v.%v", (*ip)[0], (*ip)[1], (*ip)[2], (*ip)[3])
// fmt.Printf("host: %v\n", ip.String())
hosts = append(hosts, ip.String())
}
return hosts
}

View file

@ -26,8 +26,14 @@ type UpdateParams struct {
TransferProtocol string
}
// NOTE: Does not work since OpenBMC, whic bmclib uses underneath, does not
// support multipart updates. See issue: https://github.com/bmc-toolbox/bmclib/issues/341
// UpdateFirmware() uses 'bmc-toolbox/bmclib' to update the firmware of a BMC node.
// The function expects the firmware URL, firmware version, and component flags to be
// set from the CLI to perform a firmware update.
//
// NOTE: Multipart HTTP updating may not work since older verions of OpenBMC, which bmclib
// uses underneath, did not support support multipart updates. This was changed with the
// inclusion of support for MultipartHttpPushUri in OpenBMC (https://gerrit.openbmc.org/c/openbmc/bmcweb/+/32174).
// Also, related to bmclib: https://github.com/bmc-toolbox/bmclib/issues/341
func UpdateFirmware(client *bmclib.Client, l *log.Logger, q *UpdateParams) error {
if q.Component == "" {
return fmt.Errorf("component is required")