From 39fbeaa03ee7c7ae3ded9b02ddcdcd9657758e4e Mon Sep 17 00:00:00 2001 From: Jash Lal Date: Tue, 22 Jul 2025 09:20:27 -0700 Subject: [PATCH 1/3] Also retrieve username from secret in the hotswap driver function --- aws/secret.go | 29 ++++++++++++++++++++++------- dbconn/factory.go | 19 ++++++++++++++----- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/aws/secret.go b/aws/secret.go index 8e79eb12..e8a884d1 100644 --- a/aws/secret.go +++ b/aws/secret.go @@ -25,7 +25,23 @@ func NewSecret(name string, cfg aws.Config) Secret { } } -func (s Secret) Password(ctx context.Context) (string, error) { +func (s Secret) Username(v map[string]interface{}) (string, error) { + username, ok := v["username"] + if !ok { + return "", fmt.Errorf("failed to retrieve value for key 'username'") + } + return username.(string), nil +} + +func (s Secret) Password(v map[string]interface{}) (string, error) { + username, ok := v["password"] + if !ok { + return "", fmt.Errorf("failed to retrieve value for key 'password'") + } + return username.(string), nil +} + +func (s Secret) GetSecret(ctx context.Context) (map[string]interface{}, error) { input := &secretsmanager.GetSecretValueInput{ SecretId: aws.String(s.name), VersionStage: aws.String("AWSCURRENT"), @@ -33,21 +49,20 @@ func (s Secret) Password(ctx context.Context) (string, error) { sv, err := s.client.GetSecretValue(ctx, input) if err != nil { - return "", fmt.Errorf("Secrets Manager API error: %s", err) + return nil, fmt.Errorf("Secrets Manager API error: %s", err) } blip.Debug("DEBUG: aws secret: %+v", *sv) if sv.SecretString == nil || *sv.SecretString == "" { - return "", fmt.Errorf("secret string is nil or empty") + return nil, fmt.Errorf("secret string is nil or empty") } var v map[string]interface{} if err := json.Unmarshal([]byte(*sv.SecretString), &v); err != nil { - return "", fmt.Errorf("cannot decode secret string as map[string]string: %s", err) + return nil, fmt.Errorf("cannot decode secret string as map[string]string: %s", err) } if v == nil { - return "", fmt.Errorf("secret value is 'null' literal") + return nil, fmt.Errorf("secret value is 'null' literal") } - - return v["password"].(string), nil + return v, nil } diff --git a/dbconn/factory.go b/dbconn/factory.go index d1331c06..a9b26dd1 100644 --- a/dbconn/factory.go +++ b/dbconn/factory.go @@ -8,7 +8,6 @@ import ( "database/sql" "fmt" "io/fs" - "io/ioutil" "log" "os" "os/exec" @@ -290,15 +289,25 @@ func (f factory) Credentials(cfg blip.ConfigMonitor) (CredentialFunc, error) { } secret := aws.NewSecret(cfg.AWS.PasswordSecret, awscfg) return func(ctx context.Context) (Credentials, error) { - passwd, err := secret.Password(ctx) + newSecret, err := secret.GetSecret(ctx) if err != nil { return Credentials{}, err } + username, err := secret.Username(newSecret) + if err != nil { + // The username key is optional. Default to config + username = cfg.Username + } + password, err := secret.Password(newSecret) + if err != nil { + return Credentials{}, fmt.Errorf("error retrieving value for secret '%v'", cfg.AWS.PasswordSecret) + } + return Credentials{ - Password: passwd, - Username: cfg.Username, + Password: password, + Username: username, }, nil }, nil } @@ -307,7 +316,7 @@ func (f factory) Credentials(cfg blip.ConfigMonitor) (CredentialFunc, error) { if cfg.PasswordFile != "" { blip.Debug("%s: password file", cfg.MonitorId) return func(context.Context) (Credentials, error) { - bytes, err := ioutil.ReadFile(cfg.PasswordFile) + bytes, err := os.ReadFile(cfg.PasswordFile) if err != nil { return Credentials{}, err } From 03da191b67c565deafb0a48caf7bfc606d7df037 Mon Sep 17 00:00:00 2001 From: Jash Lal Date: Thu, 24 Jul 2025 10:48:14 -0700 Subject: [PATCH 2/3] Remove username and password functions --- aws/secret.go | 16 ---------------- dbconn/factory.go | 15 +++++++-------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/aws/secret.go b/aws/secret.go index e8a884d1..b4927c72 100644 --- a/aws/secret.go +++ b/aws/secret.go @@ -25,22 +25,6 @@ func NewSecret(name string, cfg aws.Config) Secret { } } -func (s Secret) Username(v map[string]interface{}) (string, error) { - username, ok := v["username"] - if !ok { - return "", fmt.Errorf("failed to retrieve value for key 'username'") - } - return username.(string), nil -} - -func (s Secret) Password(v map[string]interface{}) (string, error) { - username, ok := v["password"] - if !ok { - return "", fmt.Errorf("failed to retrieve value for key 'password'") - } - return username.(string), nil -} - func (s Secret) GetSecret(ctx context.Context) (map[string]interface{}, error) { input := &secretsmanager.GetSecretValueInput{ SecretId: aws.String(s.name), diff --git a/dbconn/factory.go b/dbconn/factory.go index a9b26dd1..c5e7a65b 100644 --- a/dbconn/factory.go +++ b/dbconn/factory.go @@ -290,24 +290,23 @@ func (f factory) Credentials(cfg blip.ConfigMonitor) (CredentialFunc, error) { secret := aws.NewSecret(cfg.AWS.PasswordSecret, awscfg) return func(ctx context.Context) (Credentials, error) { newSecret, err := secret.GetSecret(ctx) - if err != nil { return Credentials{}, err } - username, err := secret.Username(newSecret) - if err != nil { + username, ok := newSecret["username"] + if !ok { // The username key is optional. Default to config username = cfg.Username } - password, err := secret.Password(newSecret) - if err != nil { - return Credentials{}, fmt.Errorf("error retrieving value for secret '%v'", cfg.AWS.PasswordSecret) + password, ok := newSecret["password"] + if !ok { + return Credentials{}, fmt.Errorf("error retrieving 'password' value for secret") } return Credentials{ - Password: password, - Username: username, + Password: password.(string), + Username: username.(string), }, nil }, nil } From 14c6dada8912e9b4b4412deabb625eb7908a21db Mon Sep 17 00:00:00 2001 From: Jash Lal Date: Thu, 24 Jul 2025 11:07:53 -0700 Subject: [PATCH 3/3] Type check secret values before returning --- dbconn/factory.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/dbconn/factory.go b/dbconn/factory.go index c5e7a65b..b4f90aec 100644 --- a/dbconn/factory.go +++ b/dbconn/factory.go @@ -299,14 +299,22 @@ func (f factory) Credentials(cfg blip.ConfigMonitor) (CredentialFunc, error) { // The username key is optional. Default to config username = cfg.Username } + usernameStr, ok := username.(string) + if !ok { + username = cfg.Username + } password, ok := newSecret["password"] if !ok { - return Credentials{}, fmt.Errorf("error retrieving 'password' value for secret") + return Credentials{}, fmt.Errorf("error retrieving 'password' value of secret") + } + passwordStr, ok := password.(string) + if !ok { + return Credentials{}, fmt.Errorf("invalid type for 'password' value of secret") } return Credentials{ - Password: password.(string), - Username: username.(string), + Password: passwordStr, + Username: usernameStr, }, nil }, nil }