Skip to content

Commit 3b637a8

Browse files
committed
Add tests for keyless verification
Signed-off-by: Stefan Prodan <[email protected]>
1 parent b5ffc9f commit 3b637a8

File tree

2 files changed

+75
-4
lines changed

2 files changed

+75
-4
lines changed

controllers/ocirepository_controller.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,9 +419,12 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, obj *sour
419419
} else if !obj.GetArtifact().HasRevision(revision) ||
420420
conditions.GetObservedGeneration(obj, sourcev1.SourceVerifiedCondition) != obj.Generation ||
421421
conditions.IsFalse(obj, sourcev1.SourceVerifiedCondition) {
422-
provider := obj.Spec.Verify.Provider
423422
err := r.verifyOCISourceSignature(ctx, obj, url, keychain)
424423
if err != nil {
424+
provider := obj.Spec.Verify.Provider
425+
if obj.Spec.Verify.SecretRef == nil {
426+
provider = fmt.Sprintf("%s keyless", provider)
427+
}
425428
e := serror.NewGeneric(
426429
fmt.Errorf("failed to verify the signature using provider '%s': %w", provider, err),
427430
sourcev1.VerificationError,
@@ -570,7 +573,7 @@ func (r *OCIRepositoryReconciler) verifyOCISourceSignature(ctx context.Context,
570573
}
571574

572575
// if no secret is provided, try keyless verification
573-
ctrl.LoggerFrom(ctx).Info("no secret reference is provided, trying to verify the image using keyless approach")
576+
ctrl.LoggerFrom(ctx).Info("no secret reference is provided, trying to verify the image using keyless method")
574577
verifier, err := soci.NewVerifier(ctxTimeout, defaultCosignOciOpts...)
575578
if err != nil {
576579
return err

controllers/ocirepository_controller_test.go

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,8 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
10291029
wantErr bool
10301030
wantErrMsg string
10311031
shouldSign bool
1032+
keyless bool
1033+
beforeFunc func(obj *sourcev1.OCIRepository)
10321034
assertConditions []metav1.Condition
10331035
}{
10341036
{
@@ -1060,6 +1062,64 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
10601062
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider>': no matching signatures were found for '<url>'"),
10611063
},
10621064
},
1065+
{
1066+
name: "unsigned image should not pass keyless verification",
1067+
reference: &sourcev1.OCIRepositoryRef{
1068+
Tag: "6.1.5",
1069+
},
1070+
digest: img5.digest.Hex,
1071+
wantErr: true,
1072+
want: sreconcile.ResultEmpty,
1073+
keyless: true,
1074+
assertConditions: []metav1.Condition{
1075+
*conditions.TrueCondition(meta.ReconcilingCondition, "NewRevision", "new digest '<digest>' for '<url>'"),
1076+
*conditions.TrueCondition(sourcev1.ArtifactOutdatedCondition, "NewRevision", "new digest '<digest>' for '<url>'"),
1077+
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider> keyless': no matching signatures"),
1078+
},
1079+
},
1080+
{
1081+
name: "verify failed before, removed from spec, remove condition",
1082+
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
1083+
digest: img4.digest.Hex,
1084+
beforeFunc: func(obj *sourcev1.OCIRepository) {
1085+
conditions.MarkFalse(obj, sourcev1.SourceVerifiedCondition, "VerifyFailed", "fail msg")
1086+
obj.Spec.Verify = nil
1087+
obj.Status.Artifact = &sourcev1.Artifact{Revision: img4.digest.Hex}
1088+
},
1089+
want: sreconcile.ResultSuccess,
1090+
},
1091+
{
1092+
name: "same artifact, verified before, change in obj gen verify again",
1093+
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
1094+
digest: img4.digest.Hex,
1095+
shouldSign: true,
1096+
beforeFunc: func(obj *sourcev1.OCIRepository) {
1097+
obj.Status.Artifact = &sourcev1.Artifact{Revision: img4.digest.Hex}
1098+
// Set Verified with old observed generation and different reason/message.
1099+
conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified")
1100+
// Set new object generation.
1101+
obj.SetGeneration(3)
1102+
},
1103+
want: sreconcile.ResultSuccess,
1104+
assertConditions: []metav1.Condition{
1105+
*conditions.TrueCondition(sourcev1.SourceVerifiedCondition, meta.SucceededReason, "verified signature of digest <digest>"),
1106+
},
1107+
},
1108+
{
1109+
name: "no verify for already verified, verified condition remains the same",
1110+
reference: &sourcev1.OCIRepositoryRef{Tag: "6.1.4"},
1111+
digest: img4.digest.Hex,
1112+
shouldSign: true,
1113+
beforeFunc: func(obj *sourcev1.OCIRepository) {
1114+
// Artifact present and custom verified condition reason/message.
1115+
obj.Status.Artifact = &sourcev1.Artifact{Revision: img4.digest.Hex}
1116+
conditions.MarkTrue(obj, sourcev1.SourceVerifiedCondition, "Verified", "verified")
1117+
},
1118+
want: sreconcile.ResultSuccess,
1119+
assertConditions: []metav1.Condition{
1120+
*conditions.TrueCondition(sourcev1.SourceVerifiedCondition, "Verified", "verified"),
1121+
},
1122+
},
10631123
}
10641124

10651125
builder := fakeclient.NewClientBuilder().WithScheme(testEnv.GetScheme())
@@ -1102,13 +1162,17 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
11021162
Spec: sourcev1.OCIRepositorySpec{
11031163
URL: fmt.Sprintf("oci://%s/podinfo", server.registryHost),
11041164
Verify: &sourcev1.OCIRepositoryVerification{
1105-
Provider: "cosign",
1106-
SecretRef: &meta.LocalObjectReference{Name: "cosign-key"}},
1165+
Provider: "cosign",
1166+
},
11071167
Interval: metav1.Duration{Duration: interval},
11081168
Timeout: &metav1.Duration{Duration: timeout},
11091169
},
11101170
}
11111171

1172+
if !tt.keyless {
1173+
obj.Spec.Verify.SecretRef = &meta.LocalObjectReference{Name: "cosign-key"}
1174+
}
1175+
11121176
if tt.reference != nil {
11131177
obj.Spec.Reference = tt.reference
11141178
}
@@ -1147,6 +1211,10 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
11471211
assertConditions[k].Message = strings.ReplaceAll(assertConditions[k].Message, "<provider>", "cosign")
11481212
}
11491213

1214+
if tt.beforeFunc != nil {
1215+
tt.beforeFunc(obj)
1216+
}
1217+
11501218
artifact := &sourcev1.Artifact{}
11511219
got, err := r.reconcileSource(ctx, obj, artifact, tmpDir)
11521220
if tt.wantErr {

0 commit comments

Comments
 (0)