Files

80 lines
1.8 KiB
Go

package content
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
"strings"
"sync"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/rs/zerolog"
)
type transport struct {
base http.RoundTripper
warnOnce sync.Once
}
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
if strings.EqualFold(req.URL.Scheme, "http") {
t.warnOnce.Do(func() {
zerolog.Ctx(req.Context()).Warn().Msgf("pulling content over plain HTTP [%s]", req.URL.Host)
})
}
return t.base.RoundTrip(req)
}
// BuildTransport returns a RoundTripper configured with the requested TLS
// settings. It also warns if the image pull makes a request over plain HTTP.
//
// insecureSkipTLSVerify takes precedence over caFile. When enabled, caFile is
// ignored.
func BuildTransport(insecureSkipTLSVerify bool, caFile string) (http.RoundTripper, error) {
base := remote.DefaultTransport
if insecureSkipTLSVerify || caFile != "" {
defaultTransport, ok := remote.DefaultTransport.(*http.Transport)
if !ok {
return nil, fmt.Errorf("unexpected default transport type %T", remote.DefaultTransport)
}
tr := defaultTransport.Clone()
if tr.TLSClientConfig == nil {
tr.TLSClientConfig = &tls.Config{}
} else {
tr.TLSClientConfig = tr.TLSClientConfig.Clone()
}
if insecureSkipTLSVerify {
tr.TLSClientConfig.InsecureSkipVerify = true //nolint:gosec
} else {
pool, err := x509.SystemCertPool()
if err != nil || pool == nil {
pool = x509.NewCertPool()
}
pem, err := os.ReadFile(caFile)
if err != nil {
return nil, fmt.Errorf("reading CA file %q: %w", caFile, err)
}
if !pool.AppendCertsFromPEM(pem) {
return nil, fmt.Errorf("no valid certificates found in CA file %q", caFile)
}
tr.TLSClientConfig.RootCAs = pool
}
base = tr
}
return &transport{
base: base,
}, nil
}