Allow user to provide registry certificate

Fixes #1100
Fixes #1101
This commit is contained in:
Ben Einaudi
2020-03-08 18:17:50 +01:00
parent 17ceb312c6
commit b73c2c10c8
9 changed files with 217 additions and 7 deletions
+49 -4
View File
@@ -18,6 +18,7 @@ package executor
import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
@@ -62,6 +63,41 @@ 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,
}
}
// CheckPushPermissions checks that the configured credentials can be used to
// push to every specified destination.
func CheckPushPermissions(opts *config.KanikoOptions) error {
@@ -87,7 +123,7 @@ func CheckPushPermissions(opts *config.KanikoOptions) error {
}
destRef.Repository.Registry = newReg
}
tr := makeTransport(opts, registryName)
tr := makeTransport(opts, registryName, defaultX509Handler)
if err := remote.CheckPushPermission(destRef, creds.GetKeychain(), tr); err != nil {
return errors.Wrapf(err, "checking push permission for %q", destRef)
}
@@ -184,7 +220,7 @@ func DoPush(image v1.Image, opts *config.KanikoOptions) error {
return errors.Wrap(err, "resolving pushAuth")
}
tr := makeTransport(opts, registryName)
tr := makeTransport(opts, registryName, defaultX509Handler)
rt := &withUserAgent{t: tr}
if err := remote.Write(destRef, image, remote.WithAuth(pushAuth), remote.WithTransport(rt)); err != nil {
@@ -228,13 +264,22 @@ func writeImageOutputs(image v1.Image, destRefs []name.Tag) error {
return nil
}
func makeTransport(opts *config.KanikoOptions, registryName string) http.RoundTripper {
func makeTransport(opts *config.KanikoOptions, registryName string, loader systemCertLoader) http.RoundTripper {
// Create a transport to set our user-agent.
tr := http.DefaultTransport
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
}