mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-07 00:17:13 +00:00
* feat: add notary repository Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * feat: add notary verifier Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * feat: tests Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * feat: more tests Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: more tests Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: ci Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * feat: update types Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> --------- Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> Co-authored-by: shuting <shuting@nirmata.com>
123 lines
4 KiB
Go
123 lines
4 KiB
Go
package notary
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/go-logr/logr"
|
|
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
|
|
"github.com/kyverno/kyverno/pkg/imagedataloader"
|
|
"github.com/kyverno/kyverno/pkg/logging"
|
|
"github.com/notaryproject/notation-go"
|
|
notationlog "github.com/notaryproject/notation-go/log"
|
|
"github.com/pkg/errors"
|
|
"go.uber.org/multierr"
|
|
)
|
|
|
|
func NewVerifier() *notaryVerifier {
|
|
return ¬aryVerifier{
|
|
log: logging.WithName("Notary"),
|
|
}
|
|
}
|
|
|
|
type notaryVerifier struct {
|
|
log logr.Logger
|
|
}
|
|
|
|
func (v *notaryVerifier) VerifyImageSignature(ctx context.Context, image *imagedataloader.ImageData, attestor *policiesv1alpha1.Attestor) error {
|
|
if attestor.Notary == nil {
|
|
return fmt.Errorf("notary verifier only supports notary attestor")
|
|
}
|
|
|
|
logger := v.log.WithValues("image", image.Image, "digest", image.Digest, "attestor", attestor.Name)
|
|
logger.V(2).Info("verifying notary image signature", "image", image.Image)
|
|
|
|
vInfo, err := getVerificationInfo(image, attestor.Notary)
|
|
if err != nil {
|
|
err := errors.Wrapf(err, "failed to setup notation verification data")
|
|
logger.Error(err, "image verification failed")
|
|
return err
|
|
}
|
|
|
|
opts := notation.VerifyOptions{
|
|
ArtifactReference: image.WithDigest(image.Digest),
|
|
MaxSignatureAttempts: 10,
|
|
}
|
|
_, outcomes, err := notation.Verify(notationlog.WithLogger(ctx, NotaryLoggerAdapter(v.log.WithName("Notary Verifier Debug"))), vInfo.Verifier,
|
|
vInfo.Repo, opts)
|
|
if err != nil {
|
|
err := errors.Wrapf(err, "failed to verify image %s", image.Image)
|
|
logger.Error(err, "image verification failed")
|
|
return err
|
|
}
|
|
|
|
if err := checkVerificationOutcomes(outcomes); err != nil {
|
|
err := errors.Wrapf(err, "notation failed to verify signatures")
|
|
logger.Error(err, "image verification failed")
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (v *notaryVerifier) VerifyAttestationSignature(ctx context.Context, image *imagedataloader.ImageData, attestation *policiesv1alpha1.Attestation, attestor *policiesv1alpha1.Attestor) error {
|
|
if attestation.Referrer == nil {
|
|
return fmt.Errorf("notary verifier only supports oci 1.1 referrers as attestations")
|
|
}
|
|
if attestor.Notary == nil {
|
|
return fmt.Errorf("notary verifier only supports notary attestor")
|
|
}
|
|
|
|
logger := v.log.WithValues("image", image.Image, "digest", image.Digest, "attestation", attestation.Name, "attestor", attestor.Name) // TODO: use attestor and attestation names
|
|
logger.V(2).Info("verifying notary image signature", "image", image.Image)
|
|
|
|
vInfo, err := getVerificationInfo(image, attestor.Notary)
|
|
if err != nil {
|
|
err := errors.Wrapf(err, "failed to setup notation verification data")
|
|
logger.Error(err, "image verification failed")
|
|
return err
|
|
}
|
|
|
|
referrers, err := image.FetchRefererrs(attestation.Referrer.Type)
|
|
if err != nil {
|
|
err := errors.Wrapf(err, "failed to fetch referrers")
|
|
logger.Error(err, "image attestation verification failed")
|
|
return err
|
|
}
|
|
|
|
var errs []error
|
|
for _, r := range referrers {
|
|
reference := image.WithDigest(r.Digest.String())
|
|
logger := logger.WithValues("attestation ref", reference)
|
|
|
|
logger.V(2).Info("verifying attestation")
|
|
opts := notation.VerifyOptions{
|
|
ArtifactReference: reference,
|
|
MaxSignatureAttempts: 10,
|
|
}
|
|
|
|
_, outcomes, err := notation.Verify(notationlog.WithLogger(ctx, NotaryLoggerAdapter(v.log.WithName("Notary Verifier Debug"))), vInfo.Verifier,
|
|
vInfo.Repo, opts)
|
|
if err != nil {
|
|
err := errors.Wrapf(err, "failed to verify attestation %s, digest %s", r.ArtifactType, r.Digest)
|
|
logger.Error(err, "attestation verification failed")
|
|
errs = append(errs, err)
|
|
continue
|
|
}
|
|
|
|
if err := checkVerificationOutcomes(outcomes); err != nil {
|
|
err := errors.Wrapf(err, "notation failed to verify attesattion signatures")
|
|
logger.Error(err, "attesatation verification failed")
|
|
errs = append(errs, err)
|
|
continue
|
|
}
|
|
|
|
image.AddVerifiedReferrer(r)
|
|
return nil
|
|
}
|
|
|
|
if len(errs) == 0 {
|
|
return fmt.Errorf("attestation verification failed, no attestations found for type: %s", attestation.Referrer.Type)
|
|
}
|
|
return multierr.Combine(errs...)
|
|
}
|