Merge pull request #1221 from antechrestos/refactoring/default_transport
Remove direct use of DefaultTransport
This commit is contained in:
		
						commit
						d86e09bac1
					
				|  | @ -17,9 +17,7 @@ limitations under the License. | ||||||
| package cache | package cache | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"crypto/tls" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" |  | ||||||
| 	"os" | 	"os" | ||||||
| 	"path" | 	"path" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | @ -27,6 +25,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/config" | 	"github.com/GoogleContainerTools/kaniko/pkg/config" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/creds" | 	"github.com/GoogleContainerTools/kaniko/pkg/creds" | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/pkg/util" | ||||||
| 	"github.com/google/go-containerregistry/pkg/name" | 	"github.com/google/go-containerregistry/pkg/name" | ||||||
| 	v1 "github.com/google/go-containerregistry/pkg/v1" | 	v1 "github.com/google/go-containerregistry/pkg/v1" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/remote" | 	"github.com/google/go-containerregistry/pkg/v1/remote" | ||||||
|  | @ -67,12 +66,7 @@ func (rc *RegistryCache) RetrieveLayer(ck string) (v1.Image, error) { | ||||||
| 		cacheRef.Repository.Registry = newReg | 		cacheRef.Repository.Registry = newReg | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tr := http.DefaultTransport.(*http.Transport) | 	tr := util.MakeTransport(rc.Opts, registryName) | ||||||
| 	if rc.Opts.SkipTLSVerifyRegistries.Contains(registryName) { |  | ||||||
| 		tr.TLSClientConfig = &tls.Config{ |  | ||||||
| 			InsecureSkipVerify: true, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	img, err := remote.Image(cacheRef, remote.WithTransport(tr), remote.WithAuthFromKeychain(creds.GetKeychain())) | 	img, err := remote.Image(cacheRef, remote.WithTransport(tr), remote.WithAuthFromKeychain(creds.GetKeychain())) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ import ( | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/config" | 	"github.com/GoogleContainerTools/kaniko/pkg/config" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/constants" | 	"github.com/GoogleContainerTools/kaniko/pkg/constants" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/dockerfile" | 	"github.com/GoogleContainerTools/kaniko/pkg/dockerfile" | ||||||
|  | 	image_util "github.com/GoogleContainerTools/kaniko/pkg/image" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/snapshot" | 	"github.com/GoogleContainerTools/kaniko/pkg/snapshot" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/timing" | 	"github.com/GoogleContainerTools/kaniko/pkg/timing" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/util" | 	"github.com/GoogleContainerTools/kaniko/pkg/util" | ||||||
|  | @ -84,7 +85,7 @@ type stageBuilder struct { | ||||||
| 
 | 
 | ||||||
| // newStageBuilder returns a new type stageBuilder which contains all the information required to build the stage
 | // newStageBuilder returns a new type stageBuilder which contains all the information required to build the stage
 | ||||||
| func newStageBuilder(opts *config.KanikoOptions, stage config.KanikoStage, crossStageDeps map[int][]string, dcm map[string]string, sid map[string]string, stageNameToIdx map[string]string) (*stageBuilder, error) { | func newStageBuilder(opts *config.KanikoOptions, stage config.KanikoStage, crossStageDeps map[int][]string, dcm map[string]string, sid map[string]string, stageNameToIdx map[string]string) (*stageBuilder, error) { | ||||||
| 	sourceImage, err := util.RetrieveSourceImage(stage, opts) | 	sourceImage, err := image_util.RetrieveSourceImage(stage, opts) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -517,7 +518,7 @@ func CalculateDependencies(stages []config.KanikoStage, opts *config.KanikoOptio | ||||||
| 		} else if s.Name == constants.NoBaseImage { | 		} else if s.Name == constants.NoBaseImage { | ||||||
| 			image = empty.Image | 			image = empty.Image | ||||||
| 		} else { | 		} else { | ||||||
| 			image, err = util.RetrieveSourceImage(s, opts) | 			image, err = image_util.RetrieveSourceImage(s, opts) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return nil, err | 				return nil, err | ||||||
| 			} | 			} | ||||||
|  | @ -751,7 +752,7 @@ func fetchExtraStages(stages []config.KanikoStage, opts *config.KanikoOptions) e | ||||||
| 
 | 
 | ||||||
| 			// This must be an image name, fetch it.
 | 			// This must be an image name, fetch it.
 | ||||||
| 			logrus.Debugf("Found extra base image stage %s", c.From) | 			logrus.Debugf("Found extra base image stage %s", c.From) | ||||||
| 			sourceImage, err := util.RetrieveRemoteImage(c.From, opts) | 			sourceImage, err := image_util.RetrieveRemoteImage(c.From, opts) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -17,8 +17,6 @@ limitations under the License. | ||||||
| package executor | package executor | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"crypto/tls" |  | ||||||
| 	"crypto/x509" |  | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
|  | @ -34,6 +32,7 @@ import ( | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/constants" | 	"github.com/GoogleContainerTools/kaniko/pkg/constants" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/creds" | 	"github.com/GoogleContainerTools/kaniko/pkg/creds" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/timing" | 	"github.com/GoogleContainerTools/kaniko/pkg/timing" | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/pkg/util" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/version" | 	"github.com/GoogleContainerTools/kaniko/pkg/version" | ||||||
| 	"github.com/google/go-containerregistry/pkg/name" | 	"github.com/google/go-containerregistry/pkg/name" | ||||||
| 	v1 "github.com/google/go-containerregistry/pkg/v1" | 	v1 "github.com/google/go-containerregistry/pkg/v1" | ||||||
|  | @ -48,15 +47,15 @@ import ( | ||||||
| 	"github.com/spf13/afero" | 	"github.com/spf13/afero" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | type withUserAgent struct { | ||||||
|  | 	t http.RoundTripper | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // for testing
 | // for testing
 | ||||||
| var ( | var ( | ||||||
| 	newRetry = transport.NewRetry | 	newRetry = transport.NewRetry | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type withUserAgent struct { |  | ||||||
| 	t http.RoundTripper |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const ( | const ( | ||||||
| 	UpstreamClientUaKey = "UPSTREAM_CLIENT_TYPE" | 	UpstreamClientUaKey = "UPSTREAM_CLIENT_TYPE" | ||||||
| ) | ) | ||||||
|  | @ -82,41 +81,6 @@ func (w *withUserAgent) RoundTrip(r *http.Request) (*http.Response, error) { | ||||||
| 	return w.t.RoundTrip(r) | 	return w.t.RoundTrip(r) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type CertPool interface { |  | ||||||
| 	value() *x509.CertPool |  | ||||||
| 	append(path string) error |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type X509CertPool struct { |  | ||||||
| 	inner x509.CertPool |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (p *X509CertPool) value() *x509.CertPool { |  | ||||||
| 	return &p.inner |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (p *X509CertPool) append(path string) error { |  | ||||||
| 	pem, err := ioutil.ReadFile(path) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	p.inner.AppendCertsFromPEM(pem) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type systemCertLoader func() CertPool |  | ||||||
| 
 |  | ||||||
| var defaultX509Handler systemCertLoader = func() CertPool { |  | ||||||
| 	systemCertPool, err := x509.SystemCertPool() |  | ||||||
| 	if err != nil { |  | ||||||
| 		logrus.Warn("Failed to load system cert pool. Loading empty one instead.") |  | ||||||
| 		systemCertPool = x509.NewCertPool() |  | ||||||
| 	} |  | ||||||
| 	return &X509CertPool{ |  | ||||||
| 		inner: *systemCertPool, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // for testing
 | // for testing
 | ||||||
| var ( | var ( | ||||||
| 	fs                        = afero.NewOsFs() | 	fs                        = afero.NewOsFs() | ||||||
|  | @ -161,7 +125,7 @@ func CheckPushPermissions(opts *config.KanikoOptions) error { | ||||||
| 			} | 			} | ||||||
| 			destRef.Repository.Registry = newReg | 			destRef.Repository.Registry = newReg | ||||||
| 		} | 		} | ||||||
| 		tr := makeTransport(opts, registryName, defaultX509Handler) | 		tr := newRetry(util.MakeTransport(opts, registryName)) | ||||||
| 		if err := checkRemotePushPermission(destRef, creds.GetKeychain(), tr); err != nil { | 		if err := checkRemotePushPermission(destRef, creds.GetKeychain(), tr); err != nil { | ||||||
| 			return errors.Wrapf(err, "checking push permission for %q", destRef) | 			return errors.Wrapf(err, "checking push permission for %q", destRef) | ||||||
| 		} | 		} | ||||||
|  | @ -258,7 +222,7 @@ func DoPush(image v1.Image, opts *config.KanikoOptions) error { | ||||||
| 			return errors.Wrap(err, "resolving pushAuth") | 			return errors.Wrap(err, "resolving pushAuth") | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		tr := makeTransport(opts, registryName, defaultX509Handler) | 		tr := newRetry(util.MakeTransport(opts, registryName)) | ||||||
| 		rt := &withUserAgent{t: tr} | 		rt := &withUserAgent{t: tr} | ||||||
| 
 | 
 | ||||||
| 		if err := remote.Write(destRef, image, remote.WithAuth(pushAuth), remote.WithTransport(rt)); err != nil { | 		if err := remote.Write(destRef, image, remote.WithAuth(pushAuth), remote.WithTransport(rt)); err != nil { | ||||||
|  | @ -300,26 +264,6 @@ func writeImageOutputs(image v1.Image, destRefs []name.Tag) error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func makeTransport(opts *config.KanikoOptions, registryName string, loader systemCertLoader) http.RoundTripper { |  | ||||||
| 	// Create a transport to set our user-agent.
 |  | ||||||
| 	var tr http.RoundTripper = http.DefaultTransport.(*http.Transport).Clone() |  | ||||||
| 	if opts.SkipTLSVerify || opts.SkipTLSVerifyRegistries.Contains(registryName) { |  | ||||||
| 		tr.(*http.Transport).TLSClientConfig = &tls.Config{ |  | ||||||
| 			InsecureSkipVerify: true, |  | ||||||
| 		} |  | ||||||
| 	} else if certificatePath := opts.RegistriesCertificates[registryName]; certificatePath != "" { |  | ||||||
| 		systemCertPool := loader() |  | ||||||
| 		if err := systemCertPool.append(certificatePath); err != nil { |  | ||||||
| 			logrus.WithError(err).Warnf("Failed to load certificate %s for %s\n", certificatePath, registryName) |  | ||||||
| 		} else { |  | ||||||
| 			tr.(*http.Transport).TLSClientConfig = &tls.Config{ |  | ||||||
| 				RootCAs: systemCertPool.value(), |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return newRetry(tr) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // pushLayerToCache pushes layer (tagged with cacheKey) to opts.Cache
 | // pushLayerToCache pushes layer (tagged with cacheKey) to opts.Cache
 | ||||||
| // if opts.Cache doesn't exist, infer the cache from the given destination
 | // if opts.Cache doesn't exist, infer the cache from the given destination
 | ||||||
| func pushLayerToCache(opts *config.KanikoOptions, cacheKey string, tarPath string, createdBy string) error { | func pushLayerToCache(opts *config.KanikoOptions, cacheKey string, tarPath string, createdBy string) error { | ||||||
|  |  | ||||||
|  | @ -18,8 +18,6 @@ package executor | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"crypto/tls" |  | ||||||
| 	"crypto/x509" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | @ -34,7 +32,6 @@ import ( | ||||||
| 	"github.com/google/go-containerregistry/pkg/name" | 	"github.com/google/go-containerregistry/pkg/name" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/layout" | 	"github.com/google/go-containerregistry/pkg/v1/layout" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/random" | 	"github.com/google/go-containerregistry/pkg/v1/random" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/remote/transport" |  | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/validate" | 	"github.com/google/go-containerregistry/pkg/v1/validate" | ||||||
| 
 | 
 | ||||||
| 	"github.com/spf13/afero" | 	"github.com/spf13/afero" | ||||||
|  | @ -272,103 +269,6 @@ func TestImageNameDigestFile(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type mockedCertPool struct { |  | ||||||
| 	certificatesPath []string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (m *mockedCertPool) value() *x509.CertPool { |  | ||||||
| 	return &x509.CertPool{} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (m *mockedCertPool) append(path string) error { |  | ||||||
| 	m.certificatesPath = append(m.certificatesPath, path) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type retryTransport struct { |  | ||||||
| 	inner http.RoundTripper |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (t *retryTransport) RoundTrip(in *http.Request) (out *http.Response, err error) { |  | ||||||
| 	return nil, nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func Test_makeTransport(t *testing.T) { |  | ||||||
| 	registryName := "my.registry.name" |  | ||||||
| 
 |  | ||||||
| 	tests := []struct { |  | ||||||
| 		name  string |  | ||||||
| 		opts  *config.KanikoOptions |  | ||||||
| 		check func(*tls.Config, *mockedCertPool) |  | ||||||
| 	}{ |  | ||||||
| 		{ |  | ||||||
| 			name: "SkipTLSVerify set", |  | ||||||
| 			opts: &config.KanikoOptions{SkipTLSVerify: true}, |  | ||||||
| 			check: func(config *tls.Config, pool *mockedCertPool) { |  | ||||||
| 				if !config.InsecureSkipVerify { |  | ||||||
| 					t.Errorf("makeTransport().TLSClientConfig.InsecureSkipVerify not set while SkipTLSVerify set") |  | ||||||
| 				} |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name: "SkipTLSVerifyRegistries set with expected registry", |  | ||||||
| 			opts: &config.KanikoOptions{SkipTLSVerifyRegistries: []string{registryName}}, |  | ||||||
| 			check: func(config *tls.Config, pool *mockedCertPool) { |  | ||||||
| 				if !config.InsecureSkipVerify { |  | ||||||
| 					t.Errorf("makeTransport().TLSClientConfig.InsecureSkipVerify not set while SkipTLSVerifyRegistries set with registry name") |  | ||||||
| 				} |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name: "SkipTLSVerifyRegistries set with other registry", |  | ||||||
| 			opts: &config.KanikoOptions{SkipTLSVerifyRegistries: []string{fmt.Sprintf("other.%s", registryName)}}, |  | ||||||
| 			check: func(config *tls.Config, pool *mockedCertPool) { |  | ||||||
| 				if config.InsecureSkipVerify { |  | ||||||
| 					t.Errorf("makeTransport().TLSClientConfig.InsecureSkipVerify set while SkipTLSVerifyRegistries not set with registry name") |  | ||||||
| 				} |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name: "RegistriesCertificates set for registry", |  | ||||||
| 			opts: &config.KanikoOptions{RegistriesCertificates: map[string]string{registryName: "/path/to/the/certificate.cert"}}, |  | ||||||
| 			check: func(config *tls.Config, pool *mockedCertPool) { |  | ||||||
| 				if len(pool.certificatesPath) != 1 || pool.certificatesPath[0] != "/path/to/the/certificate.cert" { |  | ||||||
| 					t.Errorf("makeTransport().RegistriesCertificates certificate not appended to system certificates") |  | ||||||
| 				} |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			name: "RegistriesCertificates set for another registry", |  | ||||||
| 			opts: &config.KanikoOptions{RegistriesCertificates: map[string]string{fmt.Sprintf("other.%s=", registryName): "/path/to/the/certificate.cert"}}, |  | ||||||
| 			check: func(config *tls.Config, pool *mockedCertPool) { |  | ||||||
| 				if len(pool.certificatesPath) != 0 { |  | ||||||
| 					t.Errorf("makeTransport().RegistriesCertificates certificate appended to system certificates while added for other registry") |  | ||||||
| 				} |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 	for _, tt := range tests { |  | ||||||
| 		t.Run(tt.name, func(t *testing.T) { |  | ||||||
| 			originalRetry := newRetry |  | ||||||
| 			newRetry = func(inner http.RoundTripper, _ ...transport.Option) http.RoundTripper { |  | ||||||
| 				return &retryTransport{ |  | ||||||
| 					inner: inner, |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			defer func() { newRetry = originalRetry }() |  | ||||||
| 			var certificatesPath []string |  | ||||||
| 			certPool := mockedCertPool{ |  | ||||||
| 				certificatesPath: certificatesPath, |  | ||||||
| 			} |  | ||||||
| 			var mockedSystemCertLoader systemCertLoader = func() CertPool { |  | ||||||
| 				return &certPool |  | ||||||
| 			} |  | ||||||
| 			actual := makeTransport(tt.opts, registryName, mockedSystemCertLoader) |  | ||||||
| 			tt.check(actual.(*retryTransport).inner.(*http.Transport).TLSClientConfig, &certPool) |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| var calledExecCommand = false | var calledExecCommand = false | ||||||
| var calledCheckPushPermission = false | var calledCheckPushPermission = false | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,43 +0,0 @@ | ||||||
| /* |  | ||||||
| Copyright 2018 Google LLC |  | ||||||
| 
 |  | ||||||
| Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
| you may not use this file except in compliance with the License. |  | ||||||
| You may obtain a copy of the License at |  | ||||||
| 
 |  | ||||||
|     http://www.apache.org/licenses/LICENSE-2.0
 |  | ||||||
| 
 |  | ||||||
| Unless required by applicable law or agreed to in writing, software |  | ||||||
| distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
| See the License for the specific language governing permissions and |  | ||||||
| limitations under the License. |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| package image |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"os" |  | ||||||
| 	"strings" |  | ||||||
| 
 |  | ||||||
| 	v1 "github.com/google/go-containerregistry/pkg/v1" |  | ||||||
| 
 |  | ||||||
| 	"github.com/sirupsen/logrus" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // SetEnvVariables sets environment variables as specified in the image
 |  | ||||||
| func SetEnvVariables(img v1.Image) error { |  | ||||||
| 	cfg, err := img.ConfigFile() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
| 	envVars := cfg.Config.Env |  | ||||||
| 	for _, envVar := range envVars { |  | ||||||
| 		split := strings.SplitN(envVar, "=", 2) |  | ||||||
| 		if err := os.Setenv(split[0], split[1]); err != nil { |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		logrus.Infof("Setting environment variable %s", envVar) |  | ||||||
| 	} |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  | @ -14,29 +14,28 @@ See the License for the specific language governing permissions and | ||||||
| limitations under the License. | limitations under the License. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| package util | package image | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"crypto/tls" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" |  | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | 	"runtime" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 
 | 
 | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/timing" | 	"github.com/GoogleContainerTools/kaniko/pkg/cache" | ||||||
| 
 | 	"github.com/GoogleContainerTools/kaniko/pkg/config" | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/pkg/constants" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/creds" | 	"github.com/GoogleContainerTools/kaniko/pkg/creds" | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/pkg/timing" | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/pkg/util" | ||||||
| 
 | 
 | ||||||
| 	"github.com/google/go-containerregistry/pkg/name" | 	"github.com/google/go-containerregistry/pkg/name" | ||||||
| 	v1 "github.com/google/go-containerregistry/pkg/v1" | 	v1 "github.com/google/go-containerregistry/pkg/v1" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/empty" | 	"github.com/google/go-containerregistry/pkg/v1/empty" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/remote" | 	"github.com/google/go-containerregistry/pkg/v1/remote" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/tarball" | 	"github.com/google/go-containerregistry/pkg/v1/tarball" | ||||||
| 	"github.com/sirupsen/logrus" |  | ||||||
| 
 | 
 | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/cache" | 	"github.com/sirupsen/logrus" | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/config" |  | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/constants" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
|  | @ -55,7 +54,7 @@ func RetrieveSourceImage(stage config.KanikoStage, opts *config.KanikoOptions) ( | ||||||
| 		buildArgs = append(buildArgs, fmt.Sprintf("%s=%s", arg.Key, arg.ValueString())) | 		buildArgs = append(buildArgs, fmt.Sprintf("%s=%s", arg.Key, arg.ValueString())) | ||||||
| 	} | 	} | ||||||
| 	buildArgs = append(buildArgs, opts.BuildArgs...) | 	buildArgs = append(buildArgs, opts.BuildArgs...) | ||||||
| 	currentBaseName, err := ResolveEnvironmentReplacement(stage.BaseName, buildArgs, false) | 	currentBaseName, err := util.ResolveEnvironmentReplacement(stage.BaseName, buildArgs, false) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -146,12 +145,7 @@ func remoteImage(image string, opts *config.KanikoOptions) (v1.Image, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func remoteOptions(registryName string, opts *config.KanikoOptions) []remote.Option { | func remoteOptions(registryName string, opts *config.KanikoOptions) []remote.Option { | ||||||
| 	tr := http.DefaultTransport.(*http.Transport) | 	tr := util.MakeTransport(opts, registryName) | ||||||
| 	if opts.SkipTLSVerifyPull || opts.SkipTLSVerifyRegistries.Contains(registryName) { |  | ||||||
| 		tr.TLSClientConfig = &tls.Config{ |  | ||||||
| 			InsecureSkipVerify: true, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	// on which v1.Platform is this currently running?
 | 	// on which v1.Platform is this currently running?
 | ||||||
| 	platform := currentPlatform() | 	platform := currentPlatform() | ||||||
|  | @ -182,3 +176,11 @@ func cachedImage(opts *config.KanikoOptions, image string) (v1.Image, error) { | ||||||
| 	} | 	} | ||||||
| 	return cache.LocalSource(&opts.CacheOptions, cacheKey) | 	return cache.LocalSource(&opts.CacheOptions, cacheKey) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // CurrentPlatform returns the v1.Platform on which the code runs
 | ||||||
|  | func currentPlatform() v1.Platform { | ||||||
|  | 	return v1.Platform{ | ||||||
|  | 		OS:           runtime.GOOS, | ||||||
|  | 		Architecture: runtime.GOARCH, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -14,18 +14,19 @@ See the License for the specific language governing permissions and | ||||||
| limitations under the License. | limitations under the License. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| package util | package image | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
| 	"github.com/GoogleContainerTools/kaniko/pkg/config" |  | ||||||
| 	"github.com/GoogleContainerTools/kaniko/testutil" |  | ||||||
| 	v1 "github.com/google/go-containerregistry/pkg/v1" | 	v1 "github.com/google/go-containerregistry/pkg/v1" | ||||||
| 	"github.com/google/go-containerregistry/pkg/v1/empty" | 	"github.com/google/go-containerregistry/pkg/v1/empty" | ||||||
| 	"github.com/moby/buildkit/frontend/dockerfile/instructions" | 	"github.com/moby/buildkit/frontend/dockerfile/instructions" | ||||||
| 	"github.com/moby/buildkit/frontend/dockerfile/parser" | 	"github.com/moby/buildkit/frontend/dockerfile/parser" | ||||||
|  | 
 | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/pkg/config" | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/testutil" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
|  | @ -0,0 +1,82 @@ | ||||||
|  | /* | ||||||
|  | Copyright 2020 Google LLC | ||||||
|  | 
 | ||||||
|  | Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | you may not use this file except in compliance with the License. | ||||||
|  | You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  | Unless required by applicable law or agreed to in writing, software | ||||||
|  | distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | See the License for the specific language governing permissions and | ||||||
|  | limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package util | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"crypto/tls" | ||||||
|  | 	"crypto/x509" | ||||||
|  | 
 | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/pkg/config" | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type CertPool interface { | ||||||
|  | 	value() *x509.CertPool | ||||||
|  | 	append(path string) error | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type X509CertPool struct { | ||||||
|  | 	inner x509.CertPool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *X509CertPool) value() *x509.CertPool { | ||||||
|  | 	return &p.inner | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *X509CertPool) append(path string) error { | ||||||
|  | 	pem, err := ioutil.ReadFile(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	p.inner.AppendCertsFromPEM(pem) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var systemCertLoader CertPool | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	systemCertPool, err := x509.SystemCertPool() | ||||||
|  | 	if err != nil { | ||||||
|  | 		logrus.Warn("Failed to load system cert pool. Loading empty one instead.") | ||||||
|  | 		systemCertPool = x509.NewCertPool() | ||||||
|  | 	} | ||||||
|  | 	systemCertLoader = &X509CertPool{ | ||||||
|  | 		inner: *systemCertPool, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func MakeTransport(opts *config.KanikoOptions, registryName string) http.RoundTripper { | ||||||
|  | 	// Create a transport to set our user-agent.
 | ||||||
|  | 	var tr http.RoundTripper = http.DefaultTransport.(*http.Transport).Clone() | ||||||
|  | 	if opts.SkipTLSVerify || opts.SkipTLSVerifyRegistries.Contains(registryName) { | ||||||
|  | 		tr.(*http.Transport).TLSClientConfig = &tls.Config{ | ||||||
|  | 			InsecureSkipVerify: true, | ||||||
|  | 		} | ||||||
|  | 	} else if certificatePath := opts.RegistriesCertificates[registryName]; certificatePath != "" { | ||||||
|  | 		if err := systemCertLoader.append(certificatePath); err != nil { | ||||||
|  | 			logrus.WithError(err).Warnf("Failed to load certificate %s for %s\n", certificatePath, registryName) | ||||||
|  | 		} else { | ||||||
|  | 			tr.(*http.Transport).TLSClientConfig = &tls.Config{ | ||||||
|  | 				RootCAs: systemCertLoader.value(), | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return tr | ||||||
|  | } | ||||||
|  | @ -0,0 +1,110 @@ | ||||||
|  | /* | ||||||
|  | Copyright 2020 Google LLC | ||||||
|  | 
 | ||||||
|  | Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | you may not use this file except in compliance with the License. | ||||||
|  | You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  | Unless required by applicable law or agreed to in writing, software | ||||||
|  | distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | See the License for the specific language governing permissions and | ||||||
|  | limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package util | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"crypto/tls" | ||||||
|  | 	"crypto/x509" | ||||||
|  | 	"fmt" | ||||||
|  | 	"net/http" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/GoogleContainerTools/kaniko/pkg/config" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type mockedCertPool struct { | ||||||
|  | 	certificatesPath []string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m *mockedCertPool) value() *x509.CertPool { | ||||||
|  | 	return &x509.CertPool{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m *mockedCertPool) append(path string) error { | ||||||
|  | 	m.certificatesPath = append(m.certificatesPath, path) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func Test_makeTransport(t *testing.T) { | ||||||
|  | 	registryName := "my.registry.name" | ||||||
|  | 
 | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name  string | ||||||
|  | 		opts  *config.KanikoOptions | ||||||
|  | 		check func(*tls.Config, *mockedCertPool) | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name: "SkipTLSVerify set", | ||||||
|  | 			opts: &config.KanikoOptions{SkipTLSVerify: true}, | ||||||
|  | 			check: func(config *tls.Config, pool *mockedCertPool) { | ||||||
|  | 				if !config.InsecureSkipVerify { | ||||||
|  | 					t.Errorf("makeTransport().TLSClientConfig.InsecureSkipVerify not set while SkipTLSVerify set") | ||||||
|  | 				} | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "SkipTLSVerifyRegistries set with expected registry", | ||||||
|  | 			opts: &config.KanikoOptions{SkipTLSVerifyRegistries: []string{registryName}}, | ||||||
|  | 			check: func(config *tls.Config, pool *mockedCertPool) { | ||||||
|  | 				if !config.InsecureSkipVerify { | ||||||
|  | 					t.Errorf("makeTransport().TLSClientConfig.InsecureSkipVerify not set while SkipTLSVerifyRegistries set with registry name") | ||||||
|  | 				} | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "SkipTLSVerifyRegistries set with other registry", | ||||||
|  | 			opts: &config.KanikoOptions{SkipTLSVerifyRegistries: []string{fmt.Sprintf("other.%s", registryName)}}, | ||||||
|  | 			check: func(config *tls.Config, pool *mockedCertPool) { | ||||||
|  | 				if config.InsecureSkipVerify { | ||||||
|  | 					t.Errorf("makeTransport().TLSClientConfig.InsecureSkipVerify set while SkipTLSVerifyRegistries not set with registry name") | ||||||
|  | 				} | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "RegistriesCertificates set for registry", | ||||||
|  | 			opts: &config.KanikoOptions{RegistriesCertificates: map[string]string{registryName: "/path/to/the/certificate.cert"}}, | ||||||
|  | 			check: func(config *tls.Config, pool *mockedCertPool) { | ||||||
|  | 				if len(pool.certificatesPath) != 1 || pool.certificatesPath[0] != "/path/to/the/certificate.cert" { | ||||||
|  | 					t.Errorf("makeTransport().RegistriesCertificates certificate not appended to system certificates") | ||||||
|  | 				} | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "RegistriesCertificates set for another registry", | ||||||
|  | 			opts: &config.KanikoOptions{RegistriesCertificates: map[string]string{fmt.Sprintf("other.%s=", registryName): "/path/to/the/certificate.cert"}}, | ||||||
|  | 			check: func(config *tls.Config, pool *mockedCertPool) { | ||||||
|  | 				if len(pool.certificatesPath) != 0 { | ||||||
|  | 					t.Errorf("makeTransport().RegistriesCertificates certificate appended to system certificates while added for other registry") | ||||||
|  | 				} | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	savedSystemCertLoader := systemCertLoader | ||||||
|  | 	defer func() { systemCertLoader = savedSystemCertLoader }() | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		var certificatesPath []string | ||||||
|  | 		certPool := &mockedCertPool{ | ||||||
|  | 			certificatesPath: certificatesPath, | ||||||
|  | 		} | ||||||
|  | 		systemCertLoader = certPool | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			tr := MakeTransport(tt.opts, registryName) | ||||||
|  | 			tt.check(tr.(*http.Transport).TLSClientConfig, certPool) | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -23,14 +23,11 @@ import ( | ||||||
| 	"io" | 	"io" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"runtime" |  | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"syscall" | 	"syscall" | ||||||
| 
 | 
 | ||||||
| 	"github.com/minio/highwayhash" | 	"github.com/minio/highwayhash" | ||||||
| 
 |  | ||||||
| 	v1 "github.com/google/go-containerregistry/pkg/v1" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Hasher returns a hash function, used in snapshotting to determine if a file has changed
 | // Hasher returns a hash function, used in snapshotting to determine if a file has changed
 | ||||||
|  | @ -128,14 +125,6 @@ func SHA256(r io.Reader) (string, error) { | ||||||
| 	return hex.EncodeToString(hasher.Sum(make([]byte, 0, hasher.Size()))), nil | 	return hex.EncodeToString(hasher.Sum(make([]byte, 0, hasher.Size()))), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CurrentPlatform returns the v1.Platform on which the code runs
 |  | ||||||
| func currentPlatform() v1.Platform { |  | ||||||
| 	return v1.Platform{ |  | ||||||
| 		OS:           runtime.GOOS, |  | ||||||
| 		Architecture: runtime.GOARCH, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // GetInputFrom returns Reader content
 | // GetInputFrom returns Reader content
 | ||||||
| func GetInputFrom(r io.Reader) ([]byte, error) { | func GetInputFrom(r io.Reader) ([]byte, error) { | ||||||
| 	output, err := ioutil.ReadAll(r) | 	output, err := ioutil.ReadAll(r) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue