mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
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 <pradeep.vaishnav4@gmail.com> * Update pkg/registryclient/client.go Signed-off-by: Vishal Choudhary <vishal.chdhry.work@gmail.com> --------- Signed-off-by: Pradeep Lakshmi Narasimha <pradeep.vaishnav4@gmail.com> Signed-off-by: Vishal Choudhary <vishal.chdhry.work@gmail.com> Co-authored-by: Vishal Choudhary <vishal.choudhary@nirmata.com> Co-authored-by: Vishal Choudhary <vishal.chdhry.work@gmail.com>
This commit is contained in:
parent
bd3a6f066b
commit
373f942ea9
10 changed files with 54 additions and 21 deletions
|
@ -60,7 +60,8 @@ func (v *cosignVerifier) VerifySignature(ctx context.Context, opts images.Option
|
||||||
return &images.Response{Digest: results[0].Desc.Digest.String()}, nil
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse image %s", opts.ImageRef)
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nameOpts := opts.Client.NameOptions()
|
||||||
signatures, bundleVerified, err := tracing.ChildSpan3(
|
signatures, bundleVerified, err := tracing.ChildSpan3(
|
||||||
ctx,
|
ctx,
|
||||||
"",
|
"",
|
||||||
"VERIFY IMG ATTESTATIONS",
|
"VERIFY IMG ATTESTATIONS",
|
||||||
func(ctx context.Context, span trace.Span) (checkedAttestations []oci.Signature, bundleVerified bool, err error) {
|
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 {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("failed to parse image: %w", err)
|
return nil, false, fmt.Errorf("failed to parse image: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,8 @@ type Bundle struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyBundleAndFetchAttestations(ctx context.Context, opts images.Options) ([]*VerificationResult, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to parse image reference: %v", opts.ImageRef)
|
return nil, errors.Wrapf(err, "failed to parse image reference: %v", opts.ImageRef)
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,8 @@ func TestSigstoreBundleSignatureResponse(t *testing.T) {
|
||||||
response, err := verifier.VerifySignature(context.TODO(), opts)
|
response, err := verifier.VerifySignature(context.TODO(), opts)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
ref, err := name.ParseReference(opts.ImageRef)
|
nameOpts := rc.NameOptions()
|
||||||
|
ref, err := name.ParseReference(opts.ImageRef, nameOpts...)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
desc, err := remote.Head(ref)
|
desc, err := remote.Head(ref)
|
||||||
|
@ -74,7 +75,8 @@ func TestSigstoreBundleAttestation(t *testing.T) {
|
||||||
response, err := verifier.FetchAttestations(context.TODO(), opts)
|
response, err := verifier.FetchAttestations(context.TODO(), opts)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
ref, err := name.ParseReference(opts.ImageRef)
|
nameOpts := rc.NameOptions()
|
||||||
|
ref, err := name.ParseReference(opts.ImageRef, nameOpts...)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
desc, err := remote.Head(ref)
|
desc, err := remote.Head(ref)
|
||||||
|
|
|
@ -25,7 +25,8 @@ func (a *rclientAdapter) ForRef(ctx context.Context, ref string) (*engineapi.Ima
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to fetch image descriptor: %s, error: %v", ref, err)
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse image reference: %s, error: %v", ref, err)
|
return nil, fmt.Errorf("failed to parse image reference: %s, error: %v", ref, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/google/go-containerregistry/pkg/authn"
|
"github.com/google/go-containerregistry/pkg/authn"
|
||||||
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
gcrremote "github.com/google/go-containerregistry/pkg/v1/remote"
|
gcrremote "github.com/google/go-containerregistry/pkg/v1/remote"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
@ -62,6 +63,7 @@ type KeychainClient interface {
|
||||||
|
|
||||||
type RemoteClient interface {
|
type RemoteClient interface {
|
||||||
Options(context.Context) ([]gcrremote.Option, error)
|
Options(context.Context) ([]gcrremote.Option, error)
|
||||||
|
NameOptions() []name.Option
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegistryClient interface {
|
type RegistryClient interface {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/google/go-containerregistry/pkg/authn"
|
"github.com/google/go-containerregistry/pkg/authn"
|
||||||
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
gcrremote "github.com/google/go-containerregistry/pkg/v1/remote"
|
gcrremote "github.com/google/go-containerregistry/pkg/v1/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ type ImageVerifier interface {
|
||||||
type Client interface {
|
type Client interface {
|
||||||
Keychain() authn.Keychain
|
Keychain() authn.Keychain
|
||||||
Options(context.Context) ([]gcrremote.Option, error)
|
Options(context.Context) ([]gcrremote.Option, error)
|
||||||
|
NameOptions() []name.Option
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
|
|
|
@ -136,7 +136,8 @@ func (v *notaryVerifier) verifyOutcomes(outcomes []*notation.VerificationOutcome
|
||||||
func (v *notaryVerifier) FetchAttestations(ctx context.Context, opts images.Options) (*images.Response, error) {
|
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)
|
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 {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to parse image reference: %s", opts.ImageRef)
|
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)
|
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 {
|
if err != nil {
|
||||||
msg := err.Error()
|
msg := err.Error()
|
||||||
v.log.V(4).Info("failed to extract statements %s", "err", msg)
|
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
|
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)
|
statements := make([]map[string]interface{}, 0)
|
||||||
data, err := extractStatement(ctx, repoRef, desc, remoteOpts)
|
data, err := extractStatement(ctx, repoRef, desc, remoteOpts, nameOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -286,9 +287,9 @@ func extractStatements(ctx context.Context, repoRef name.Reference, desc v1.Desc
|
||||||
return statements, nil
|
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()
|
refStr := repoRef.Context().RegistryStr() + "/" + repoRef.Context().RepositoryStr() + "@" + desc.Digest.String()
|
||||||
ref, err := name.ParseReference(refStr)
|
ref, err := name.ParseReference(refStr, nameOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to parse image reference: %s", refStr)
|
return nil, errors.Wrapf(err, "failed to parse image reference: %s", refStr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ func TestExtractStatements(t *testing.T) {
|
||||||
|
|
||||||
for _, referrer := range referrersDescs.Manifests {
|
for _, referrer := range referrersDescs.Manifests {
|
||||||
if referrer.ArtifactType == "application/vnd.cncf.notary.signature" {
|
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.NilError(t, err)
|
||||||
assert.Assert(t, len(statements) == 1)
|
assert.Assert(t, len(statements) == 1)
|
||||||
assert.Assert(t, statements[0]["type"] == referrer.ArtifactType)
|
assert.Assert(t, statements[0]["type"] == referrer.ArtifactType)
|
||||||
|
|
|
@ -20,7 +20,8 @@ type parsedReference struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseReferenceCrane(ctx context.Context, ref string, registryClient images.Client) (*parsedReference, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -36,7 +37,7 @@ func parseReferenceCrane(ctx context.Context, ref string, registryClient images.
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isDigestReference(ref) {
|
if !isDigestReference(ref) {
|
||||||
nameRef, err = name.ParseReference(GetReferenceFromDescriptor(v1ToOciSpecDescriptor(*desc), nameRef))
|
nameRef, err = name.ParseReference(GetReferenceFromDescriptor(v1ToOciSpecDescriptor(*desc), nameRef), nameOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,17 +58,22 @@ type Client interface {
|
||||||
|
|
||||||
// Options returns remote.Option configuration for the client.
|
// Options returns remote.Option configuration for the client.
|
||||||
Options(context.Context) ([]gcrremote.Option, error)
|
Options(context.Context) ([]gcrremote.Option, error)
|
||||||
|
|
||||||
|
// NameOptions returns name.Option configuration for the client.
|
||||||
|
NameOptions() []name.Option
|
||||||
}
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
keychain authn.Keychain
|
keychain authn.Keychain
|
||||||
transport http.RoundTripper
|
transport http.RoundTripper
|
||||||
|
allowInsecureRegistry bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
keychain []authn.Keychain
|
keychain []authn.Keychain
|
||||||
transport *http.Transport
|
transport *http.Transport
|
||||||
tracing bool
|
tracing bool
|
||||||
|
allowInsecureRegistry bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option is an option to initialize registry client.
|
// Option is an option to initialize registry client.
|
||||||
|
@ -94,6 +99,9 @@ func New(options ...Option) (Client, error) {
|
||||||
if cfg.tracing {
|
if cfg.tracing {
|
||||||
c.transport = tracing.Transport(cfg.transport, otelhttp.WithFilter(tracing.RequestFilterIsInSpan))
|
c.transport = tracing.Transport(cfg.transport, otelhttp.WithFilter(tracing.RequestFilterIsInSpan))
|
||||||
}
|
}
|
||||||
|
if cfg.allowInsecureRegistry {
|
||||||
|
c.allowInsecureRegistry = true
|
||||||
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +155,7 @@ func WithCredentialProviders(credentialProviders ...string) Option {
|
||||||
func WithAllowInsecureRegistry() Option {
|
func WithAllowInsecureRegistry() Option {
|
||||||
return func(c *config) error {
|
return func(c *config) error {
|
||||||
c.transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint:gosec
|
c.transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint:gosec
|
||||||
|
c.allowInsecureRegistry = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,10 +200,22 @@ func (c *client) Options(ctx context.Context) ([]gcrremote.Option, error) {
|
||||||
return opts, nil
|
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
|
// FetchImageDescriptor fetches Descriptor from registry with given imageRef
|
||||||
// and provides access to metadata about remote artifact.
|
// and provides access to metadata about remote artifact.
|
||||||
func (c *client) FetchImageDescriptor(ctx context.Context, imageRef string) (*gcrremote.Descriptor, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse image reference: %s, error: %v", imageRef, err)
|
return nil, fmt.Errorf("failed to parse image reference: %s, error: %v", imageRef, err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue