diff --git a/cmd/crawl.go b/cmd/crawl.go index 9b44285..5e4a038 100644 --- a/cmd/crawl.go +++ b/cmd/crawl.go @@ -7,6 +7,7 @@ import ( "github.com/rs/zerolog/log" urlx "github.com/OpenCHAMI/magellan/internal/url" + "github.com/OpenCHAMI/magellan/pkg/bmc" "github.com/OpenCHAMI/magellan/pkg/crawler" "github.com/OpenCHAMI/magellan/pkg/secrets" "github.com/spf13/cobra" @@ -43,60 +44,32 @@ var CrawlCmd = &cobra.Command{ if username != "" && password != "" { // First, try and load credentials from --username and --password if both are set. - log.Debug().Str("uri", uri).Msgf("--username and --password specified, using them for BMC credentials") + log.Debug().Str("id", uri).Msgf("--username and --password specified, using them for BMC credentials") store = secrets.NewStaticStore(username, password) } else { // Alternatively, locate specific credentials (falling back to default) and override those // with --username or --password if either are passed. - log.Debug().Str("uri", uri).Msgf("one or both of --username and --password NOT passed, attempting to obtain missing credentials from secret store at %s", secretsFile) + log.Debug().Str("id", uri).Msgf("one or both of --username and --password NOT passed, attempting to obtain missing credentials from secret store at %s", secretsFile) if store, err = secrets.OpenStore(secretsFile); err != nil { - log.Error().Str("uri", uri).Err(err).Msg("failed to open local secrets store") + log.Error().Str("id", uri).Err(err).Msg("failed to open local secrets store") } // Either none of the flags were passed or only one of them were; get // credentials from secrets store to fill in the gaps. - // - // Attempt to get URI-specific credentials. - var nodeCreds secrets.StaticStore - if uriCreds, err := store.GetSecretByID(uri); err != nil { - // Specific credentials for URI not found, fetch default. - log.Warn().Str("uri", uri).Msg("specific credentials not found, falling back to default") - defaultSecret, err := store.GetSecretByID(secrets.DEFAULT_KEY) - if err != nil { - // We've exhausted all options, the credentials will be blank unless - // overridden by a CLI flag. - log.Warn().Str("uri", uri).Err(err).Msg("no default credentials were set, they will be blank unless overridden by CLI flags") - } else { - // Default credentials found, use them. - var creds crawler.BMCUsernamePassword - if err = json.Unmarshal([]byte(defaultSecret), &creds); err != nil { - log.Warn().Str("uri", uri).Err(err).Msg("failed to unmarshal default secrets store credentials") - } else { - log.Info().Str("uri", uri).Msg("default credentials found, using") - nodeCreds.Username = creds.Username - nodeCreds.Password = creds.Password - } - } - } else { - // Specific URI credentials found, use them. - var creds crawler.BMCUsernamePassword - if err = json.Unmarshal([]byte(uriCreds), &creds); err != nil { - log.Warn().Str("uri", uri).Err(err).Msg("failed to unmarshal uri credentials") - } else { - nodeCreds.Username = creds.Username - nodeCreds.Password = creds.Password - log.Info().Str("uri", uri).Msg("specific credentials found, using") - } + bmcCreds, _ := bmc.GetBMCCredentials(store, uri) + nodeCreds := secrets.StaticStore{ + Username: bmcCreds.Username, + Password: bmcCreds.Password, } // If either of the flags were passed, override the fetched // credentials with them. if username != "" { - log.Info().Str("uri", uri).Msg("--username was set, overriding username for this BMC") + log.Info().Str("id", uri).Msg("--username was set, overriding username for this BMC") nodeCreds.Username = username } if password != "" { - log.Info().Str("uri", uri).Msg("--password was set, overriding password for this BMC") + log.Info().Str("id", uri).Msg("--password was set, overriding password for this BMC") nodeCreds.Password = password } diff --git a/pkg/bmc/bmc.go b/pkg/bmc/bmc.go new file mode 100644 index 0000000..9948e0d --- /dev/null +++ b/pkg/bmc/bmc.go @@ -0,0 +1,45 @@ +package bmc + +import ( + "encoding/json" + + "github.com/OpenCHAMI/magellan/pkg/secrets" + "github.com/rs/zerolog/log" +) + +type BMCCredentials struct { + Username string `json:"username"` + Password string `json:"password"` +} + +func GetBMCCredentials(store secrets.SecretStore, id string) (BMCCredentials, error) { + var creds BMCCredentials + if uriCreds, err := store.GetSecretByID(id); err != nil { + // Specific credentials for URI not found, fetch default. + log.Warn().Str("id", id).Msg("specific credentials not found, falling back to default") + defaultSecret, err := store.GetSecretByID(secrets.DEFAULT_KEY) + if err != nil { + // We've exhausted all options, the credentials will be blank unless + // overridden by a CLI flag. + log.Warn().Str("id", id).Err(err).Msg("no default credentials were set, they will be blank unless overridden by CLI flags") + } else { + // Default credentials found, use them. + if err = json.Unmarshal([]byte(defaultSecret), &creds); err != nil { + log.Warn().Str("id", id).Err(err).Msg("failed to unmarshal default secrets store credentials") + return creds, err + } else { + log.Info().Str("id", id).Msg("default credentials found, using") + } + } + } else { + // Specific URI credentials found, use them. + if err = json.Unmarshal([]byte(uriCreds), &creds); err != nil { + log.Warn().Str("id", id).Err(err).Msg("failed to unmarshal specific credentials") + return creds, err + } else { + log.Info().Str("id", id).Msg("specific credentials found, using") + } + } + + return creds, nil +} diff --git a/pkg/crawler/main.go b/pkg/crawler/main.go index 2eb9932..8b732f4 100644 --- a/pkg/crawler/main.go +++ b/pkg/crawler/main.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + "github.com/OpenCHAMI/magellan/pkg/bmc" "github.com/OpenCHAMI/magellan/pkg/secrets" "github.com/rs/zerolog/log" "github.com/stmcginnis/gofish" @@ -18,15 +19,10 @@ type CrawlerConfig struct { UseDefault bool } -func (cc *CrawlerConfig) GetUserPass() (BMCUsernamePassword, error) { +func (cc *CrawlerConfig) GetUserPass() (bmc.BMCCredentials, error) { return loadBMCCreds(*cc) } -type BMCUsernamePassword struct { - Username string `json:"username"` - Password string `json:"password"` -} - type EthernetInterface struct { URI string `json:"uri,omitempty"` // URI of the interface MAC string `json:"mac,omitempty"` // MAC address of the interface @@ -373,10 +369,10 @@ func walkManagers(rf_managers []*redfish.Manager, baseURI string) ([]Manager, er return managers, nil } -func loadBMCCreds(config CrawlerConfig) (BMCUsernamePassword, error) { +func loadBMCCreds(config CrawlerConfig) (bmc.BMCCredentials, error) { // NOTE: it is possible for the SecretStore to be nil, so we need a check if config.CredentialStore == nil { - return BMCUsernamePassword{}, fmt.Errorf("credential store is invalid") + return bmc.BMCCredentials{}, fmt.Errorf("credential store is invalid") } creds, err := config.CredentialStore.GetSecretByID(config.URI) if err != nil { @@ -391,19 +387,19 @@ func loadBMCCreds(config CrawlerConfig) (BMCUsernamePassword, error) { event := log.Error() event.Err(err) event.Msg("failed to get default credentials from secret store") - return BMCUsernamePassword{}, err + return bmc.BMCCredentials{}, err } } else { - return BMCUsernamePassword{}, err + return bmc.BMCCredentials{}, err } } - var bmc_creds BMCUsernamePassword + var bmc_creds bmc.BMCCredentials err = json.Unmarshal([]byte(creds), &bmc_creds) if err != nil { event := log.Error() event.Err(err) event.Msg("failed to unmarshal credentials") - return BMCUsernamePassword{}, err + return bmc.BMCCredentials{}, err } return bmc_creds, nil } diff --git a/pkg/update.go b/pkg/update.go index fea41b8..411c28e 100644 --- a/pkg/update.go +++ b/pkg/update.go @@ -4,6 +4,7 @@ import ( "fmt" "net/url" + "github.com/OpenCHAMI/magellan/pkg/bmc" "github.com/stmcginnis/gofish" "github.com/stmcginnis/gofish/redfish" ) @@ -34,8 +35,14 @@ func UpdateFirmwareRemote(q *UpdateParams) error { return fmt.Errorf("failed to parse URI: %w", err) } + // Get BMC credentials from secret store in update parameters + bmcCreds, err := bmc.GetBMCCredentials(q.SecretStore, q.URI) + if err != nil { + return fmt.Errorf("failed to get BMC credentials: %w", err) + } + // Connect to the Redfish service using gofish - client, err := gofish.Connect(gofish.ClientConfig{Endpoint: uri.String(), Username: q.Username, Password: q.Password, Insecure: q.Insecure}) + client, err := gofish.Connect(gofish.ClientConfig{Endpoint: uri.String(), Username: bmcCreds.Username, Password: bmcCreds.Password, Insecure: q.Insecure}) if err != nil { return fmt.Errorf("failed to connect to Redfish service: %w", err) } @@ -69,8 +76,14 @@ func GetUpdateStatus(q *UpdateParams) error { return fmt.Errorf("failed to parse URI: %w", err) } + // Get BMC credentials from secret store in update parameters + bmcCreds, err := bmc.GetBMCCredentials(q.SecretStore, q.URI) + if err != nil { + return fmt.Errorf("failed to get BMC credentials: %w", err) + } + // Connect to the Redfish service using gofish - client, err := gofish.Connect(gofish.ClientConfig{Endpoint: uri.String(), Username: q.Username, Password: q.Password, Insecure: q.Insecure}) + client, err := gofish.Connect(gofish.ClientConfig{Endpoint: uri.String(), Username: bmcCreds.Username, Password: bmcCreds.Password, Insecure: q.Insecure}) if err != nil { return fmt.Errorf("failed to connect to Redfish service: %w", err) }