From 26bc91160b326dacbb6aa42fb81c8475571b7d68 Mon Sep 17 00:00:00 2001 From: Manveer Singh Date: Wed, 28 Jun 2023 16:51:26 +0530 Subject: [PATCH] feat(docker): add support for mTLS authentication when connecting to registry (#4649) * feat: add support for mTLS authentication when connecting to registry * feat: add support for mTLS authentication when connecting to registry - added error handling * feat: add support for mTLS authentication when connecting to registry - code quality improvements * feat: add support for mTLS authentication when connecting to registry - code quality improvements * wrap errors --------- Co-authored-by: knqyf263 --- pkg/fanal/types/image.go | 4 ++++ pkg/remote/remote.go | 29 +++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/pkg/fanal/types/image.go b/pkg/fanal/types/image.go index 88621560cf8..ab76cfc086f 100644 --- a/pkg/fanal/types/image.go +++ b/pkg/fanal/types/image.go @@ -85,6 +85,10 @@ type RegistryOptions struct { // SSL/TLS Insecure bool + // For internal use. Needed for mTLS authentication. + ClientCert []byte + ClientKey []byte + // Architecture Platform Platform diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index c20c2b23863..08924704a7d 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -26,7 +26,10 @@ type Descriptor = remote.Descriptor // Get is a wrapper of google/go-containerregistry/pkg/v1/remote.Get // so that it can try multiple authentication methods. func Get(ctx context.Context, ref name.Reference, option types.RegistryOptions) (*Descriptor, error) { - transport := httpTransport(option.Insecure) + transport, err := httpTransport(option) + if err != nil { + return nil, xerrors.Errorf("failed to create http transport: %w", err) + } var errs error // Try each authentication method until it succeeds @@ -68,7 +71,10 @@ func Get(ctx context.Context, ref name.Reference, option types.RegistryOptions) // Image is a wrapper of google/go-containerregistry/pkg/v1/remote.Image // so that it can try multiple authentication methods. func Image(ctx context.Context, ref name.Reference, option types.RegistryOptions) (v1.Image, error) { - transport := httpTransport(option.Insecure) + transport, err := httpTransport(option) + if err != nil { + return nil, xerrors.Errorf("failed to create http transport: %w", err) + } var errs error // Try each authentication method until it succeeds @@ -92,7 +98,10 @@ func Image(ctx context.Context, ref name.Reference, option types.RegistryOptions // Referrers is a wrapper of google/go-containerregistry/pkg/v1/remote.Referrers // so that it can try multiple authentication methods. func Referrers(ctx context.Context, d name.Digest, option types.RegistryOptions) (v1.ImageIndex, error) { - transport := httpTransport(option.Insecure) + transport, err := httpTransport(option) + if err != nil { + return nil, xerrors.Errorf("failed to create http transport: %w", err) + } var errs error // Try each authentication method until it succeeds @@ -113,15 +122,23 @@ func Referrers(ctx context.Context, d name.Digest, option types.RegistryOptions) return nil, errs } -func httpTransport(insecure bool) *http.Transport { +func httpTransport(option types.RegistryOptions) (*http.Transport, error) { d := &net.Dialer{ Timeout: 10 * time.Minute, } tr := http.DefaultTransport.(*http.Transport).Clone() tr.DialContext = d.DialContext - tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: insecure} + tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: option.Insecure} + + if len(option.ClientCert) != 0 && len(option.ClientKey) != 0 { + cert, err := tls.X509KeyPair(option.ClientCert, option.ClientKey) + if err != nil { + return nil, err + } + tr.TLSClientConfig.Certificates = []tls.Certificate{cert} + } - return tr + return tr, nil } func authOptions(ctx context.Context, ref name.Reference, option types.RegistryOptions) []remote.Option {