diff --git a/internal/collect.go b/internal/collect.go index ea7ca69..8c03050 100644 --- a/internal/collect.go +++ b/internal/collect.go @@ -2,8 +2,12 @@ package magellan import ( + "crypto/tls" + "crypto/x509" "encoding/json" "fmt" + "net" + "net/http" "os" "path" "sync" @@ -58,12 +62,32 @@ func CollectInventory(assets *[]RemoteAsset, params *CollectParams) error { done = make(chan struct{}, params.Concurrency+1) chanAssets = make(chan RemoteAsset, params.Concurrency+1) outputPath = path.Clean(params.OutputPath) - smdClient = client.NewClient( - client.WithSecureTLS[client.SmdClient](params.CaCertPath), - ) + smdClient = &client.SmdClient{Client: &http.Client{}} ) - // set the client's host from the CLI param + // set the client's params from CLI + // NOTE: temporary solution until client.NewClient() is fixed smdClient.URI = params.URI + if params.CaCertPath != "" { + cacert, err := os.ReadFile(params.CaCertPath) + if err != nil { + return fmt.Errorf("failed to read CA cert path: %w", err) + } + certPool := x509.NewCertPool() + certPool.AppendCertsFromPEM(cacert) + smdClient.Client.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: certPool, + InsecureSkipVerify: true, + }, + DisableKeepAlives: true, + Dial: (&net.Dialer{ + Timeout: 120 * time.Second, + KeepAlive: 120 * time.Second, + }).Dial, + TLSHandshakeTimeout: 120 * time.Second, + ResponseHeaderTimeout: 120 * time.Second, + } + } wg.Add(params.Concurrency) for i := 0; i < params.Concurrency; i++ { go func() { diff --git a/pkg/client/client.go b/pkg/client/client.go index 0005254..eda049b 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -9,17 +9,20 @@ import ( "net/http" "os" "time" + + "github.com/rs/zerolog/log" ) -type Option[T Client] func(client T) +type Option[T Client] func(client *T) // The 'Client' struct is a wrapper around the default http.Client // that provides an extended API to work with functional options. // It also provides functions that work with `collect` data. type Client interface { + Init() Name() string - GetClient() *http.Client RootEndpoint(endpoint string) string + GetInternalClient() *http.Client // functions needed to make request Add(data HTTPBody, headers HTTPHeader) error @@ -36,11 +39,17 @@ func NewClient[T Client](opts ...func(T)) T { } func WithCertPool[T Client](certPool *x509.CertPool) func(T) { + // make sure we have a valid cert pool if certPool == nil { return func(client T) {} } return func(client T) { - client.GetClient().Transport = &http.Transport{ + // make sure that we can access the internal client + if client.GetInternalClient() == nil { + log.Warn().Any("client", client.GetInternalClient()).Msg("invalid internal HTTP client ()") + return + } + client.GetInternalClient().Transport = &http.Transport{ TLSClientConfig: &tls.Config{ RootCAs: certPool, InsecureSkipVerify: true, diff --git a/pkg/client/smd.go b/pkg/client/smd.go index a118460..499a72c 100644 --- a/pkg/client/smd.go +++ b/pkg/client/smd.go @@ -16,22 +16,26 @@ type SmdClient struct { Xname string } -func (c SmdClient) Name() string { +func (c *SmdClient) Init() { + c.Client = &http.Client{} +} + +func (c *SmdClient) Name() string { return "smd" } -func (c SmdClient) RootEndpoint(endpoint string) string { +func (c *SmdClient) RootEndpoint(endpoint string) string { return fmt.Sprintf("%s/hsm/v2%s", c.URI, endpoint) } -func (c SmdClient) GetClient() *http.Client { +func (c *SmdClient) GetInternalClient() *http.Client { return c.Client } // Add() has a similar function definition to that of the default implementation, // but also allows further customization and data/header manipulation that would // be specific and/or unique to SMD's API. -func (c SmdClient) Add(data HTTPBody, headers HTTPHeader) error { +func (c *SmdClient) Add(data HTTPBody, headers HTTPHeader) error { if data == nil { return fmt.Errorf("failed to add redfish endpoint: no data found") } @@ -53,7 +57,7 @@ func (c SmdClient) Add(data HTTPBody, headers HTTPHeader) error { return err } -func (c SmdClient) Update(data HTTPBody, headers HTTPHeader) error { +func (c *SmdClient) Update(data HTTPBody, headers HTTPHeader) error { if data == nil { return fmt.Errorf("failed to add redfish endpoint: no data found") } diff --git a/pkg/crawler/main.go b/pkg/crawler/main.go index 78af9f9..e28cb1b 100644 --- a/pkg/crawler/main.go +++ b/pkg/crawler/main.go @@ -45,7 +45,7 @@ type InventoryDetail struct { URI string `json:"uri,omitempty"` // URI of the BMC UUID string `json:"uuid,omitempty"` // UUID of Node Manufacturer string `json:"manufacturer,omitempty"` // Manufacturer of the Node - SystemType string `json:"system_type,omitempty` // System type of the Node + SystemType string `json:"system_type,omitempty"` // System type of the Node Name string `json:"name,omitempty"` // Name of the Node Model string `json:"model,omitempty"` // Model of the Node Serial string `json:"serial,omitempty"` // Serial number of the Node