Add tests for keyless verification
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
This commit is contained in:
parent
b5ffc9fc65
commit
3b637a82fe
|
|
@ -419,9 +419,12 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, obj *sour
|
|||
} else if !obj.GetArtifact().HasRevision(revision) ||
|
||||
conditions.GetObservedGeneration(obj, sourcev1.SourceVerifiedCondition) != obj.Generation ||
|
||||
conditions.IsFalse(obj, sourcev1.SourceVerifiedCondition) {
|
||||
provider := obj.Spec.Verify.Provider
|
||||
err := r.verifyOCISourceSignature(ctx, obj, url, keychain)
|
||||
if err != nil {
|
||||
provider := obj.Spec.Verify.Provider
|
||||
if obj.Spec.Verify.SecretRef == nil {
|
||||
provider = fmt.Sprintf("%s keyless", provider)
|
||||
}
|
||||
e := serror.NewGeneric(
|
||||
fmt.Errorf("failed to verify the signature using provider '%s': %w", provider, err),
|
||||
sourcev1.VerificationError,
|
||||
|
|
@ -570,7 +573,7 @@ func (r *OCIRepositoryReconciler) verifyOCISourceSignature(ctx context.Context,
|
|||
}
|
||||
|
||||
// if no secret is provided, try keyless verification
|
||||
ctrl.LoggerFrom(ctx).Info("no secret reference is provided, trying to verify the image using keyless approach")
|
||||
ctrl.LoggerFrom(ctx).Info("no secret reference is provided, trying to verify the image using keyless method")
|
||||
verifier, err := soci.NewVerifier(ctxTimeout, defaultCosignOciOpts...)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -1029,6 +1029,8 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
|||
wantErr bool
|
||||
wantErrMsg string
|
||||
shouldSign bool
|
||||
keyless bool
|
||||
beforeFunc func(obj *sourcev1.OCIRepository)
|
||||
assertConditions []metav1.Condition
|
||||
}{
|
||||
{
|
||||
|
|
@ -1060,6 +1062,64 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
|||
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider>': no matching signatures were found for '<url>'"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unsigned image should not pass keyless verification",
|
||||
reference: &sourcev1.OCIRepositoryRef{
|
||||
Tag: "6.1.5",
|
||||
},
|
||||
digest: img5.digest.Hex,
|
||||
wantErr: true,
|
||||
want: sreconcile.ResultEmpty,
|
||||
keyless: true,
|
||||
assertConditions: []metav1.Condition{
|
||||
*conditions.TrueCondition(meta.ReconcilingCondition, "NewRevision", "new digest '<digest>' for '<url>'"),
|
||||
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewRevision", "new digest '<digest>' for '<url>'"),
|
||||
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider> keyless': no matching signatures"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "verify failed before, removed from spec, remove condition",
|
||||
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
|
||||
digest: img4.digest.Hex,
|
||||
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
||||
conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, "VerifyFailed", "fail msg")
|
||||
obj.Spec.Verify = nil
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: img4.digest.Hex}
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
},
|
||||
{
|
||||
name: "same artifact, verified before, change in obj gen verify again",
|
||||
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
|
||||
digest: img4.digest.Hex,
|
||||
shouldSign: true,
|
||||
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: img4.digest.Hex}
|
||||
// Set Verified with old observed generation and different reason/message.
|
||||
conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified")
|
||||
// Set new object generation.
|
||||
obj.SetGeneration(3)
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
assertConditions: []metav1.Condition{
|
||||
*conditions.TrueCondition(sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of digest <digest>"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no verify for already verified, verified condition remains the same",
|
||||
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
|
||||
digest: img4.digest.Hex,
|
||||
shouldSign: true,
|
||||
beforeFunc: func(obj *sourcev1.OCIRepository) {
|
||||
// Artifact present and custom verified condition reason/message.
|
||||
obj.Status.Artifact = &sourcev1.Artifact{Revision: img4.digest.Hex}
|
||||
conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified")
|
||||
},
|
||||
want: sreconcile.ResultSuccess,
|
||||
assertConditions: []metav1.Condition{
|
||||
*conditions.TrueCondition(sourcev1.SourceVerifiedCondition, "Verified", "verified"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
builder := fakeclient.NewClientBuilder().WithScheme(testEnv.GetScheme())
|
||||
|
|
@ -1102,13 +1162,17 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
|||
Spec: sourcev1.OCIRepositorySpec{
|
||||
URL: fmt.Sprintf("oci://%s/podinfo", server.registryHost),
|
||||
Verify: &sourcev1.OCIRepositoryVerification{
|
||||
Provider: "cosign",
|
||||
SecretRef: &meta.LocalObjectReference{Name: "cosign-key"}},
|
||||
Provider: "cosign",
|
||||
},
|
||||
Interval: metav1.Duration{Duration: interval},
|
||||
Timeout: &metav1.Duration{Duration: timeout},
|
||||
},
|
||||
}
|
||||
|
||||
if !tt.keyless {
|
||||
obj.Spec.Verify.SecretRef = &meta.LocalObjectReference{Name: "cosign-key"}
|
||||
}
|
||||
|
||||
if tt.reference != nil {
|
||||
obj.Spec.Reference = tt.reference
|
||||
}
|
||||
|
|
@ -1147,6 +1211,10 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
|
|||
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<provider>", "cosign")
|
||||
}
|
||||
|
||||
if tt.beforeFunc != nil {
|
||||
tt.beforeFunc(obj)
|
||||
}
|
||||
|
||||
artifact := &sourcev1.Artifact{}
|
||||
got, err := r.reconcileSource(ctx, obj, artifact, tmpDir)
|
||||
if tt.wantErr {
|
||||
|
|
|
|||
Loading…
Reference in New Issue