From f9477863a58688e745bb842df3bc8723b8879199 Mon Sep 17 00:00:00 2001 From: Christopher Bentkowski Date: Fri, 25 Oct 2024 21:18:00 -0500 Subject: [PATCH 1/7] Added new else if for SECRET_JSON to call utils function to parse JSON Username/Password --- lambda/main.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lambda/main.go b/lambda/main.go index 639d52c6..e003037e 100644 --- a/lambda/main.go +++ b/lambda/main.go @@ -163,6 +163,9 @@ func parseCreds(creds string) (string, error) { return secret, err } else if credsType == SECRET_TEXT { return creds, nil + } else if credsType == SECRET_JSON { + secret, err := GetJSONSecret(creds) + return secret, err } - return "", fmt.Errorf("unkown creds type") + return "", fmt.Errorf("unknown creds type") } From 7ef5de8fa103f89e70085f193a6573354037b87b Mon Sep 17 00:00:00 2001 From: Christopher Bentkowski Date: Fri, 25 Oct 2024 21:18:54 -0500 Subject: [PATCH 2/7] Updated GetCredsType to detect JSON Username/Password. Added function GetJSONSecret to parse JSON Username/Password. --- lambda/utils.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lambda/utils.go b/lambda/utils.go index 461c3807..81aa45bc 100644 --- a/lambda/utils.go +++ b/lambda/utils.go @@ -154,9 +154,18 @@ const ( SECRET_ARN = "SECRET_ARN" SECRET_NAME = "SECRET_NAME" SECRET_TEXT = "SECRET_TEXT" + SECRET_JSON = "SECRET_JSON" ) func GetCredsType(s string) string { + var jsonData map[string]interface{} + if err := json.Unmarshal([]byte(s), &jsonData); err == nil { + if _, hasUsername := jsonData["username"]; hasUsername { + if _, hasPassword := jsonData["password"]; hasPassword { + return SECRET_JSON + } + } + } if strings.HasPrefix(s, "arn:aws") { return SECRET_ARN } else if strings.Contains(s, ":") { @@ -184,3 +193,19 @@ func GetSecret(secretId string) (secret string, err error) { } return *resp.SecretString, nil } + +func GetJSONSecret(secretJson string) (secret string, err error) { + var jsonData map[string]interface{} + if err := json.Unmarshal([]byte(secretJson), &jsonData); err != nil { + return "", fmt.Errorf("json unmarshal error: %v", err.Error()) + } + username, ok := jsonData["username"].(string) + if !ok { + return "", fmt.Errorf("json username error") + } + password, ok := jsonData["password"].(string) + if !ok { + return "", fmt.Errorf("json password error") + } + return fmt.Sprintf("%s:%s", username, password), nil +} From 4a7f182d439c25cda8ee5449cad45e218a543f5d Mon Sep 17 00:00:00 2001 From: Christopher Bentkowski Date: Fri, 25 Oct 2024 21:19:31 -0500 Subject: [PATCH 3/7] Added new asserstion to test JSON Username/Password --- lambda/utils_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lambda/utils_test.go b/lambda/utils_test.go index 4f93a37d..131ee670 100644 --- a/lambda/utils_test.go +++ b/lambda/utils_test.go @@ -30,4 +30,5 @@ func TestGetCredsType(t *testing.T) { assert.Equal(t, SECRET_NAME, GetCredsType("fake-secret")) assert.Equal(t, SECRET_TEXT, GetCredsType("username:password")) assert.Equal(t, SECRET_NAME, GetCredsType("")) + assert.Equal(t, SECRET_JSON, GetCredsType("{ \"username\" : \"privateRegistryUsername\", \"password\" : \"privateRegistryPassword\" }")) } From 0459b6abe369c482628acbeb860ff12c9ef968a6 Mon Sep 17 00:00:00 2001 From: Christopher Bentkowski Date: Wed, 30 Oct 2024 05:01:24 -0500 Subject: [PATCH 4/7] Added documentation about parsing JSON string secrets --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index 9ab65116..1dcdceb3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -106,6 +106,7 @@ export interface IImageName { /** * The credentials of the docker image. Format `user:password` or `AWS Secrets Manager secret arn` or `AWS Secrets Manager secret name` + * Supports JSON format returned from AWS Secrets in the format `{"username":"", "password":""}` */ creds?: string; } From 67e3ab3888ed02ba70175030d8d6e20bd77e20dc Mon Sep 17 00:00:00 2001 From: Christopher Bentkowski Date: Wed, 30 Oct 2024 05:04:56 -0500 Subject: [PATCH 5/7] Added detection for stringified JSON output from secretsmanager and call to parse the JSON --- lambda/main.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lambda/main.go b/lambda/main.go index e003037e..043c6612 100644 --- a/lambda/main.go +++ b/lambda/main.go @@ -159,12 +159,22 @@ func parseCreds(creds string) (string, error) { if creds == "" { return "", nil } else if (credsType == SECRET_ARN) || (credsType == SECRET_NAME) { - secret, err := GetSecret(creds) - return secret, err + secret, isJSON, err := GetSecret(creds) + if err != nil { + return "", err + } + if isJSON { + parsedSecret, err := ParseJSONSecret(secret) + if err != nil { + return "", err + } + return parsedSecret, nil + } + return secret, nil } else if credsType == SECRET_TEXT { return creds, nil } else if credsType == SECRET_JSON { - secret, err := GetJSONSecret(creds) + secret, err := ParseJSONSecret(creds) return secret, err } return "", fmt.Errorf("unknown creds type") From 6b23047f73dbc95fe34bf309cdf1ab1d5945ab2e Mon Sep 17 00:00:00 2001 From: Christopher Bentkowski Date: Wed, 30 Oct 2024 05:05:50 -0500 Subject: [PATCH 6/7] Added JSON detection for GetSecret for additional JSON parsing if needed --- lambda/utils.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lambda/utils.go b/lambda/utils.go index 81aa45bc..7a365d39 100644 --- a/lambda/utils.go +++ b/lambda/utils.go @@ -175,13 +175,13 @@ func GetCredsType(s string) string { } } -func GetSecret(secretId string) (secret string, err error) { +func GetSecret(secretId string) (secret string, isJSON bool, err error) { cfg, err := config.LoadDefaultConfig( context.TODO(), ) log.Printf("get secret id: %s of region: %s", secretId, cfg.Region) if err != nil { - return "", fmt.Errorf("api client configuration error: %v", err.Error()) + return "", false, fmt.Errorf("api client configuration error: %v", err.Error()) } client := secretsmanager.NewFromConfig(cfg) @@ -189,12 +189,20 @@ func GetSecret(secretId string) (secret string, err error) { SecretId: aws.String(secretId), }) if err != nil { - return "", fmt.Errorf("fetch secret value error: %v", err.Error()) + return "", false, fmt.Errorf("fetch secret value error: %v", err.Error()) } - return *resp.SecretString, nil + + secretString := *resp.SecretString + + var jsonData map[string]interface{} + if err := json.Unmarshal([]byte(secretString), &jsonData); err == nil { + return secretString, true, nil + } + + return secretString, false, nil } -func GetJSONSecret(secretJson string) (secret string, err error) { +func ParseJSONSecret(secretJson string) (secret string, err error) { var jsonData map[string]interface{} if err := json.Unmarshal([]byte(secretJson), &jsonData); err != nil { return "", fmt.Errorf("json unmarshal error: %v", err.Error()) From 23681f7a69f768b8931d44c8016bfefbb17ac84b Mon Sep 17 00:00:00 2001 From: Christopher Bentkowski Date: Wed, 30 Oct 2024 05:14:42 -0500 Subject: [PATCH 7/7] Beginnings of testing ParseCreds --- lambda/main_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/lambda/main_test.go b/lambda/main_test.go index a28b323f..f91abdc5 100644 --- a/lambda/main_test.go +++ b/lambda/main_test.go @@ -53,3 +53,53 @@ func TestMain(t *testing.T) { }) assert.NoError(t, err) } +func TestParseCreds(t *testing.T) { + tests := []struct { + name string + creds string + want string + wantErr bool + }{ + { + name: "Empty creds", + creds: "", + want: "", + wantErr: false, + }, + // { + // name: "Secret ARN", + // creds: "arn:aws:secretsmanager:us-west-2:00000:secret:fake-secret", + // want: "{\"username\":\"privateRegistryUsername\",\"password\":\"privateRegistryPassword\"}", + // wantErr: false, + // }, + { + name: "Secret JSON", + creds: "{ \"username\" : \"privateRegistryUsername\", \"password\" : \"privateRegistryPassword\" }", + want: "privateRegistryUsername:privateRegistryPassword", + wantErr: false, + }, + { + name: "Secret Text", + creds: "username:password", + want: "username:password", + wantErr: false, + }, + { + name: "Unknown creds type", + creds: "unknown-creds", + want: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseCreds(tt.creds) + if (err != nil) != tt.wantErr { + t.Errorf("parseCreds() error = %v, wantErr %v", err, tt.wantErr) + return + } + assert.Equal(t, tt.want, got) + }) + } +}