mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-08-27 00:37:20 +00:00
Gerard/sc 106216/b registry image collector (#1570)
* update registry auth with username and password * add unit test
This commit is contained in:
+21
-3
@@ -21,6 +21,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
type RegistryImage struct {
|
||||
@@ -97,6 +98,7 @@ func imageExists(namespace string, clientConfig *rest.Config, registryCollector
|
||||
|
||||
authConfig, err := getImageAuthConfig(namespace, clientConfig, registryCollector, imageRef)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to get auth config: %v", err)
|
||||
return false, errors.Wrap(err, "failed to get auth config")
|
||||
}
|
||||
|
||||
@@ -115,10 +117,13 @@ func imageExists(namespace string, clientConfig *rest.Config, registryCollector
|
||||
|
||||
remoteImage, err := imageRef.NewImage(context.Background(), &sysCtx)
|
||||
if err == nil {
|
||||
klog.Infof("image %s exists", image)
|
||||
remoteImage.Close()
|
||||
return true, nil
|
||||
}
|
||||
|
||||
klog.Errorf("failed to get image %s: %v", image, err)
|
||||
|
||||
if strings.Contains(err.Error(), "no image found in manifest list for architecture") {
|
||||
// manifest was downloaded, but no matching architecture found in manifest
|
||||
// should this count as image does not exist?
|
||||
@@ -188,7 +193,9 @@ func getImageAuthConfigFromData(imageRef types.ImageReference, pullSecrets *v1be
|
||||
|
||||
dockerCfgJSON := struct {
|
||||
Auths map[string]struct {
|
||||
Auth []byte `json:"auth"`
|
||||
Auth string `json:"auth"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
} `json:"auths"`
|
||||
}{}
|
||||
|
||||
@@ -203,14 +210,25 @@ func getImageAuthConfigFromData(imageRef types.ImageReference, pullSecrets *v1be
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// gcr.io auth uses username and password, e.g. username: _json_key, password: <sa_key>
|
||||
if auth.Username != "" && auth.Password != "" {
|
||||
return ®istryAuthConfig{
|
||||
username: auth.Username,
|
||||
password: auth.Password,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// docker.io auth uses auth, e.g. auth: <base64_encoded_username_password>
|
||||
// username and password can't contain colon
|
||||
// at least according to https://github.com/docker/cli/blob/v27.0.3/cli/config/configfile/file.go#L247
|
||||
parts := strings.Split(string(auth.Auth), ":")
|
||||
if len(parts) != 2 {
|
||||
return nil, errors.Errorf("expected 2 parts in the string, but found %d", len(parts))
|
||||
return nil, errors.Errorf("expected 2 parts in the auth string, but found %d", len(parts))
|
||||
}
|
||||
|
||||
authConfig := registryAuthConfig{
|
||||
username: parts[0],
|
||||
password: parts[1],
|
||||
password: strings.Trim(parts[1], "\x00"),
|
||||
}
|
||||
|
||||
return &authConfig, nil
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package collect
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetImageAuthConfigFromData(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
imageName string
|
||||
dockerConfigJSON string
|
||||
expectedUsername string
|
||||
expectedPassword string
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "docker.io auth",
|
||||
imageName: "docker.io/myimage",
|
||||
dockerConfigJSON: `{"auths":{"docker.io":{"auth":"username:password"}}}`,
|
||||
expectedUsername: "username",
|
||||
expectedPassword: "password",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "docker.io auth multi colon",
|
||||
imageName: "docker.io/myimage",
|
||||
dockerConfigJSON: `{"auths":{"docker.io":{"auth":"user:name:pass:word"}}}`,
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "gcr.io auth",
|
||||
imageName: "gcr.io/myimage",
|
||||
dockerConfigJSON: `{"auths":{"gcr.io":{"username":"_json_key","password":"sa-key"}}}`,
|
||||
expectedUsername: "_json_key",
|
||||
expectedPassword: "sa-key",
|
||||
expectedError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
imageRef, err := alltransports.ParseImageName(fmt.Sprintf("docker://%s", test.imageName))
|
||||
assert.NoError(t, err)
|
||||
|
||||
pullSecrets := &v1beta2.ImagePullSecrets{
|
||||
SecretType: "kubernetes.io/dockerconfigjson",
|
||||
Data: map[string]string{
|
||||
".dockerconfigjson": base64.StdEncoding.EncodeToString([]byte(test.dockerConfigJSON)),
|
||||
},
|
||||
}
|
||||
|
||||
authConfig, err := getImageAuthConfigFromData(imageRef, pullSecrets)
|
||||
if test.expectedError {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, authConfig)
|
||||
assert.Equal(t, test.expectedUsername, authConfig.username)
|
||||
assert.Equal(t, test.expectedPassword, authConfig.password)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user