Merge remote-tracking branch 'origin/master' into fix/1172

This commit is contained in:
Yoan Blanc
2020-05-25 13:54:37 +02:00
22 changed files with 416 additions and 237 deletions
+18
View File
@@ -23,12 +23,17 @@ import (
"github.com/GoogleContainerTools/kaniko/pkg/constants"
git "gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/transport"
"gopkg.in/src-d/go-git.v4/plumbing/transport/http"
)
const (
gitPullMethodEnvKey = "GIT_PULL_METHOD"
gitPullMethodHTTPS = "https"
gitPullMethodHTTP = "http"
gitAuthUsernameEnvKey = "GIT_USERNAME"
gitAuthPasswordEnvKey = "GIT_PASSWORD"
)
var (
@@ -46,6 +51,7 @@ func (g *Git) UnpackTarFromBuildContext() (string, error) {
parts := strings.Split(g.context, "#")
options := git.CloneOptions{
URL: getGitPullMethod() + "://" + parts[0],
Auth: getGitAuth(),
Progress: os.Stdout,
}
if len(parts) > 1 {
@@ -55,6 +61,18 @@ func (g *Git) UnpackTarFromBuildContext() (string, error) {
return directory, err
}
func getGitAuth() transport.AuthMethod {
username := os.Getenv(gitAuthUsernameEnvKey)
password := os.Getenv(gitAuthPasswordEnvKey)
if username != "" || password != "" {
return &http.BasicAuth{
Username: username,
Password: password,
}
}
return nil
}
func getGitPullMethod() string {
gitPullMethod := os.Getenv(gitPullMethodEnvKey)
if ok := supportedGitPullMethods[gitPullMethod]; !ok {
+87
View File
@@ -21,6 +21,8 @@ import (
"testing"
"github.com/GoogleContainerTools/kaniko/testutil"
"gopkg.in/src-d/go-git.v4/plumbing/transport"
"gopkg.in/src-d/go-git.v4/plumbing/transport/http"
)
func TestGetGitPullMethod(t *testing.T) {
@@ -80,3 +82,88 @@ func TestGetGitPullMethod(t *testing.T) {
})
}
}
func TestGetGitAuth(t *testing.T) {
tests := []struct {
testName string
setEnv func() (expectedValue transport.AuthMethod)
}{
{
testName: "noEnv",
setEnv: func() (expectedValue transport.AuthMethod) {
expectedValue = nil
return
},
},
{
testName: "emptyUsernameEnv",
setEnv: func() (expectedValue transport.AuthMethod) {
_ = os.Setenv(gitAuthUsernameEnvKey, "")
expectedValue = nil
return
},
},
{
testName: "emptyPasswordEnv",
setEnv: func() (expectedValue transport.AuthMethod) {
_ = os.Setenv(gitAuthPasswordEnvKey, "")
expectedValue = nil
return
},
},
{
testName: "emptyEnv",
setEnv: func() (expectedValue transport.AuthMethod) {
_ = os.Setenv(gitAuthUsernameEnvKey, "")
_ = os.Setenv(gitAuthPasswordEnvKey, "")
expectedValue = nil
return
},
},
{
testName: "withUsername",
setEnv: func() (expectedValue transport.AuthMethod) {
username := "foo"
_ = os.Setenv(gitAuthUsernameEnvKey, username)
expectedValue = &http.BasicAuth{Username: username}
return
},
},
{
testName: "withPassword",
setEnv: func() (expectedValue transport.AuthMethod) {
pass := "super-secret-password-1234"
_ = os.Setenv(gitAuthPasswordEnvKey, pass)
expectedValue = &http.BasicAuth{Password: pass}
return
},
},
{
testName: "withUsernamePassword",
setEnv: func() (expectedValue transport.AuthMethod) {
username := "foo"
pass := "super-secret-password-1234"
_ = os.Setenv(gitAuthUsernameEnvKey, username)
_ = os.Setenv(gitAuthPasswordEnvKey, pass)
expectedValue = &http.BasicAuth{Username: username, Password: pass}
return
},
},
}
for _, tt := range tests {
t.Run(tt.testName, func(t *testing.T) {
// Make sure to unset environment vars to get a clean test each time
defer clearTestAuthEnv()
expectedValue := tt.setEnv()
testutil.CheckDeepEqual(t, expectedValue, getGitAuth())
})
}
}
func clearTestAuthEnv() {
_ = os.Unsetenv(gitAuthUsernameEnvKey)
_ = os.Unsetenv(gitAuthPasswordEnvKey)
}
+2 -8
View File
@@ -17,9 +17,7 @@ limitations under the License.
package cache
import (
"crypto/tls"
"fmt"
"net/http"
"os"
"path"
"path/filepath"
@@ -27,6 +25,7 @@ import (
"github.com/GoogleContainerTools/kaniko/pkg/config"
"github.com/GoogleContainerTools/kaniko/pkg/creds"
"github.com/GoogleContainerTools/kaniko/pkg/util"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"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
}
tr := http.DefaultTransport.(*http.Transport)
if rc.Opts.SkipTLSVerifyRegistries.Contains(registryName) {
tr.TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
}
}
tr := util.MakeTransport(rc.Opts, registryName)
img, err := remote.Image(cacheRef, remote.WithTransport(tr), remote.WithAuthFromKeychain(creds.GetKeychain()))
if err != nil {
+9 -1
View File
@@ -65,7 +65,8 @@ func (r *RunCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
logrus.Infof("args: %s", newCommand[1:])
cmd := exec.Command(newCommand[0], newCommand[1:]...)
cmd.Dir = config.WorkingDir
cmd.Dir = setWorkDirIfExists(config.WorkingDir)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
replacementEnvs := buildArgs.ReplacementEnvs(config.Env)
@@ -236,3 +237,10 @@ func (cr *CachingRunCommand) String() string {
func (cr *CachingRunCommand) MetadataOnly() bool {
return false
}
func setWorkDirIfExists(workdir string) string {
if _, err := os.Lstat(workdir); err == nil {
return workdir
}
return ""
}
+9
View File
@@ -316,3 +316,12 @@ func Test_CachingRunCommand_ExecuteCommand(t *testing.T) {
})
}
}
func TestSetWorkDirIfExists(t *testing.T) {
testDir, err := ioutil.TempDir("", "workdir")
if err != nil {
t.Error(err)
}
testutil.CheckDeepEqual(t, testDir, setWorkDirIfExists(testDir))
testutil.CheckDeepEqual(t, "", setWorkDirIfExists("doesnot-exists"))
}
+6 -3
View File
@@ -44,6 +44,7 @@ import (
"github.com/GoogleContainerTools/kaniko/pkg/config"
"github.com/GoogleContainerTools/kaniko/pkg/constants"
"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/timing"
"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
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 {
return nil, err
}
@@ -517,7 +518,7 @@ func CalculateDependencies(stages []config.KanikoStage, opts *config.KanikoOptio
} else if s.Name == constants.NoBaseImage {
image = empty.Image
} else {
image, err = util.RetrieveSourceImage(s, opts)
image, err = image_util.RetrieveSourceImage(s, opts)
if err != nil {
return nil, err
}
@@ -596,6 +597,7 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
}
logrus.Infof("Built cross stage deps: %v", crossStageDependencies)
util.IsFirstStage = true
for index, stage := range kanikoStages {
sb, err := newStageBuilder(opts, stage, crossStageDependencies, digestToCacheKey, stageIdxToDigest, stageNameToIdx)
if err != nil {
@@ -604,6 +606,7 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
if err := sb.build(); err != nil {
return nil, errors.Wrap(err, "error building stage")
}
util.IsFirstStage = false
reviewConfig(stage, &sb.cf.Config)
@@ -749,7 +752,7 @@ func fetchExtraStages(stages []config.KanikoStage, opts *config.KanikoOptions) e
// This must be an image name, fetch it.
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 {
return err
}
+9 -59
View File
@@ -17,8 +17,6 @@ limitations under the License.
package executor
import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
@@ -34,6 +32,7 @@ import (
"github.com/GoogleContainerTools/kaniko/pkg/constants"
"github.com/GoogleContainerTools/kaniko/pkg/creds"
"github.com/GoogleContainerTools/kaniko/pkg/timing"
"github.com/GoogleContainerTools/kaniko/pkg/util"
"github.com/GoogleContainerTools/kaniko/pkg/version"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
@@ -41,6 +40,7 @@ import (
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -51,6 +51,11 @@ type withUserAgent struct {
t http.RoundTripper
}
// for testing
var (
newRetry = transport.NewRetry
)
const (
UpstreamClientUaKey = "UPSTREAM_CLIENT_TYPE"
)
@@ -76,41 +81,6 @@ func (w *withUserAgent) RoundTrip(r *http.Request) (*http.Response, error) {
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
var (
fs = afero.NewOsFs()
@@ -155,7 +125,7 @@ func CheckPushPermissions(opts *config.KanikoOptions) error {
}
destRef.Repository.Registry = newReg
}
tr := makeTransport(opts, registryName, defaultX509Handler)
tr := newRetry(util.MakeTransport(opts, registryName))
if err := checkRemotePushPermission(destRef, creds.GetKeychain(), tr); err != nil {
return errors.Wrapf(err, "checking push permission for %q", destRef)
}
@@ -252,7 +222,7 @@ func DoPush(image v1.Image, opts *config.KanikoOptions) error {
return errors.Wrap(err, "resolving pushAuth")
}
tr := makeTransport(opts, registryName, defaultX509Handler)
tr := newRetry(util.MakeTransport(opts, registryName))
rt := &withUserAgent{t: tr}
if err := remote.Write(destRef, image, remote.WithAuth(pushAuth), remote.WithTransport(rt)); err != nil {
@@ -294,26 +264,6 @@ func writeImageOutputs(image v1.Image, destRefs []name.Tag) error {
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 tr
}
// pushLayerToCache pushes layer (tagged with cacheKey) to opts.Cache
// 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 {
+1 -84
View File
@@ -18,8 +18,6 @@ package executor
import (
"bytes"
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net/http"
@@ -35,6 +33,7 @@ import (
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/random"
"github.com/google/go-containerregistry/pkg/v1/validate"
"github.com/spf13/afero"
)
@@ -270,88 +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
}
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) {
var certificatesPath []string
certPool := mockedCertPool{
certificatesPath: certificatesPath,
}
var mockedSystemCertLoader systemCertLoader = func() CertPool {
return &certPool
}
transport := makeTransport(tt.opts, registryName, mockedSystemCertLoader)
tt.check(transport.(*http.Transport).TLSClientConfig, &certPool)
})
}
}
var calledExecCommand = false
var calledCheckPushPermission = false
-43
View File
@@ -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,30 +14,29 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package util
package image
import (
"crypto/tls"
"fmt"
"net/http"
"path/filepath"
"runtime"
"strconv"
"strings"
"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/timing"
"github.com/GoogleContainerTools/kaniko/pkg/util"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/tarball"
"github.com/sirupsen/logrus"
"github.com/GoogleContainerTools/kaniko/pkg/cache"
"github.com/GoogleContainerTools/kaniko/pkg/config"
"github.com/GoogleContainerTools/kaniko/pkg/constants"
"github.com/sirupsen/logrus"
)
var (
@@ -56,7 +55,7 @@ func RetrieveSourceImage(stage config.KanikoStage, opts *config.KanikoOptions) (
buildArgs = append(buildArgs, fmt.Sprintf("%s=%s", arg.Key, arg.ValueString()))
}
buildArgs = append(buildArgs, opts.BuildArgs...)
currentBaseName, err := ResolveEnvironmentReplacement(stage.BaseName, buildArgs, false)
currentBaseName, err := util.ResolveEnvironmentReplacement(stage.BaseName, buildArgs, false)
if err != nil {
return nil, err
}
@@ -154,12 +153,7 @@ func remoteImage(image string, opts *config.KanikoOptions) (v1.Image, error) {
}
func remoteOptions(registryName string, opts *config.KanikoOptions) []remote.Option {
tr := http.DefaultTransport.(*http.Transport)
if opts.SkipTLSVerifyPull || opts.SkipTLSVerifyRegistries.Contains(registryName) {
tr.TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
}
}
tr := util.MakeTransport(opts, registryName)
// on which v1.Platform is this currently running?
platform := currentPlatform()
@@ -190,3 +184,11 @@ func cachedImage(opts *config.KanikoOptions, image string) (v1.Image, error) {
}
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.
*/
package util
package image
import (
"bytes"
"testing"
"github.com/GoogleContainerTools/kaniko/pkg/config"
"github.com/GoogleContainerTools/kaniko/testutil"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/moby/buildkit/frontend/dockerfile/instructions"
"github.com/moby/buildkit/frontend/dockerfile/parser"
"github.com/GoogleContainerTools/kaniko/pkg/config"
"github.com/GoogleContainerTools/kaniko/testutil"
)
var (
+2
View File
@@ -158,6 +158,7 @@ func (s *Snapshotter) scanFullFilesystem() ([]string, []string, error) {
)
timing.DefaultRun.Stop(timer)
timer = timing.Start("Resolving Paths")
resolvedFiles, err := filesystem.ResolvePaths(foundPaths, s.whitelist)
if err != nil {
return nil, nil, err
@@ -207,6 +208,7 @@ func (s *Snapshotter) scanFullFilesystem() ([]string, []string, error) {
}
}
timing.DefaultRun.Stop(timer)
sort.Strings(filesToAdd)
// Add files to the layered map
for _, file := range filesToAdd {
+5
View File
@@ -73,6 +73,7 @@ var whitelist = initialWhitelist
var volumes = []string{}
var excluded []string
var IsFirstStage = true
type ExtractFunction func(string, *tar.Header, io.Reader) error
@@ -678,6 +679,10 @@ func GetExcludedFiles(dockerfilepath string, buildcontext string) error {
// ExcludeFile returns true if the .dockerignore specified this file should be ignored
func ExcludeFile(path, buildcontext string) bool {
// Apply dockerfile excludes for first stage only
if !IsFirstStage {
return false
}
if HasFilepathPrefix(path, buildcontext, false) {
var err error
path, err = filepath.Rel(buildcontext, path)
+82
View File
@@ -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
}
+110
View File
@@ -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)
})
}
}
-11
View File
@@ -23,14 +23,11 @@ import (
"io"
"io/ioutil"
"os"
"runtime"
"strconv"
"sync"
"syscall"
"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
@@ -128,14 +125,6 @@ func SHA256(r io.Reader) (string, error) {
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
func GetInputFrom(r io.Reader) ([]byte, error) {
output, err := ioutil.ReadAll(r)