@@ -73,6 +73,7 @@ var helmChartReadyCondition = summarize.Conditions{
7373 sourcev1 .FetchFailedCondition ,
7474 sourcev1 .StorageOperationFailedCondition ,
7575 sourcev1 .ArtifactOutdatedCondition ,
76+ sourcev1 .SourceVerifiedCondition ,
7677 meta .ReadyCondition ,
7778 meta .ReconcilingCondition ,
7879 meta .StalledCondition ,
@@ -82,6 +83,7 @@ var helmChartReadyCondition = summarize.Conditions{
8283 sourcev1 .FetchFailedCondition ,
8384 sourcev1 .StorageOperationFailedCondition ,
8485 sourcev1 .ArtifactOutdatedCondition ,
86+ sourcev1 .SourceVerifiedCondition ,
8587 meta .StalledCondition ,
8688 meta .ReconcilingCondition ,
8789 },
@@ -469,16 +471,20 @@ func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *
469471 opts .VersionMetadata = strconv .FormatInt (obj .Generation , 10 )
470472 }
471473
472- var keyring []byte
473- keyring , err = r .getProvenanceKeyring (ctx , obj )
474+ keyring , err := r .getProvenanceKeyring (ctx , obj )
474475 if err != nil {
475- conditions .MarkTrue (obj , sourcev1 .FetchFailedCondition , sourcev1 .AuthenticationFailedReason , err .Error ())
476- return sreconcile .ResultEmpty , err
476+ e := & serror.Event {
477+ Err : fmt .Errorf ("failed to get public key for chart signature verification: %w" , err ),
478+ Reason : sourcev1 .SourceVerifiedCondition ,
479+ }
480+ conditions .MarkFalse (obj , sourcev1 .FetchFailedCondition , sourcev1 .SourceVerifiedCondition , e .Error ())
481+ return sreconcile .ResultEmpty , e
477482 }
483+ opts .Keyring = keyring
478484
479485 // Build the chart
480486 ref := chart.RemoteReference {Name : obj .Spec .Chart , Version : obj .Spec .Version }
481- build , err := cb .Build (ctx , ref , util .TempPathForObj ("" , ".tgz" , obj ), opts , keyring )
487+ build , err := cb .Build (ctx , ref , util .TempPathForObj ("" , ".tgz" , obj ), opts )
482488
483489 if err != nil {
484490 return sreconcile .ResultEmpty , err
@@ -599,19 +605,23 @@ func (r *HelmChartReconciler) buildFromTarballArtifact(ctx context.Context, obj
599605 }
600606 opts .VersionMetadata += strconv .FormatInt (obj .Generation , 10 )
601607 }
602- var keyring []byte
603- keyring , err = r .getProvenanceKeyring (ctx , obj )
608+ keyring , err := r .getProvenanceKeyring (ctx , obj )
604609 if err != nil {
605- conditions .MarkTrue (obj , sourcev1 .FetchFailedCondition , sourcev1 .AuthenticationFailedReason , err .Error ())
606- return sreconcile .ResultEmpty , err
610+ e := & serror.Event {
611+ Err : fmt .Errorf ("failed to get public key for chart signature verification: %w" , err ),
612+ Reason : sourcev1 .SourceVerifiedCondition ,
613+ }
614+ conditions .MarkFalse (obj , sourcev1 .FetchFailedCondition , sourcev1 .SourceVerifiedCondition , e .Error ())
615+ return sreconcile .ResultEmpty , e
607616 }
617+ opts .Keyring = keyring
608618
609619 // Build chart
610620 cb := chart .NewLocalBuilder (dm )
611621 build , err := cb .Build (ctx , chart.LocalReference {
612622 WorkDir : sourceDir ,
613623 Path : chartPath ,
614- }, util .TempPathForObj ("" , ".tgz" , obj ), opts , keyring )
624+ }, util .TempPathForObj ("" , ".tgz" , obj ), opts )
615625 if err != nil {
616626 return sreconcile .ResultEmpty , err
617627 }
@@ -641,6 +651,14 @@ func (r *HelmChartReconciler) reconcileArtifact(ctx context.Context, obj *source
641651 conditions .Delete (obj , sourcev1 .ArtifactOutdatedCondition )
642652 conditions .MarkTrue (obj , meta .ReadyCondition , reasonForBuild (b ), b .Summary ())
643653 }
654+ if b .VerificationSignature != nil && b .ProvFilePath != "" && obj .GetArtifact () != nil {
655+ var sigVerMsg strings.Builder
656+ sigVerMsg .WriteString (fmt .Sprintf ("chart signed by: %v" , strings .Join (b .VerificationSignature .Identities [:], "," )))
657+ sigVerMsg .WriteString (fmt .Sprintf (" using key with fingeprint: %X" , b .VerificationSignature .KeyFingerprint ))
658+ sigVerMsg .WriteString (fmt .Sprintf (" and hash verified: %s" , b .VerificationSignature .FileHash ))
659+
660+ conditions .MarkTrue (obj , sourcev1 .SourceVerifiedCondition , reasonForBuild (b ), sigVerMsg .String ())
661+ }
644662 }()
645663
646664 // Create artifact from build data
@@ -692,7 +710,7 @@ func (r *HelmChartReconciler) reconcileArtifact(ctx context.Context, obj *source
692710 if err = r .Storage .CopyFromPath (& provArtifact , b .ProvFilePath ); err != nil {
693711 return sreconcile .ResultEmpty , & serror.Event {
694712 Err : fmt .Errorf ("unable to copy Helm chart provenance file to storage: %w" , err ),
695- Reason : sourcev1 .StorageOperationFailedReason ,
713+ Reason : sourcev1 .StorageOperationFailedCondition ,
696714 }
697715 }
698716 }
@@ -790,15 +808,23 @@ func (r *HelmChartReconciler) garbageCollect(ctx context.Context, obj *sourcev1.
790808 obj .Status .Artifact = nil
791809 return nil
792810 }
811+
793812 if obj .GetArtifact () != nil {
794- if deleted , err := r .Storage .RemoveAllButCurrent (* obj .GetArtifact ()); err != nil {
813+ localPath := r .Storage .LocalPath (* obj .GetArtifact ())
814+ provFilePath := localPath + ".prov"
815+ dir := filepath .Dir (localPath )
816+ callbacks := make ([]func (path string , info os.FileInfo ) bool , 0 )
817+ callbacks = append (callbacks , func (path string , info os.FileInfo ) bool {
818+ if path != localPath && path != provFilePath && info .Mode ()& os .ModeSymlink != os .ModeSymlink {
819+ return true
820+ }
821+ return false
822+ })
823+ if _ , err := r .Storage .RemoveConditionally (dir , callbacks ); err != nil {
795824 return & serror.Event {
796825 Err : fmt .Errorf ("garbage collection of old artifacts failed: %w" , err ),
797826 Reason : "GarbageCollectionFailed" ,
798827 }
799- } else if len (deleted ) > 0 {
800- r .eventLogf (ctx , obj , events .EventTypeTrace , "GarbageCollectionSucceeded" ,
801- "garbage collected old artifacts" )
802828 }
803829 }
804830 return nil
@@ -1076,20 +1102,12 @@ func (r *HelmChartReconciler) getProvenanceKeyring(ctx context.Context, chart *s
10761102 var secret corev1.Secret
10771103 err := r .Client .Get (ctx , name , & secret )
10781104 if err != nil {
1079- e := & serror.Event {
1080- Err : fmt .Errorf ("failed to get secret '%s': %w" , chart .Spec .VerificationKeyring .SecretRef .Name , err ),
1081- Reason : sourcev1 .AuthenticationFailedReason ,
1082- }
1083- return nil , e
1105+ return nil , err
10841106 }
10851107 key := chart .Spec .VerificationKeyring .Key
10861108 if val , ok := secret .Data [key ]; ! ok {
10871109 err = fmt .Errorf ("secret doesn't contain the advertised verification keyring name %s" , key )
1088- e := & serror.Event {
1089- Err : fmt .Errorf ("invalid secret '%s': %w" , secret .GetName (), err ),
1090- Reason : sourcev1 .AuthenticationFailedReason ,
1091- }
1092- return nil , e
1110+ return nil , err
10931111 } else {
10941112 return val , nil
10951113 }
0 commit comments