diff --git a/api/v1/helmchart_types.go b/api/v1/helmchart_types.go index 224d8533d..bb7421443 100644 --- a/api/v1/helmchart_types.go +++ b/api/v1/helmchart_types.go @@ -86,7 +86,7 @@ type HelmChartSpec struct { // This field is only supported when using HelmRepository source with spec.type 'oci'. // Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. // +optional - Verify *OCIRepositoryVerification `json:"verify,omitempty"` + Verify *HelmChartVerification `json:"verify,omitempty"` } const ( diff --git a/api/v1/ociverification_types.go b/api/v1/ociverification_types.go index a2cf4c4ed..43c876b62 100644 --- a/api/v1/ociverification_types.go +++ b/api/v1/ociverification_types.go @@ -47,6 +47,26 @@ type OCIRepositoryVerification struct { TrustedRootSecretRef *meta.LocalObjectReference `json:"trustedRootSecretRef,omitempty"` } +// HelmChartVerification verifies the authenticity of an OCI Artifact +type HelmChartVerification struct { + // Provider specifies the technology used to sign the OCI Artifact. + // +kubebuilder:validation:Enum=cosign;notation + // +kubebuilder:default:=cosign + Provider string `json:"provider"` + + // SecretRef specifies the Kubernetes Secret containing the + // trusted public keys. + // +optional + SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"` + + // MatchOIDCIdentity specifies the identity matching criteria to use + // while verifying an OCI artifact which was signed using Cosign keyless + // signing. The artifact's identity is deemed to be verified if any of the + // specified matchers match against the identity. + // +optional + MatchOIDCIdentity []OIDCIdentityMatch `json:"matchOIDCIdentity,omitempty"` +} + // OIDCIdentityMatch specifies options for verifying the certificate identity, // i.e. the issuer and the subject of the certificate. type OIDCIdentityMatch struct { diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index dc13584ae..c8ff55417 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -588,7 +588,7 @@ func (in *HelmChartSpec) DeepCopyInto(out *HelmChartSpec) { } if in.Verify != nil { in, out := &in.Verify, &out.Verify - *out = new(OCIRepositoryVerification) + *out = new(HelmChartVerification) (*in).DeepCopyInto(*out) } } @@ -636,6 +636,31 @@ func (in *HelmChartStatus) DeepCopy() *HelmChartStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HelmChartVerification) DeepCopyInto(out *HelmChartVerification) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(meta.LocalObjectReference) + **out = **in + } + if in.MatchOIDCIdentity != nil { + in, out := &in.MatchOIDCIdentity, &out.MatchOIDCIdentity + *out = make([]OIDCIdentityMatch, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmChartVerification. +func (in *HelmChartVerification) DeepCopy() *HelmChartVerification { + if in == nil { + return nil + } + out := new(HelmChartVerification) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HelmRepository) DeepCopyInto(out *HelmRepository) { *out = *in diff --git a/config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml b/config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml index 4b57126c7..9d2848312 100644 --- a/config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml +++ b/config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml @@ -184,19 +184,6 @@ spec: required: - name type: object - trustedRootSecretRef: - description: |- - TrustedRootSecretRef specifies the Kubernetes Secret containing a - Sigstore trusted_root.json file. This enables verification against - self-hosted Sigstore infrastructure (custom Fulcio CA, self-hosted - Rekor instance). The Secret must contain a key named "trusted_root.json". - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object required: - provider type: object diff --git a/docs/api/v1/source.md b/docs/api/v1/source.md index 78cbabcea..b01da91a1 100644 --- a/docs/api/v1/source.md +++ b/docs/api/v1/source.md @@ -757,8 +757,8 @@ source.

verify
- -OCIRepositoryVerification + +HelmChartVerification @@ -2638,8 +2638,8 @@ source.

verify
- -OCIRepositoryVerification + +HelmChartVerification @@ -2787,6 +2787,70 @@ github.com/fluxcd/pkg/apis/meta.ReconcileRequestStatus +

HelmChartVerification +

+

+(Appears on: +HelmChartSpec) +

+

HelmChartVerification verifies the authenticity of an OCI Artifact

+
+
+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+provider
+ +string + +
+

Provider specifies the technology used to sign the OCI Artifact.

+
+secretRef
+ + +github.com/fluxcd/pkg/apis/meta.LocalObjectReference + + +
+(Optional) +

SecretRef specifies the Kubernetes Secret containing the +trusted public keys.

+
+matchOIDCIdentity
+ + +[]OIDCIdentityMatch + + +
+(Optional) +

MatchOIDCIdentity specifies the identity matching criteria to use +while verifying an OCI artifact which was signed using Cosign keyless +signing. The artifact’s identity is deemed to be verified if any of the +specified matchers match against the identity.

+
+
+

HelmRepositorySpec

@@ -3605,7 +3669,6 @@ github.com/fluxcd/pkg/apis/meta.ReconcileRequestStatus

(Appears on: -HelmChartSpec, OCIRepositorySpec)

OCIRepositoryVerification verifies the authenticity of an OCI Artifact

@@ -3687,6 +3750,7 @@ Rekor instance). The Secret must contain a key named “trusted_root.json&rd

(Appears on: +HelmChartVerification, OCIRepositoryVerification)

OIDCIdentityMatch specifies options for verifying the certificate identity, diff --git a/internal/controller/helmchart_controller_test.go b/internal/controller/helmchart_controller_test.go index 23188e968..0eafc426c 100644 --- a/internal/controller/helmchart_controller_test.go +++ b/internal/controller/helmchart_controller_test.go @@ -2903,7 +2903,7 @@ func TestHelmChartRepository_reconcileSource_verifyOCISourceSignature_keyless(t }, Version: tt.version, Chart: "podinfo", - Verify: &sourcev1.OCIRepositoryVerification{ + Verify: &sourcev1.HelmChartVerification{ Provider: "cosign", }, }, @@ -3017,7 +3017,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureNotation(t *t beforeFunc: func(obj *sourcev1.HelmChart) { obj.Spec.Chart = metadata.Name obj.Spec.Version = metadata.Version - obj.Spec.Verify = &sourcev1.OCIRepositoryVerification{ + obj.Spec.Verify = &sourcev1.HelmChartVerification{ Provider: "notation", SecretRef: &meta.LocalObjectReference{Name: "notation-config"}, } @@ -3036,7 +3036,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureNotation(t *t beforeFunc: func(obj *sourcev1.HelmChart) { obj.Spec.Chart = metadata.Name obj.Spec.Version = metadata.Version - obj.Spec.Verify = &sourcev1.OCIRepositoryVerification{ + obj.Spec.Verify = &sourcev1.HelmChartVerification{ Provider: "notation", SecretRef: &meta.LocalObjectReference{Name: "notation-config"}, } @@ -3057,7 +3057,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureNotation(t *t beforeFunc: func(obj *sourcev1.HelmChart) { obj.Spec.Chart = metadata.Name obj.Spec.Version = metadata.Version - obj.Spec.Verify = &sourcev1.OCIRepositoryVerification{ + obj.Spec.Verify = &sourcev1.HelmChartVerification{ Provider: "notation", SecretRef: &meta.LocalObjectReference{Name: "notation-config"}, } @@ -3096,7 +3096,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureNotation(t *t beforeFunc: func(obj *sourcev1.HelmChart) { obj.Spec.Chart = metadata.Name obj.Spec.Version = metadata.Version - obj.Spec.Verify = &sourcev1.OCIRepositoryVerification{ + obj.Spec.Verify = &sourcev1.HelmChartVerification{ Provider: "notation", SecretRef: &meta.LocalObjectReference{Name: "notation-config"}, } @@ -3116,7 +3116,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureNotation(t *t beforeFunc: func(obj *sourcev1.HelmChart) { obj.Spec.Chart = metadata.Name obj.Spec.Version = metadata.Version - obj.Spec.Verify = &sourcev1.OCIRepositoryVerification{ + obj.Spec.Verify = &sourcev1.HelmChartVerification{ Provider: "notation", SecretRef: &meta.LocalObjectReference{Name: "notation-config"}, } @@ -3341,7 +3341,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureCosign(t *tes beforeFunc: func(obj *sourcev1.HelmChart) { obj.Spec.Chart = metadata.Name obj.Spec.Version = metadata.Version - obj.Spec.Verify = &sourcev1.OCIRepositoryVerification{ + obj.Spec.Verify = &sourcev1.HelmChartVerification{ Provider: "cosign", SecretRef: &meta.LocalObjectReference{Name: "cosign-key"}, } @@ -3359,7 +3359,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureCosign(t *tes beforeFunc: func(obj *sourcev1.HelmChart) { obj.Spec.Chart = metadata.Name obj.Spec.Version = metadata.Version - obj.Spec.Verify = &sourcev1.OCIRepositoryVerification{ + obj.Spec.Verify = &sourcev1.HelmChartVerification{ Provider: "cosign", } }, @@ -3376,7 +3376,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureCosign(t *tes beforeFunc: func(obj *sourcev1.HelmChart) { obj.Spec.Chart = metadata.Name obj.Spec.Version = metadata.Version - obj.Spec.Verify = &sourcev1.OCIRepositoryVerification{ + obj.Spec.Verify = &sourcev1.HelmChartVerification{ Provider: "cosign", SecretRef: &meta.LocalObjectReference{Name: "cosign-key"}, }