diff --git a/pkg/cosign/cosign.go b/pkg/cosign/cosign.go index 54ffdb7b23..44aaf855f4 100644 --- a/pkg/cosign/cosign.go +++ b/pkg/cosign/cosign.go @@ -95,7 +95,11 @@ func buildCosignOptions(ctx context.Context, opts images.Options) (*cosign.Check "sha512": crypto.SHA512, } - remoteOpts = append(remoteOpts, opts.Client.BuildRemoteOption(ctx)) + cosignRemoteOpts, err := opts.Client.BuildCosignRemoteOption(ctx) + if err != nil { + return nil, fmt.Errorf("constructing cosign remote options: %w", err) + } + remoteOpts = append(remoteOpts, cosignRemoteOpts) cosignOpts := &cosign.CheckOpts{ Annotations: map[string]interface{}{}, RegistryClientOpts: remoteOpts, diff --git a/pkg/engine/api/client.go b/pkg/engine/api/client.go index 27e0795f13..3a4d9c3db5 100644 --- a/pkg/engine/api/client.go +++ b/pkg/engine/api/client.go @@ -6,7 +6,7 @@ import ( "github.com/google/go-containerregistry/pkg/authn" gcrremote "github.com/google/go-containerregistry/pkg/v1/remote" - "github.com/sigstore/cosign/v2/pkg/oci/remote" + cosignremote "github.com/sigstore/cosign/v2/pkg/oci/remote" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -61,12 +61,13 @@ type KeychainClient interface { Keychain() authn.Keychain } -type CosignClient interface { - BuildRemoteOption(context.Context) remote.Option +type RemoteClient interface { + BuildCosignRemoteOption(context.Context) (cosignremote.Option, error) + BuildGCRRemoteOption(context.Context) ([]gcrremote.Option, error) } type RegistryClient interface { ImageDataClient KeychainClient - CosignClient + RemoteClient } diff --git a/pkg/images/verifier.go b/pkg/images/verifier.go index 1b7fb0755a..5f11df625c 100644 --- a/pkg/images/verifier.go +++ b/pkg/images/verifier.go @@ -4,6 +4,7 @@ import ( "context" "github.com/google/go-containerregistry/pkg/authn" + gcrremote "github.com/google/go-containerregistry/pkg/v1/remote" "github.com/sigstore/cosign/v2/pkg/oci/remote" ) @@ -17,7 +18,8 @@ type ImageVerifier interface { type Client interface { Keychain() authn.Keychain - BuildRemoteOption(context.Context) remote.Option + BuildCosignRemoteOption(context.Context) (remote.Option, error) + BuildGCRRemoteOption(context.Context) ([]gcrremote.Option, error) } type Options struct { diff --git a/pkg/notary/notary.go b/pkg/notary/notary.go index ce7f3fbd8d..f33f6e5736 100644 --- a/pkg/notary/notary.go +++ b/pkg/notary/notary.go @@ -140,12 +140,7 @@ func (v *notaryVerifier) FetchAttestations(ctx context.Context, opts images.Opti if err != nil { return nil, errors.Wrapf(err, "failed to parse image reference: %s", opts.ImageRef) } - authenticator, err := getAuthenticator(ctx, opts.ImageRef, opts.Client) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse authenticator: %s", opts.ImageRef) - } - - remoteOpts, err := getRemoteOpts(*authenticator) + remoteOpts, err := opts.Client.BuildGCRRemoteOption(ctx) if err != nil { return nil, err } diff --git a/pkg/notary/registry.go b/pkg/notary/registry.go index a5862a6ab4..542c912370 100644 --- a/pkg/notary/registry.go +++ b/pkg/notary/registry.go @@ -4,7 +4,6 @@ import ( "context" "strings" - "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/name" gcrremote "github.com/google/go-containerregistry/pkg/v1/remote" "github.com/kyverno/kyverno/pkg/images" @@ -26,12 +25,7 @@ func parseReferenceCrane(ctx context.Context, ref string, registryClient images. return nil, err } - authenticator, err := getAuthenticator(ctx, ref, registryClient) - if err != nil { - return nil, err - } - - remoteOpts, err := getRemoteOpts(*authenticator) + remoteOpts, err := registryClient.BuildGCRRemoteOption(ctx) if err != nil { return nil, err } @@ -62,30 +56,6 @@ func parseReferenceCrane(ctx context.Context, ref string, registryClient images. }, nil } -type imageResource struct { - ref name.Reference -} - -func (ir *imageResource) String() string { - return ir.ref.Name() -} - -func (ir *imageResource) RegistryStr() string { - return ir.ref.Context().RegistryStr() -} - -func getAuthenticator(ctx context.Context, ref string, registryClient images.Client) (*authn.Authenticator, error) { - parsedRef, err := name.ParseReference(ref) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse registry reference %s", ref) - } - authn, err := registryClient.Keychain().Resolve(&imageResource{parsedRef}) - if err != nil { - return nil, errors.Wrapf(err, "failed to resolve auth for %s", parsedRef.String()) - } - return &authn, nil -} - func isDigestReference(reference string) bool { parts := strings.SplitN(reference, "/", 2) if len(parts) == 1 { @@ -96,25 +66,6 @@ func isDigestReference(reference string) bool { return index != -1 } -func getRemoteOpts(authenticator authn.Authenticator) ([]gcrremote.Option, error) { - remoteOpts := []gcrremote.Option{} - remoteOpts = append(remoteOpts, gcrremote.WithAuth(authenticator)) - - pusher, err := gcrremote.NewPusher(remoteOpts...) - if err != nil { - return nil, err - } - remoteOpts = append(remoteOpts, gcrremote.Reuse(pusher)) - - puller, err := gcrremote.NewPuller(remoteOpts...) - if err != nil { - return nil, err - } - remoteOpts = append(remoteOpts, gcrremote.Reuse(puller)) - - return remoteOpts, nil -} - func resolveDigestCrane(repo notationregistry.Repository, remoteOpts []gcrremote.Option, ref name.Reference) error { _, err := repo.Resolve(context.Background(), ref.Identifier()) if err != nil { diff --git a/pkg/registryclient/client.go b/pkg/registryclient/client.go index fb58b2c495..650a293ee2 100644 --- a/pkg/registryclient/client.go +++ b/pkg/registryclient/client.go @@ -54,8 +54,11 @@ type Client interface { // and provides access to metadata about remote artifact. FetchImageDescriptor(context.Context, string) (*gcrremote.Descriptor, error) - // BuildRemoteOption builds remote.Option based on client. - BuildRemoteOption(context.Context) remote.Option + // BuildCosignRemoteOption builds remote.Option for cosign client. + BuildCosignRemoteOption(context.Context) (remote.Option, error) + + // BuildGCRRemoteOption builds []gcrremote.option based on client. + BuildGCRRemoteOption(ctx context.Context) ([]gcrremote.Option, error) } type client struct { @@ -165,14 +168,40 @@ func WithTracing() Option { } } -// BuildRemoteOption builds remote.Option based on client. -func (c *client) BuildRemoteOption(ctx context.Context) remote.Option { - return remote.WithRemoteOptions( +// BuildCosignRemoteOption builds remote.Option for cosign client. +func (c *client) BuildCosignRemoteOption(ctx context.Context) (remote.Option, error) { + gcrRemoteOpts, err := c.getGCRRemoteOption(ctx) + if err != nil { + return nil, err + } + gcrRemoteOpts = append(gcrRemoteOpts, gcrremote.WithUserAgent(userAgent)) + return remote.WithRemoteOptions(gcrRemoteOpts...), nil +} + +// BuildGCRRemoteOption builds []gcrremote.Option based on client. +func (c *client) BuildGCRRemoteOption(ctx context.Context) ([]gcrremote.Option, error) { + return c.getGCRRemoteOption(ctx) +} + +func (c *client) getGCRRemoteOption(ctx context.Context) ([]gcrremote.Option, error) { + remoteOpts := []gcrremote.Option{ gcrremote.WithAuthFromKeychain(c.keychain), gcrremote.WithTransport(c.transport), gcrremote.WithContext(ctx), - gcrremote.WithUserAgent(userAgent), - ) + } + + pusher, err := gcrremote.NewPusher(remoteOpts...) + if err != nil { + return nil, err + } + remoteOpts = append(remoteOpts, gcrremote.Reuse(pusher)) + + puller, err := gcrremote.NewPuller(remoteOpts...) + if err != nil { + return nil, err + } + remoteOpts = append(remoteOpts, gcrremote.Reuse(puller)) + return remoteOpts, nil } // FetchImageDescriptor fetches Descriptor from registry with given imageRef