diff --git a/README.md b/README.md index 6b20567a9e..de42f91e05 100644 --- a/README.md +++ b/README.md @@ -283,6 +283,14 @@ 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 + +Push to insecure registry ignoring TLS verify + +### --insecure-skip-tls-verify-at-pull + +Pull from insecure registries 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..df44818110 100644 --- a/cmd/executor/cmd/root.go +++ b/cmd/executor/cmd/root.go @@ -86,6 +86,7 @@ func addKanikoOptionsFlags(cmd *cobra.Command) { 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.DockerInsecureSkipTLSVerifyAtPull, "insecure-skip-tls-verify-at-pull", "", false, "Pull from insecure registries 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..9dec88e7ac 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.DockerInsecureSkipTLSVerifyAtPull, stages) if err != nil { return nil, err } diff --git a/pkg/options/options.go b/pkg/options/options.go index 9f9d593547..60883f3a28 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -18,16 +18,17 @@ package options // KanikoOptions are options that are set by command line arguments type KanikoOptions struct { - DockerfilePath string - Destinations multiArg - SrcContext string - SnapshotMode string - Bucket string - DockerInsecureSkipTLSVerify bool - BuildArgs multiArg - TarPath string - SingleSnapshot bool - Reproducible bool - Target string - NoPush bool + DockerfilePath string + Destinations multiArg + SrcContext string + SnapshotMode string + Bucket string + DockerInsecureSkipTLSVerify bool + DockerInsecureSkipTLSVerifyAtPull bool + BuildArgs multiArg + TarPath string + SingleSnapshot bool + Reproducible bool + Target string + NoPush bool } diff --git a/pkg/util/image_util.go b/pkg/util/image_util.go index 0dd066d55f..c03af6658b 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, dockerInsecureSkipTLSVerifyAtPull 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, dockerInsecureSkipTLSVerifyAtPull) } // 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, dockerInsecureSkipTLSVerifyAtPull 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 dockerInsecureSkipTLSVerifyAtPull is true, + // make registry and transport be insecure. + if err != nil && dockerInsecureSkipTLSVerifyAtPull { + // 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) }