From fe02e5e2c31b50f8b3ce10964b3e702bf9a7ef13 Mon Sep 17 00:00:00 2001 From: Shingo Omura Date: Fri, 24 Aug 2018 23:23:34 +0900 Subject: [PATCH] support to pull base images from insecure registries. --- README.md | 4 ++++ cmd/executor/cmd/root.go | 2 +- pkg/executor/build.go | 2 +- pkg/util/image_util.go | 40 +++++++++++++++++++++++++++++++++---- pkg/util/image_util_test.go | 8 ++++---- 5 files changed, 46 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6b20567a9e..1787c2f487 100644 --- a/README.md +++ b/README.md @@ -283,6 +283,10 @@ Set this flag to indicate which build stage is the target build stage. Set this flag if you only want to build the image, without pushing to a registry. +### --insecure-skip-tls-verify + +Pull or Push to insecure registry ignoring TLS verify + ### Debug Image The kaniko executor image is based off of scratch and doesn't contain a shell. diff --git a/cmd/executor/cmd/root.go b/cmd/executor/cmd/root.go index c05c21b673..467c8cce5d 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -85,7 +85,7 @@ func addKanikoOptionsFlags(cmd *cobra.Command) { RootCmd.PersistentFlags().VarP(&opts.Destinations, "destination", "d", "Registry the final image should be pushed to. Set it repeatedly for multiple destinations.") RootCmd.PersistentFlags().StringVarP(&opts.SnapshotMode, "snapshotMode", "", "full", "Change the file attributes inspected during snapshotting") RootCmd.PersistentFlags().VarP(&opts.BuildArgs, "build-arg", "", "This flag allows you to pass in ARG values at build time. Set it repeatedly for multiple values.") - RootCmd.PersistentFlags().BoolVarP(&opts.DockerInsecureSkipTLSVerify, "insecure-skip-tls-verify", "", false, "Push to insecure registry ignoring TLS verify") + RootCmd.PersistentFlags().BoolVarP(&opts.DockerInsecureSkipTLSVerify, "insecure-skip-tls-verify", "", false, "Pull or Push to insecure registry ignoring TLS verify") RootCmd.PersistentFlags().StringVarP(&opts.TarPath, "tarPath", "", "", "Path to save the image in as a tarball instead of pushing") RootCmd.PersistentFlags().BoolVarP(&opts.SingleSnapshot, "single-snapshot", "", false, "Take a single snapshot at the end of the build.") RootCmd.PersistentFlags().BoolVarP(&opts.Reproducible, "reproducible", "", false, "Strip timestamps out of the image to make it reproducible") diff --git a/pkg/executor/build.go b/pkg/executor/build.go index a3f958e62e..05564d6144 100644 --- a/pkg/executor/build.go +++ b/pkg/executor/build.go @@ -54,7 +54,7 @@ func DoBuild(opts *options.KanikoOptions) (v1.Image, error) { for index, stage := range stages { finalStage := finalStage(index, opts.Target, stages) // Unpack file system to root - sourceImage, err := util.RetrieveSourceImage(index, opts.BuildArgs, stages) + sourceImage, err := util.RetrieveSourceImage(index, opts.BuildArgs, opts.DockerInsecureSkipTLSVerify, stages) if err != nil { return nil, err } diff --git a/pkg/util/image_util.go b/pkg/util/image_util.go index 0dd066d55f..d1f43de9fd 100644 --- a/pkg/util/image_util.go +++ b/pkg/util/image_util.go @@ -17,6 +17,8 @@ limitations under the License. package util import ( + "fmt" + "net/http" "path/filepath" "strconv" @@ -40,7 +42,7 @@ var ( ) // RetrieveSourceImage returns the base image of the stage at index -func RetrieveSourceImage(index int, buildArgs []string, stages []instructions.Stage) (v1.Image, error) { +func RetrieveSourceImage(index int, buildArgs []string, dockerInsecureSkipTLSVerify bool, stages []instructions.Stage) (v1.Image, error) { currentStage := stages[index] currentBaseName, err := ResolveEnvironmentReplacement(currentStage.BaseName, buildArgs, false) if err != nil { @@ -62,7 +64,7 @@ func RetrieveSourceImage(index int, buildArgs []string, stages []instructions.St } } // Otherwise, initialize image as usual - return retrieveRemoteImage(currentBaseName) + return retrieveRemoteImage(currentBaseName, dockerInsecureSkipTLSVerify) } // RetrieveConfigFile returns the config file for an image @@ -83,16 +85,46 @@ func tarballImage(index int) (v1.Image, error) { return tarball.ImageFromPath(tarPath, nil) } -func remoteImage(image string) (v1.Image, error) { +func remoteImage(image string, dockerInsecureSkipTLSVerify bool) (v1.Image, error) { logrus.Infof("Downloading base image %s", image) ref, err := name.ParseReference(image, name.WeakValidation) if err != nil { return nil, err } + + // check we can connect to connect regitry with normal transport + tr := http.DefaultTransport.(*http.Transport) + client := http.Client{Transport: tr} + _, err = client.Get(fmt.Sprintf("%s://%s/v2/", ref.Context().Scheme(), ref.Context().Registry.Name())) + + // when failure and dockerInsecureSkipTLSVerify is true, + // make registry and transport be insecure. + if err != nil && dockerInsecureSkipTLSVerify { + // make registry scheme be insecure. + insecureReg, err := name.NewInsecureRegistry(ref.Context().RegistryStr(), name.WeakValidation) + if err != nil { + return nil, err + } + if tag, ok := ref.(name.Tag); ok { + tag.Repository.Registry = insecureReg + ref = tag + } + if digest, ok := ref.(name.Digest); ok { + digest.Repository.Registry = insecureReg + ref = digest + } + // try to connect insecure registry with insecure transport + tr.TLSClientConfig.InsecureSkipVerify = true + _, err = client.Get(fmt.Sprintf("%s://%s/v2/", ref.Context().Scheme(), ref.Context().Registry.Name())) + if err != nil { + return nil, err + } + } + k8sc, err := k8schain.NewNoClient() if err != nil { return nil, err } kc := authn.NewMultiKeychain(authn.DefaultKeychain, k8sc) - return remote.Image(ref, remote.WithAuthFromKeychain(kc)) + return remote.Image(ref, remote.WithTransport(tr), remote.WithAuthFromKeychain(kc)) } diff --git a/pkg/util/image_util_test.go b/pkg/util/image_util_test.go index 419576d927..f0b5339198 100644 --- a/pkg/util/image_util_test.go +++ b/pkg/util/image_util_test.go @@ -50,11 +50,11 @@ func Test_StandardImage(t *testing.T) { defer func() { retrieveRemoteImage = original }() - mock := func(image string) (v1.Image, error) { + mock := func(image string, dockerInsecureSkipTLSVerifyAtPull bool) (v1.Image, error) { return nil, nil } retrieveRemoteImage = mock - actual, err := RetrieveSourceImage(0, nil, stages) + actual, err := RetrieveSourceImage(0, nil, false, stages) testutil.CheckErrorAndDeepEqual(t, false, err, nil, actual) } func Test_ScratchImage(t *testing.T) { @@ -62,7 +62,7 @@ func Test_ScratchImage(t *testing.T) { if err != nil { t.Error(err) } - actual, err := RetrieveSourceImage(1, nil, stages) + actual, err := RetrieveSourceImage(1, nil, false, stages) expected := empty.Image testutil.CheckErrorAndDeepEqual(t, false, err, expected, actual) } @@ -80,7 +80,7 @@ func Test_TarImage(t *testing.T) { return nil, nil } retrieveTarImage = mock - actual, err := RetrieveSourceImage(2, nil, stages) + actual, err := RetrieveSourceImage(2, nil, false, stages) testutil.CheckErrorAndDeepEqual(t, false, err, nil, actual) }