From 338a7c2213f897a452eadbcaee840776d5b64779 Mon Sep 17 00:00:00 2001 From: Robbie Zhang Date: Wed, 28 Nov 2018 11:33:07 -0800 Subject: [PATCH] [ACI] Fallback to parse authConfig.Auth when Username field is not specified (#421) * Fallback to parse authConfig.Auth when Username field is not specified --- providers/azure/aci.go | 59 +++++++++++++++++++++++++-------- providers/azure/aci_test.go | 66 +++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 13 deletions(-) diff --git a/providers/azure/aci.go b/providers/azure/aci.go index f5f693d1e..c6b3a9c8c 100644 --- a/providers/azure/aci.go +++ b/providers/azure/aci.go @@ -997,6 +997,38 @@ func (p *ACIProvider) getImagePullSecrets(pod *v1.Pod) ([]aci.ImageRegistryCrede return ips, nil } +func makeRegistryCredential(server string, authConfig AuthConfig) (*aci.ImageRegistryCredential, error) { + username := authConfig.Username + password := authConfig.Password + + if username == "" { + if authConfig.Auth == "" { + return nil, fmt.Errorf("no username present in auth config for server: %s", server) + } + + decoded, err := base64.StdEncoding.DecodeString(authConfig.Auth) + if err != nil { + return nil, fmt.Errorf("error decoding the auth for server: %s Error: %v", server, err) + } + + parts := strings.Split(string(decoded), ":") + if len(parts) != 2 { + return nil, fmt.Errorf("malformed auth for server: %s", server) + } + + username = parts[0] + password = parts[1] + } + + cred := aci.ImageRegistryCredential{ + Server: server, + Username: username, + Password: password, + } + + return &cred, nil +} + func readDockerCfgSecret(secret *v1.Secret, ips []aci.ImageRegistryCredential) ([]aci.ImageRegistryCredential, error) { var err error var authConfigs map[string]AuthConfig @@ -1011,12 +1043,13 @@ func readDockerCfgSecret(secret *v1.Secret, ips []aci.ImageRegistryCredential) ( return ips, err } - for server, authConfig := range authConfigs { - ips = append(ips, aci.ImageRegistryCredential{ - Password: authConfig.Password, - Server: server, - Username: authConfig.Username, - }) + for server := range authConfigs { + cred, err := makeRegistryCredential(server, authConfigs[server]) + if err != nil { + return ips, err + } + + ips = append(ips, *cred) } return ips, err @@ -1038,17 +1071,17 @@ func readDockerConfigJSONSecret(secret *v1.Secret, ips []aci.ImageRegistryCreden } auths, ok := authConfigs["auths"] - if !ok { return ips, fmt.Errorf("malformed dockerconfigjson in secret") } - for server, authConfig := range auths { - ips = append(ips, aci.ImageRegistryCredential{ - Password: authConfig.Password, - Server: server, - Username: authConfig.Username, - }) + for server := range auths { + cred, err := makeRegistryCredential(server, auths[server]) + if err != nil { + return ips, err + } + + ips = append(ips, *cred) } return ips, err diff --git a/providers/azure/aci_test.go b/providers/azure/aci_test.go index 13f354ee6..f39436d6d 100644 --- a/providers/azure/aci_test.go +++ b/providers/azure/aci_test.go @@ -7,11 +7,13 @@ package azure import ( "bytes" "context" + "encoding/base64" "encoding/json" "fmt" "io/ioutil" "net/http" "os" + "strings" "testing" "github.com/google/uuid" @@ -35,6 +37,70 @@ const ( fakeNodeName = "vk" ) +// Test make registry credential +func TestMakeRegistryCredential(t *testing.T) { + server := "server-" + uuid.New().String() + username := "user-" + uuid.New().String() + password := "pass-" + uuid.New().String() + auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) + + tt := []struct { + name string + authConfig AuthConfig + shouldFail bool + failMessage string + }{ + { + "Valid username and password", + AuthConfig{Username: username, Password: password}, + false, + "", + }, + { + "Username and password in auth", + AuthConfig{Auth: auth}, + false, + "", + }, + { + "No Username", + AuthConfig{}, + true, + "no username present in auth config for server", + }, + { + "Invalid Auth", + AuthConfig{Auth: "123"}, + true, + "error decoding the auth for server", + }, + { + "Malformed Auth", + AuthConfig{Auth: base64.StdEncoding.EncodeToString([]byte("123"))}, + true, + "malformed auth for server", + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + cred, err := makeRegistryCredential(server, tc.authConfig) + + if tc.shouldFail { + assert.NotNil(t, err, "convertion should fail") + assert.True(t, strings.Contains(err.Error(), tc.failMessage), "failed message is not expected") + return + } + + assert.Nil(t, err, "convertion should not fail") + assert.NotNil(t, cred, "credential should not be nil") + assert.Equal(t, server, cred.Server, "server doesn't match") + assert.Equal(t, username, cred.Username, "username doesn't match") + assert.Equal(t, password, cred.Password, "password doesn't match") + }) + } +} + // Tests create pod without resource spec func TestCreatePodWithoutResourceSpec(t *testing.T) { _, aciServerMocker, provider, err := prepareMocks()