diff --git a/cmd/cnbBuild.go b/cmd/cnbBuild.go index f5d6a3e76a..f294dc4f5c 100644 --- a/cmd/cnbBuild.go +++ b/cmd/cnbBuild.go @@ -529,12 +529,19 @@ func runCnbBuild(config *cnbBuildOptions, telemetry *buildpacks.Telemetry, image } } - cnbRegistryAuth, err := cnbutils.GenerateCnbAuth(config.DockerConfigJSON, utils) + credentials := cnbutils.NewCredentials(utils) + cnbRegistryAuth, err := credentials.GenerateCredentials(config.DockerConfigJSON) if err != nil { log.SetErrorCategory(log.ErrorConfiguration) return errors.Wrap(err, "failed to generate CNB_REGISTRY_AUTH") } + found := credentials.Validate(targetImage.ContainerRegistry.Host) + if !found { + log.SetErrorCategory(log.ErrorConfiguration) + return errors.New(fmt.Sprintf("DockerConfigJSON does not contain credentials for target registry (%s)", targetImage.ContainerRegistry.Host)) + } + if len(config.CustomTLSCertificateLinks) > 0 { caCertificates := "/tmp/ca-certificates.crt" _, err := utils.Copy("/etc/ssl/certs/ca-certificates.crt", caCertificates) diff --git a/cmd/cnbBuild_test.go b/cmd/cnbBuild_test.go index 0fe38a8c7a..b8e88f8b0d 100644 --- a/cmd/cnbBuild_test.go +++ b/cmd/cnbBuild_test.go @@ -125,7 +125,7 @@ func TestRunCnbBuild(t *testing.T) { ` utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) utils.FilesMock.AddFile("project.toml", []byte(projectToml)) addBuilderFiles(&utils) @@ -133,7 +133,7 @@ func TestRunCnbBuild(t *testing.T) { require.NoError(t, err) runner := utils.ExecMockRunner - assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"some-registry\":\"Basic dXNlcjpwYXNz\"}") assertLifecycleCalls(t, runner, 2) assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", imageRegistry, config.ContainerImageName, config.ContainerImageTag)) assert.Contains(t, runner.Calls[1].Params, "-run-image") @@ -160,7 +160,7 @@ func TestRunCnbBuild(t *testing.T) { ` utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) utils.FilesMock.AddFile("project.toml", []byte(projectToml)) addBuilderFiles(&utils) @@ -169,7 +169,7 @@ func TestRunCnbBuild(t *testing.T) { require.NoError(t, err) runner := utils.ExecMockRunner - assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"some-registry\":\"Basic dXNlcjpwYXNz\"}") assertLifecycleCalls(t, runner, 2) assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", imageRegistry, "io-buildpacks-my-app", config.ContainerImageTag)) assert.Equal(t, config.ContainerRegistryURL, commonPipelineEnvironment.container.registryURL) @@ -190,14 +190,14 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &commonPipelineEnvironment, &piperhttp.Client{}) require.NoError(t, err) runner := utils.ExecMockRunner - assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"some-registry\":\"Basic dXNlcjpwYXNz\"}") assertLifecycleCalls(t, runner, 2) assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", imageRegistry, config.ContainerImageName, config.ContainerImageTag)) assert.Equal(t, config.ContainerRegistryURL, commonPipelineEnvironment.container.registryURL) @@ -215,14 +215,14 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &commonPipelineEnvironment, &piperhttp.Client{}) require.NoError(t, err) runner := utils.ExecMockRunner - assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"some-registry\":\"Basic dXNlcjpwYXNz\"}") assertLifecycleCalls(t, runner, 2) assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag)) assert.Equal(t, fmt.Sprintf("https://%s", config.ContainerRegistryURL), commonPipelineEnvironment.container.registryURL) @@ -245,14 +245,14 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{}) require.NoError(t, err) runner := utils.ExecMockRunner - assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"some-registry\":\"Basic dXNlcjpwYXNz\"}") assert.Equal(t, creatorPath, runner.Calls[1].Exec) assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks") assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks/order.toml") @@ -283,14 +283,14 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{}) require.NoError(t, err) runner := utils.ExecMockRunner - assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"some-registry\":\"Basic dXNlcjpwYXNz\"}") assert.Equal(t, creatorPath, runner.Calls[1].Exec) assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks") assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks/order.toml") @@ -319,14 +319,14 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{}) require.NoError(t, err) runner := utils.ExecMockRunner - assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"some-registry\":\"Basic dXNlcjpwYXNz\"}") assert.Equal(t, creatorPath, runner.Calls[1].Exec) assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks") assert.Contains(t, runner.Calls[1].Params, "/tmp/buildpacks/order.toml") @@ -358,7 +358,7 @@ func TestRunCnbBuild(t *testing.T) { utils := newCnbBuildTestsUtils() utils.FilesMock.AddFile(caCertsFile, []byte("test\n")) - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, client) @@ -370,7 +370,7 @@ func TestRunCnbBuild(t *testing.T) { require.NoError(t, err) runner := utils.ExecMockRunner - assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"some-registry\":\"Basic dXNlcjpwYXNz\"}") assert.Contains(t, runner.Env, fmt.Sprintf("SSL_CERT_FILE=%s", caCertsTmpFile)) assertLifecycleCalls(t, runner, 2) assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag)) @@ -387,7 +387,7 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{}) @@ -412,6 +412,7 @@ func TestRunCnbBuild(t *testing.T) { "OPTIONS_KEY": "OPTIONS_VALUE", "OVERWRITE": "this should win", }, + DockerConfigJSON: "/path/to/config.json", } projectToml := `[project] @@ -427,6 +428,7 @@ func TestRunCnbBuild(t *testing.T) { ` utils := newCnbBuildTestsUtils() + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) utils.FilesMock.AddFile("project.toml", []byte(projectToml)) addBuilderFiles(&utils) @@ -453,7 +455,7 @@ func TestRunCnbBuild(t *testing.T) { utils := newCnbBuildTestsUtils() utils.FilesMock.CurrentDir = "/jenkins" utils.FilesMock.AddDir("/jenkins") - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) utils.FilesMock.AddFile("/workspace/pom.xml", []byte("test")) addBuilderFiles(&utils) @@ -478,7 +480,7 @@ func TestRunCnbBuild(t *testing.T) { utils := newCnbBuildTestsUtils() utils.FilesMock.CurrentDir = "/jenkins" utils.FilesMock.AddDir("/jenkins") - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{}) @@ -500,13 +502,30 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":"dXNlcjpwYXNz"}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":"dXNlcjpwYXNz"}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{}) assert.EqualError(t, err, "failed to generate CNB_REGISTRY_AUTH: json: cannot unmarshal string into Go struct field ConfigFile.auths of type types.AuthConfig") }) + t.Run("error case: missing target registry in docker credentials", func(t *testing.T) { + t.Parallel() + config := cnbBuildOptions{ + ContainerImageTag: "0.0.1", + ContainerRegistryURL: imageRegistry, + ContainerImageName: "my-image", + DockerConfigJSON: "/path/to/config.json", + } + + utils := newCnbBuildTestsUtils() + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-other-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + addBuilderFiles(&utils) + + err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{}) + assert.EqualError(t, err, "DockerConfigJSON does not contain credentials for target registry (some-registry)") + }) + t.Run("error case: DockerConfigJSON file not there (config.json)", func(t *testing.T) { t.Parallel() config := cnbBuildOptions{ @@ -561,7 +580,7 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{}) @@ -583,9 +602,26 @@ func TestRunCnbBuild(t *testing.T) { "runImage": "bar", }, }, + DockerConfigJSON: "/path/to/config.json", } utils := newCnbBuildTestsUtils() + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddDir("target") + utils.FilesMock.AddFile("target/project.toml", []byte(`[project] +id = "test" +name = "test" +version = "1.0.0" + +[build] +include = [] +exclude = ["*.tar"] + +[[build.buildpacks]] +uri = "some-buildpack"`)) + utils.FilesMock.AddFile("a_file", []byte(`{}`)) + utils.FilesMock.AddFile("target/somelib.jar", []byte(`FFFFFF`)) + addBuilderFiles(&utils) telemetryData := &telemetry.CustomData{} @@ -610,7 +646,7 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) utils.FilesMock.AddDir("target") utils.FilesMock.AddFile("target/app.jar", []byte(`FFFFFF`)) utils.FilesMock.AddFile("target/app-src.jar", []byte(`FFFFFF`)) @@ -637,7 +673,7 @@ func TestRunCnbBuild(t *testing.T) { } utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) utils.FilesMock.AddDir("target") utils.FilesMock.AddFile("target/app.jar", []byte(`FFFFFF`)) @@ -648,7 +684,7 @@ func TestRunCnbBuild(t *testing.T) { require.NoError(t, err) runner := utils.ExecMockRunner - assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"some-registry\":\"Basic dXNlcjpwYXNz\"}") assert.Contains(t, runner.Calls[1].Params, fmt.Sprintf("%s/%s:%s", imageRegistry, config.ContainerImageName, config.ContainerImageTag)) assert.Equal(t, config.ContainerRegistryURL, commonPipelineEnvironment.container.registryURL) assert.Equal(t, "my-image:3.1.5", commonPipelineEnvironment.container.imageNameTag) @@ -668,7 +704,7 @@ func TestRunCnbBuild(t *testing.T) { expectedImageCount := len(config.MultipleImages) utils := newCnbBuildTestsUtils() - utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"some-registry":{"auth":"dXNlcjpwYXNz"}}}`)) addBuilderFiles(&utils) telemetryData := &telemetry.CustomData{} diff --git a/pkg/cnbutils/auth.go b/pkg/cnbutils/auth.go index 98a5b58b3b..eaafa799bb 100644 --- a/pkg/cnbutils/auth.go +++ b/pkg/cnbutils/auth.go @@ -4,30 +4,66 @@ import ( "encoding/base64" "encoding/json" "fmt" + "strings" "github.com/SAP/jenkins-library/pkg/log" "github.com/docker/cli/cli/config/configfile" ) -func GenerateCnbAuth(config string, utils BuildUtils) (string, error) { +type Credentials struct { + utils BuildUtils + dockerConfig *configfile.ConfigFile +} + +func NewCredentials(utils BuildUtils) Credentials { + return Credentials{ + utils: utils, + dockerConfig: nil, + } +} + +func (c *Credentials) GenerateCredentials(config string) (string, error) { var err error + c.dockerConfig, err = c.parse(config) + if err != nil { + return "", err + } + + return c.generate() +} + +func (c *Credentials) Validate(target string) bool { + if c.dockerConfig == nil { + return false + } + _, ok := c.dockerConfig.AuthConfigs[target] + if !strings.HasPrefix(target, "localhost") && !ok { + return false + } + return true +} + +func (c *Credentials) parse(config string) (*configfile.ConfigFile, error) { dockerConfig := &configfile.ConfigFile{} if config != "" { log.Entry().Debugf("using docker config file %q", config) - dockerConfigJSON, err := utils.FileRead(config) + dockerConfigJSON, err := c.utils.FileRead(config) if err != nil { - return "", err + return &configfile.ConfigFile{}, err } err = json.Unmarshal(dockerConfigJSON, dockerConfig) if err != nil { - return "", err + return &configfile.ConfigFile{}, err } } + return dockerConfig, nil +} +func (c *Credentials) generate() (string, error) { auth := map[string]string{} - for registry, value := range dockerConfig.AuthConfigs { + for registry, value := range c.dockerConfig.AuthConfigs { if value.Auth == "" && value.Username == "" && value.Password == "" { log.Entry().Warnf("docker config.json contains empty credentials for registry %q. Either 'auth' or 'username' and 'password' have to be provided.", registry) continue diff --git a/pkg/cnbutils/auth_test.go b/pkg/cnbutils/auth_test.go index 24ed900d03..086e74eacf 100644 --- a/pkg/cnbutils/auth_test.go +++ b/pkg/cnbutils/auth_test.go @@ -18,42 +18,74 @@ func TestGenerateCnbAuth(t *testing.T) { } t.Run("successfully generates cnb auth env variable", func(t *testing.T) { - mockUtils.AddFile("/test/valid_config.json", []byte("{\"auths\":{\"example.com\":{\"auth\":\"dXNlcm5hbWU6cGFzc3dvcmQ=\"}}}")) - auth, err := cnbutils.GenerateCnbAuth("/test/valid_config.json", mockUtils) + mockUtils.AddFile("/test/valid_config.json", []byte(`{"auths":{"example.com":{"auth":"dXNlcm5hbWU6cGFzc3dvcmQ="}}}`)) + credentials := cnbutils.NewCredentials(mockUtils) + auth, err := credentials.GenerateCredentials("/test/valid_config.json") assert.NoError(t, err) - assert.Equal(t, "{\"example.com\":\"Basic dXNlcm5hbWU6cGFzc3dvcmQ=\"}", auth) + assert.Equal(t, `{"example.com":"Basic dXNlcm5hbWU6cGFzc3dvcmQ="}`, auth) }) t.Run("successfully generates cnb auth env variable from username and password", func(t *testing.T) { - mockUtils.AddFile("/test/valid_config.json", []byte("{\"auths\":{\"example.com\":{\"username\":\"username\",\"password\":\"password\"}}}")) - auth, err := cnbutils.GenerateCnbAuth("/test/valid_config.json", mockUtils) + mockUtils.AddFile("/test/valid_config.json", []byte(`{"auths":{"example.com":{"username":"username","password":"password"}}}`)) + credentials := cnbutils.NewCredentials(mockUtils) + auth, err := credentials.GenerateCredentials("/test/valid_config.json") assert.NoError(t, err) - assert.Equal(t, "{\"example.com\":\"Basic dXNlcm5hbWU6cGFzc3dvcmQ=\"}", auth) + assert.Equal(t, `{"example.com":"Basic dXNlcm5hbWU6cGFzc3dvcmQ="}`, auth) }) t.Run("skips registry with empty credentials", func(t *testing.T) { - mockUtils.AddFile("/test/valid_config.json", []byte("{\"auths\":{\"example.com\":{}}}")) - auth, err := cnbutils.GenerateCnbAuth("/test/valid_config.json", mockUtils) + mockUtils.AddFile("/test/valid_config.json", []byte(`{"auths":{"example.com":{}}}`)) + credentials := cnbutils.NewCredentials(mockUtils) + auth, err := credentials.GenerateCredentials("/test/valid_config.json") assert.NoError(t, err) assert.Equal(t, "{}", auth) }) t.Run("successfully generates cnb auth env variable if docker config is not present", func(t *testing.T) { - auth, err := cnbutils.GenerateCnbAuth("", mockUtils) + credentials := cnbutils.NewCredentials(mockUtils) + auth, err := credentials.GenerateCredentials("") assert.NoError(t, err) assert.Equal(t, "{}", auth) }) t.Run("fails if file not found", func(t *testing.T) { - _, err := cnbutils.GenerateCnbAuth("/not/found", mockUtils) + credentials := cnbutils.NewCredentials(mockUtils) + _, err := credentials.GenerateCredentials("/not/found") assert.Error(t, err) assert.Equal(t, "could not read '/not/found'", err.Error()) }) t.Run("fails if file is invalid json", func(t *testing.T) { - mockUtils.AddFile("/test/invalid_config.json", []byte("not a json")) - _, err := cnbutils.GenerateCnbAuth("/test/invalid_config.json", mockUtils) + mockUtils.AddFile("/test/invalid_config.json", []byte(`not a json`)) + credentials := cnbutils.NewCredentials(mockUtils) + _, err := credentials.GenerateCredentials("/test/invalid_config.json") assert.Error(t, err) assert.Equal(t, "invalid character 'o' in literal null (expecting 'u')", err.Error()) }) + + t.Run("validate finds present registry", func(t *testing.T) { + mockUtils.AddFile("/test/valid_config.json", []byte(`{"auths":{"example.com":{"auth":"dXNlcm5hbWU6cGFzc3dvcmQ="}}}`)) + credentials := cnbutils.NewCredentials(mockUtils) + _, err := credentials.GenerateCredentials("/test/valid_config.json") + assert.NoError(t, err) + assert.True(t, credentials.Validate("example.com")) + assert.False(t, credentials.Validate("missing.com")) + + }) + + t.Run("validate handles invalid credentials", func(t *testing.T) { + mockUtils.AddFile("/test/invalid_config.json", []byte(`{"foo":"bar"}`)) + credentials := cnbutils.NewCredentials(mockUtils) + _, err := credentials.GenerateCredentials("/test/invalid_config.json") + assert.NoError(t, err) + assert.False(t, credentials.Validate("example.com")) + }) + + t.Run("validate ignors registry on localhost", func(t *testing.T) { + mockUtils.AddFile("/test/valid_config.json", []byte(`{"auths":{}}`)) + credentials := cnbutils.NewCredentials(mockUtils) + _, err := credentials.GenerateCredentials("/test/valid_config.json") + assert.NoError(t, err) + assert.True(t, credentials.Validate("localhost:5000")) + }) }