From 4f5efc88d74caa8e768d136a9042760c85c69052 Mon Sep 17 00:00:00 2001 From: Pavel Busko Date: Fri, 1 Oct 2021 10:05:15 +0200 Subject: [PATCH] cnbBuild: use DockerCredentials secret during custom buildpacks download (#3138) --- cmd/cnbBuild.go | 31 +++++++++++++++++++++++++++---- cmd/cnbBuild_test.go | 22 ++++++++++++++++++---- pkg/cnbutils/buildpack.go | 8 +++++++- pkg/cnbutils/buildpack_test.go | 2 +- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/cmd/cnbBuild.go b/cmd/cnbBuild.go index bf2d132b8..7f1d0b3ad 100644 --- a/cmd/cnbBuild.go +++ b/cmd/cnbBuild.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path" + "path/filepath" "regexp" "strings" @@ -31,10 +32,10 @@ type cnbBuildUtilsBundle struct { *docker.Client } -func setCustomBuildpacks(bpacks []string, utils cnbutils.BuildUtils) (string, string, error) { +func setCustomBuildpacks(bpacks []string, dockerCreds string, utils cnbutils.BuildUtils) (string, string, error) { buildpacksPath := "/tmp/buildpacks" orderPath := "/tmp/buildpacks/order.toml" - newOrder, err := cnbutils.DownloadBuildpacks(buildpacksPath, bpacks, utils) + newOrder, err := cnbutils.DownloadBuildpacks(buildpacksPath, bpacks, dockerCreds, utils) if err != nil { return "", "", err } @@ -153,6 +154,22 @@ func copyFile(source, target string, utils cnbutils.BuildUtils) error { return nil } +func prepareDockerConfig(source string, utils cnbutils.BuildUtils) (string, error) { + if filepath.Base(source) != "config.json" { + log.Entry().Debugf("Renaming docker config file from '%s' to 'config.json'", filepath.Base(source)) + + newPath := filepath.Join(filepath.Dir(source), "config.json") + err := utils.FileRename(source, newPath) + if err != nil { + return "", err + } + + return newPath, nil + } + + return source, nil +} + func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, utils cnbutils.BuildUtils, commonPipelineEnvironment *cnbBuildCommonPipelineEnvironment) error { var err error @@ -178,10 +195,16 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u } } + dockerConfigFile := "" dockerConfig := &configfile.ConfigFile{} dockerConfigJSON := []byte(`{"auths":{}}`) if len(config.DockerConfigJSON) > 0 { - dockerConfigJSON, err = utils.FileRead(config.DockerConfigJSON) + dockerConfigFile, err = prepareDockerConfig(config.DockerConfigJSON, utils) + if err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return errors.Wrapf(err, "failed to rename DockerConfigJSON file '%v'", config.DockerConfigJSON) + } + dockerConfigJSON, err = utils.FileRead(dockerConfigFile) if err != nil { log.SetErrorCategory(log.ErrorConfiguration) return errors.Wrapf(err, "failed to read DockerConfigJSON file '%v'", config.DockerConfigJSON) @@ -241,7 +264,7 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u if config.Buildpacks != nil && len(config.Buildpacks) > 0 { log.Entry().Infof("Setting custom buildpacks: '%v'", config.Buildpacks) - buildpacksPath, orderPath, err = setCustomBuildpacks(config.Buildpacks, utils) + buildpacksPath, orderPath, err = setCustomBuildpacks(config.Buildpacks, dockerConfigFile, utils) defer utils.RemoveAll(buildpacksPath) defer utils.RemoveAll(orderPath) if err != nil { diff --git a/cmd/cnbBuild_test.go b/cmd/cnbBuild_test.go index 4b886b921..f7acc88df 100644 --- a/cmd/cnbBuild_test.go +++ b/cmd/cnbBuild_test.go @@ -84,14 +84,14 @@ func TestRunCnbBuild(t *testing.T) { assert.Equal(t, []string{fmt.Sprintf("%s/%s:%s", registry, config.ContainerImageName, config.ContainerImageTag), fmt.Sprintf("%s/%s:latest", registry, config.ContainerImageName)}, runner.Calls[2].Params) }) - t.Run("success case (custom buildpacks and custom env variables)", func(t *testing.T) { + t.Run("success case (custom buildpacks and custom env variables, renaming docker conf file)", func(t *testing.T) { t.Parallel() registry := "some-registry" config := cnbBuildOptions{ ContainerImageName: "my-image", ContainerImageTag: "0.0.1", ContainerRegistryURL: registry, - DockerConfigJSON: "/path/to/config.json", + DockerConfigJSON: "/path/to/test.json", Buildpacks: []string{"test"}, BuildEnvVars: []string{"FOO=BAR"}, } @@ -128,7 +128,21 @@ func TestRunCnbBuild(t *testing.T) { assert.EqualError(t, err, "failed to parse DockerConfigJSON file '/path/to/config.json': json: cannot unmarshal string into Go struct field ConfigFile.auths of type types.AuthConfig") }) - t.Run("error case: DockerConfigJSON file not there", func(t *testing.T) { + t.Run("error case: DockerConfigJSON file not there (config.json)", func(t *testing.T) { + t.Parallel() + config := cnbBuildOptions{ + ContainerImageName: "my-image", + DockerConfigJSON: "not-there/config.json", + } + + utils := newCnbBuildTestsUtils() + addBuilderFiles(&utils) + + err := runCnbBuild(&config, nil, &utils, &commonPipelineEnvironment) + assert.EqualError(t, err, "failed to read DockerConfigJSON file 'not-there/config.json': could not read 'not-there/config.json'") + }) + + t.Run("error case: DockerConfigJSON file not there (not config.json)", func(t *testing.T) { t.Parallel() config := cnbBuildOptions{ ContainerImageName: "my-image", @@ -139,7 +153,7 @@ func TestRunCnbBuild(t *testing.T) { addBuilderFiles(&utils) err := runCnbBuild(&config, nil, &utils, &commonPipelineEnvironment) - assert.EqualError(t, err, "failed to read DockerConfigJSON file 'not-there': could not read 'not-there'") + assert.EqualError(t, err, "failed to rename DockerConfigJSON file 'not-there': renaming file 'not-there' is not supported, since it does not exist, or is not a leaf-entry") }) t.Run("error case: dockerImage is not a valid builder", func(t *testing.T) { diff --git a/pkg/cnbutils/buildpack.go b/pkg/cnbutils/buildpack.go index 4bd8d6463..6416567a9 100644 --- a/pkg/cnbutils/buildpack.go +++ b/pkg/cnbutils/buildpack.go @@ -4,6 +4,7 @@ package cnbutils import ( "encoding/json" "fmt" + "os" "path/filepath" "strings" @@ -25,7 +26,12 @@ type License struct { URI string `json:"uri"` } -func DownloadBuildpacks(path string, bpacks []string, utils BuildUtils) (Order, error) { +func DownloadBuildpacks(path string, bpacks []string, dockerCreds string, utils BuildUtils) (Order, error) { + + if dockerCreds != "" { + os.Setenv("DOCKER_CONFIG", filepath.Dir(dockerCreds)) + } + var order Order for _, bpack := range bpacks { var bpackMeta BuildPackMetadata diff --git a/pkg/cnbutils/buildpack_test.go b/pkg/cnbutils/buildpack_test.go index e307fefa7..f20dfea85 100644 --- a/pkg/cnbutils/buildpack_test.go +++ b/pkg/cnbutils/buildpack_test.go @@ -16,7 +16,7 @@ var mockUtils = MockUtils{ func TestBuildpackDownload(t *testing.T) { t.Run("successfully downloads a buildpack", func(t *testing.T) { mockUtils.AddDir("/tmp/testtest") - _, err := DownloadBuildpacks("/test", []string{"test"}, mockUtils) + _, err := DownloadBuildpacks("/test", []string{"test"}, "/test/config.json", mockUtils) assert.NoError(t, err) assert.True(t, mockUtils.HasRemovedFile("/tmp/testtest"))