From 373f942ea9fa8b63140d0eb0e101b9a5f71033f3 Mon Sep 17 00:00:00 2001 From: Pradeep Lakshmi Narasimha Date: Mon, 7 Oct 2024 20:59:12 +0530 Subject: [PATCH] fix: Allow images to be pulled from insecure registry when allowInsecureRegistry flag is set to true (#10934) (#11243) * fix: Allow images to be pulled from insecure registry when allowInsecureRegistry flag is set to true (#10934) Signed-off-by: Pradeep Lakshmi Narasimha * Update pkg/registryclient/client.go Signed-off-by: Vishal Choudhary --------- Signed-off-by: Pradeep Lakshmi Narasimha Signed-off-by: Vishal Choudhary Co-authored-by: Vishal Choudhary Co-authored-by: Vishal Choudhary --- pkg/cosign/cosign.go | 6 ++++-- pkg/cosign/sigstore.go | 3 ++- pkg/cosign/sigstore_test.go | 6 ++++-- pkg/engine/adapters/rclient.go | 3 ++- pkg/engine/api/client.go | 2 ++ pkg/images/verifier.go | 2 ++ pkg/notary/notary.go | 13 +++++++------ pkg/notary/notary_test.go | 2 +- pkg/notary/registry.go | 5 +++-- pkg/registryclient/client.go | 33 +++++++++++++++++++++++++++------ 10 files changed, 54 insertions(+), 21 deletions(-) diff --git a/pkg/cosign/cosign.go b/pkg/cosign/cosign.go index 156c120462..60ca416966 100644 --- a/pkg/cosign/cosign.go +++ b/pkg/cosign/cosign.go @@ -60,7 +60,8 @@ func (v *cosignVerifier) VerifySignature(ctx context.Context, opts images.Option return &images.Response{Digest: results[0].Desc.Digest.String()}, nil } - ref, err := name.ParseReference(opts.ImageRef) + nameOpts := opts.Client.NameOptions() + ref, err := name.ParseReference(opts.ImageRef, nameOpts...) if err != nil { return nil, fmt.Errorf("failed to parse image %s", opts.ImageRef) } @@ -301,12 +302,13 @@ func (v *cosignVerifier) FetchAttestations(ctx context.Context, opts images.Opti return nil, err } + nameOpts := opts.Client.NameOptions() signatures, bundleVerified, err := tracing.ChildSpan3( ctx, "", "VERIFY IMG ATTESTATIONS", func(ctx context.Context, span trace.Span) (checkedAttestations []oci.Signature, bundleVerified bool, err error) { - ref, err := name.ParseReference(opts.ImageRef) + ref, err := name.ParseReference(opts.ImageRef, nameOpts...) if err != nil { return nil, false, fmt.Errorf("failed to parse image: %w", err) } diff --git a/pkg/cosign/sigstore.go b/pkg/cosign/sigstore.go index 7527a80a16..7f2c7b5f87 100644 --- a/pkg/cosign/sigstore.go +++ b/pkg/cosign/sigstore.go @@ -38,7 +38,8 @@ type Bundle struct { } func verifyBundleAndFetchAttestations(ctx context.Context, opts images.Options) ([]*VerificationResult, error) { - ref, err := name.ParseReference(opts.ImageRef) + nameOpts := opts.Client.NameOptions() + ref, err := name.ParseReference(opts.ImageRef, nameOpts...) if err != nil { return nil, errors.Wrapf(err, "failed to parse image reference: %v", opts.ImageRef) } diff --git a/pkg/cosign/sigstore_test.go b/pkg/cosign/sigstore_test.go index 4aa4501111..e65ab20cee 100644 --- a/pkg/cosign/sigstore_test.go +++ b/pkg/cosign/sigstore_test.go @@ -48,7 +48,8 @@ func TestSigstoreBundleSignatureResponse(t *testing.T) { response, err := verifier.VerifySignature(context.TODO(), opts) assert.NilError(t, err) - ref, err := name.ParseReference(opts.ImageRef) + nameOpts := rc.NameOptions() + ref, err := name.ParseReference(opts.ImageRef, nameOpts...) assert.NilError(t, err) desc, err := remote.Head(ref) @@ -74,7 +75,8 @@ func TestSigstoreBundleAttestation(t *testing.T) { response, err := verifier.FetchAttestations(context.TODO(), opts) assert.NilError(t, err) - ref, err := name.ParseReference(opts.ImageRef) + nameOpts := rc.NameOptions() + ref, err := name.ParseReference(opts.ImageRef, nameOpts...) assert.NilError(t, err) desc, err := remote.Head(ref) diff --git a/pkg/engine/adapters/rclient.go b/pkg/engine/adapters/rclient.go index 2432b12179..94ff74733a 100644 --- a/pkg/engine/adapters/rclient.go +++ b/pkg/engine/adapters/rclient.go @@ -25,7 +25,8 @@ func (a *rclientAdapter) ForRef(ctx context.Context, ref string) (*engineapi.Ima if err != nil { return nil, fmt.Errorf("failed to fetch image descriptor: %s, error: %v", ref, err) } - parsedRef, err := name.ParseReference(ref) + nameOpts := a.Client.NameOptions() + parsedRef, err := name.ParseReference(ref, nameOpts...) if err != nil { return nil, fmt.Errorf("failed to parse image reference: %s, error: %v", ref, err) } diff --git a/pkg/engine/api/client.go b/pkg/engine/api/client.go index 8af7648243..3b9ec25926 100644 --- a/pkg/engine/api/client.go +++ b/pkg/engine/api/client.go @@ -5,6 +5,7 @@ import ( "io" "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" gcrremote "github.com/google/go-containerregistry/pkg/v1/remote" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -62,6 +63,7 @@ type KeychainClient interface { type RemoteClient interface { Options(context.Context) ([]gcrremote.Option, error) + NameOptions() []name.Option } type RegistryClient interface { diff --git a/pkg/images/verifier.go b/pkg/images/verifier.go index de0f204cff..778feb98ef 100644 --- a/pkg/images/verifier.go +++ b/pkg/images/verifier.go @@ -4,6 +4,7 @@ import ( "context" "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" gcrremote "github.com/google/go-containerregistry/pkg/v1/remote" ) @@ -18,6 +19,7 @@ type ImageVerifier interface { type Client interface { Keychain() authn.Keychain Options(context.Context) ([]gcrremote.Option, error) + NameOptions() []name.Option } type Options struct { diff --git a/pkg/notary/notary.go b/pkg/notary/notary.go index 1fac9c8f16..bce0e2765f 100644 --- a/pkg/notary/notary.go +++ b/pkg/notary/notary.go @@ -136,7 +136,8 @@ func (v *notaryVerifier) verifyOutcomes(outcomes []*notation.VerificationOutcome func (v *notaryVerifier) FetchAttestations(ctx context.Context, opts images.Options) (*images.Response, error) { v.log.V(2).Info("fetching attestations", "reference", opts.ImageRef, "opts", opts) - ref, err := name.ParseReference(opts.ImageRef) + nameOpts := opts.Client.NameOptions() + ref, err := name.ParseReference(opts.ImageRef, nameOpts...) if err != nil { return nil, errors.Wrapf(err, "failed to parse image reference: %s", opts.ImageRef) } @@ -191,7 +192,7 @@ func (v *notaryVerifier) FetchAttestations(ctx context.Context, opts images.Opti } v.log.V(4).Info("extracting statements", "desc", referrer, "repo", ref) - statements, err = extractStatements(ctx, ref, referrer, remoteOpts) + statements, err = extractStatements(ctx, ref, referrer, remoteOpts, nameOpts) if err != nil { msg := err.Error() v.log.V(4).Info("failed to extract statements %s", "err", msg) @@ -272,9 +273,9 @@ func verifyAttestators(ctx context.Context, v *notaryVerifier, ref name.Referenc return targetDesc, nil } -func extractStatements(ctx context.Context, repoRef name.Reference, desc v1.Descriptor, remoteOpts []gcrremote.Option) ([]map[string]interface{}, error) { +func extractStatements(ctx context.Context, repoRef name.Reference, desc v1.Descriptor, remoteOpts []gcrremote.Option, nameOpts []name.Option) ([]map[string]interface{}, error) { statements := make([]map[string]interface{}, 0) - data, err := extractStatement(ctx, repoRef, desc, remoteOpts) + data, err := extractStatement(ctx, repoRef, desc, remoteOpts, nameOpts) if err != nil { return nil, err } @@ -286,9 +287,9 @@ func extractStatements(ctx context.Context, repoRef name.Reference, desc v1.Desc return statements, nil } -func extractStatement(ctx context.Context, repoRef name.Reference, desc v1.Descriptor, remoteOpts []gcrremote.Option) (map[string]interface{}, error) { +func extractStatement(ctx context.Context, repoRef name.Reference, desc v1.Descriptor, remoteOpts []gcrremote.Option, nameOpts []name.Option) (map[string]interface{}, error) { refStr := repoRef.Context().RegistryStr() + "/" + repoRef.Context().RepositoryStr() + "@" + desc.Digest.String() - ref, err := name.ParseReference(refStr) + ref, err := name.ParseReference(refStr, nameOpts...) if err != nil { return nil, errors.Wrapf(err, "failed to parse image reference: %s", refStr) } diff --git a/pkg/notary/notary_test.go b/pkg/notary/notary_test.go index 56151bd31c..2d58ffaed3 100644 --- a/pkg/notary/notary_test.go +++ b/pkg/notary/notary_test.go @@ -47,7 +47,7 @@ func TestExtractStatements(t *testing.T) { for _, referrer := range referrersDescs.Manifests { if referrer.ArtifactType == "application/vnd.cncf.notary.signature" { - statements, err := extractStatements(context.Background(), ref, referrer, nil) + statements, err := extractStatements(context.Background(), ref, referrer, nil, nil) assert.NilError(t, err) assert.Assert(t, len(statements) == 1) assert.Assert(t, statements[0]["type"] == referrer.ArtifactType) diff --git a/pkg/notary/registry.go b/pkg/notary/registry.go index b9f3910a32..148368fac4 100644 --- a/pkg/notary/registry.go +++ b/pkg/notary/registry.go @@ -20,7 +20,8 @@ type parsedReference struct { } func parseReferenceCrane(ctx context.Context, ref string, registryClient images.Client) (*parsedReference, error) { - nameRef, err := name.ParseReference(ref) + nameOpts := registryClient.NameOptions() + nameRef, err := name.ParseReference(ref, nameOpts...) if err != nil { return nil, err } @@ -36,7 +37,7 @@ func parseReferenceCrane(ctx context.Context, ref string, registryClient images. } if !isDigestReference(ref) { - nameRef, err = name.ParseReference(GetReferenceFromDescriptor(v1ToOciSpecDescriptor(*desc), nameRef)) + nameRef, err = name.ParseReference(GetReferenceFromDescriptor(v1ToOciSpecDescriptor(*desc), nameRef), nameOpts...) if err != nil { return nil, err } diff --git a/pkg/registryclient/client.go b/pkg/registryclient/client.go index c6a26c2796..78fcfb45ff 100644 --- a/pkg/registryclient/client.go +++ b/pkg/registryclient/client.go @@ -58,17 +58,22 @@ type Client interface { // Options returns remote.Option configuration for the client. Options(context.Context) ([]gcrremote.Option, error) + + // NameOptions returns name.Option configuration for the client. + NameOptions() []name.Option } type client struct { - keychain authn.Keychain - transport http.RoundTripper + keychain authn.Keychain + transport http.RoundTripper + allowInsecureRegistry bool } type config struct { - keychain []authn.Keychain - transport *http.Transport - tracing bool + keychain []authn.Keychain + transport *http.Transport + tracing bool + allowInsecureRegistry bool } // Option is an option to initialize registry client. @@ -94,6 +99,9 @@ func New(options ...Option) (Client, error) { if cfg.tracing { c.transport = tracing.Transport(cfg.transport, otelhttp.WithFilter(tracing.RequestFilterIsInSpan)) } + if cfg.allowInsecureRegistry { + c.allowInsecureRegistry = true + } return c, nil } @@ -147,6 +155,7 @@ func WithCredentialProviders(credentialProviders ...string) Option { func WithAllowInsecureRegistry() Option { return func(c *config) error { c.transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint:gosec + c.allowInsecureRegistry = true return nil } } @@ -191,10 +200,22 @@ func (c *client) Options(ctx context.Context) ([]gcrremote.Option, error) { return opts, nil } +// NameOptions returns name.Option config parameters for the client +func (c *client) NameOptions() []name.Option { + nameOpts := []name.Option{} + + if c.allowInsecureRegistry { + nameOpts = append(nameOpts, name.Insecure) + } + + return nameOpts +} + // FetchImageDescriptor fetches Descriptor from registry with given imageRef // and provides access to metadata about remote artifact. func (c *client) FetchImageDescriptor(ctx context.Context, imageRef string) (*gcrremote.Descriptor, error) { - parsedRef, err := name.ParseReference(imageRef) + nameOpts := c.NameOptions() + parsedRef, err := name.ParseReference(imageRef, nameOpts...) if err != nil { return nil, fmt.Errorf("failed to parse image reference: %s, error: %v", imageRef, err) }