diff --git a/api/kyverno/v1/image_verification_types.go b/api/kyverno/v1/image_verification_types.go index 5d2800edae..0da5308452 100644 --- a/api/kyverno/v1/image_verification_types.go +++ b/api/kyverno/v1/image_verification_types.go @@ -9,7 +9,7 @@ import ( ) // ImageVerificationType selects the type of verification algorithm -// +kubebuilder:validation:Enum=Cosign;Notary +// +kubebuilder:validation:Enum=Cosign;SigstoreBundle;Notary // +kubebuilder:default=Cosign type ImageVerificationType string @@ -18,8 +18,9 @@ type ImageVerificationType string type ImageRegistryCredentialsProvidersType string const ( - Cosign ImageVerificationType = "Cosign" - Notary ImageVerificationType = "Notary" + Cosign ImageVerificationType = "Cosign" + SigstoreBundle ImageVerificationType = "SigstoreBundle" + Notary ImageVerificationType = "Notary" DEFAULT ImageRegistryCredentialsProvidersType = "default" AWS ImageRegistryCredentialsProvidersType = "amazon" @@ -46,7 +47,7 @@ type ImageVerification struct { ValidationFailureAction *ValidationFailureAction `json:"validationFailureAction,omitempty" yaml:"validationFailureAction,omitempty"` // Type specifies the method of signature validation. The allowed options - // are Cosign and Notary. By default Cosign is used if a type is not specified. + // are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. // +kubebuilder:validation:Optional Type ImageVerificationType `json:"type,omitempty" yaml:"type,omitempty"` diff --git a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_clusterpolicies.yaml b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_clusterpolicies.yaml index bdf66e154a..b2afa99eb7 100644 --- a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_clusterpolicies.yaml +++ b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_clusterpolicies.yaml @@ -4295,9 +4295,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -8715,9 +8716,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -12879,6 +12881,7 @@ spec: are Cosign and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -17296,9 +17299,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: diff --git a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_policies.yaml b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_policies.yaml index ac323e628b..612cd99213 100644 --- a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_policies.yaml +++ b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_policies.yaml @@ -4296,9 +4296,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -8717,9 +8718,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -12882,6 +12884,7 @@ spec: are Cosign and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -17299,9 +17302,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: diff --git a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml index 86c37dd3e9..792f9c04be 100644 --- a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml +++ b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml @@ -4289,9 +4289,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -8709,9 +8710,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -12873,6 +12875,7 @@ spec: are Cosign and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -17290,9 +17293,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: diff --git a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml index 3bb6f5c610..a0f27bd5e8 100644 --- a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml +++ b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml @@ -4290,9 +4290,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -8711,9 +8712,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -12876,6 +12878,7 @@ spec: are Cosign and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -17293,9 +17296,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: diff --git a/config/crds/kyverno/kyverno.io_clusterpolicies.yaml b/config/crds/kyverno/kyverno.io_clusterpolicies.yaml index 86c37dd3e9..792f9c04be 100644 --- a/config/crds/kyverno/kyverno.io_clusterpolicies.yaml +++ b/config/crds/kyverno/kyverno.io_clusterpolicies.yaml @@ -4289,9 +4289,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -8709,9 +8710,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -12873,6 +12875,7 @@ spec: are Cosign and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -17290,9 +17293,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: diff --git a/config/crds/kyverno/kyverno.io_policies.yaml b/config/crds/kyverno/kyverno.io_policies.yaml index 3bb6f5c610..a0f27bd5e8 100644 --- a/config/crds/kyverno/kyverno.io_policies.yaml +++ b/config/crds/kyverno/kyverno.io_policies.yaml @@ -4290,9 +4290,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -8711,9 +8712,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -12876,6 +12878,7 @@ spec: are Cosign and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -17293,9 +17296,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index 6cedf4eb58..0c6156ad7c 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -9487,9 +9487,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -13907,9 +13908,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -18071,6 +18073,7 @@ spec: are Cosign and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -22488,9 +22491,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -27189,9 +27193,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -31610,9 +31615,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -35775,6 +35781,7 @@ spec: are Cosign and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: @@ -40192,9 +40199,10 @@ spec: type: description: |- Type specifies the method of signature validation. The allowed options - are Cosign and Notary. By default Cosign is used if a type is not specified. + are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. enum: - Cosign + - SigstoreBundle - Notary type: string useCache: diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index e5724029ca..b9c8a7774f 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -2410,7 +2410,7 @@ ImageVerificationType
Type specifies the method of signature validation. The allowed options -are Cosign and Notary. By default Cosign is used if a type is not specified.
+are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified.Type specifies the method of signature validation. The allowed options -are Cosign and Notary. By default Cosign is used if a type is not specified.
+are Cosign, Sigstore Bundle and Notary. By default Cosign is used if a type is not specified. diff --git a/go.mod b/go.mod index 6ee2619623..efd25c8596 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.12.0 github.com/go-logr/logr v1.4.2 - github.com/go-logr/zapr v1.3.0 + github.com/go-logr/zerologr v1.2.3 github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 github.com/google/go-containerregistry v0.20.2 github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20240530172801-3764db238e3e @@ -43,16 +43,20 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.19.0 github.com/robfig/cron v1.2.0 + github.com/rs/zerolog v1.33.0 github.com/sigstore/cosign/v2 v2.2.4 github.com/sigstore/k8s-manifest-sigstore v0.5.4 + github.com/sigstore/protobuf-specs v0.3.2 // indirect github.com/sigstore/rekor v1.3.6 github.com/sigstore/sigstore v1.8.4 + github.com/sigstore/sigstore-go v0.4.0 github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.4 github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.4 github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.4 github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.4 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 + github.com/theupdateframework/go-tuf/v2 v2.0.0-20240223092044-1e7978e83f63 // indirect github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 go.opentelemetry.io/otel v1.26.0 @@ -66,7 +70,7 @@ require ( go.opentelemetry.io/otel/trace v1.26.0 go.uber.org/automaxprocs v1.5.3 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.27.0 + go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.26.0 golang.org/x/text v0.17.0 gomodules.xyz/jsonpatch/v2 v2.4.0 @@ -94,11 +98,6 @@ require ( sigs.k8s.io/yaml v1.4.0 ) -require ( - github.com/go-logr/zerologr v1.2.3 // indirect - github.com/rs/zerolog v1.33.0 // indirect -) - require ( cloud.google.com/go v0.114.0 // indirect cloud.google.com/go/auth v0.5.1 // indirect @@ -232,7 +231,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/cel-go v0.20.1 // indirect - github.com/google/certificate-transparency-go v1.1.7 // indirect + github.com/google/certificate-transparency-go v1.1.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-github/v55 v55.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect diff --git a/go.sum b/go.sum index b01ee827cf..e553cd5eef 100644 --- a/go.sum +++ b/go.sum @@ -436,8 +436,8 @@ github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/cel-go v0.17.8 h1:j9m730pMZt1Fc4oKhCLUHfjj6527LuhYcYw0Rl8gqto= github.com/google/cel-go v0.17.8/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= -github.com/google/certificate-transparency-go v1.1.7 h1:IASD+NtgSTJLPdzkthwvAG1ZVbF2WtFg4IvoA68XGSw= -github.com/google/certificate-transparency-go v1.1.7/go.mod h1:FSSBo8fyMVgqptbfF6j5p/XNdgQftAhSmXcIxV9iphE= +github.com/google/certificate-transparency-go v1.1.8 h1:LGYKkgZF7satzgTak9R4yzfJXEeYVAjV6/EAEJOf1to= +github.com/google/certificate-transparency-go v1.1.8/go.mod h1:bV/o8r0TBKRf1X//iiiSgWrvII4d7/8OiA+3vG26gI8= github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= @@ -788,10 +788,14 @@ github.com/sigstore/fulcio v1.4.3 h1:9JcUCZjjVhRF9fmhVuz6i1RyhCc/EGCD7MOl+iqCJLQ github.com/sigstore/fulcio v1.4.3/go.mod h1:BQPWo7cfxmJwgaHlphUHUpFkp5+YxeJes82oo39m5og= github.com/sigstore/k8s-manifest-sigstore v0.5.4 h1:XPLs7Dz2OXkRdt4sgAoLxuyNSfkb/n5SwfnYb23YlRk= github.com/sigstore/k8s-manifest-sigstore v0.5.4/go.mod h1:VN/nxjuAprSy1LrutFdhc5UsrQjij4DaCYV4Wklu5zo= +github.com/sigstore/protobuf-specs v0.3.2 h1:nCVARCN+fHjlNCk3ThNXwrZRqIommIeNKWwQvORuRQo= +github.com/sigstore/protobuf-specs v0.3.2/go.mod h1:RZ0uOdJR4OB3tLQeAyWoJFbNCBFrPQdcokntde4zRBA= github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8= github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc= github.com/sigstore/sigstore v1.8.4 h1:g4ICNpiENFnWxjmBzBDWUn62rNFeny/P77HUC8da32w= github.com/sigstore/sigstore v1.8.4/go.mod h1:1jIKtkTFEeISen7en+ZPWdDHazqhxco/+v9CNjc7oNg= +github.com/sigstore/sigstore-go v0.4.0 h1:0BxofjPnd+1LzyiCgsFP0NviMg8l20ZMf4aitkvYEU8= +github.com/sigstore/sigstore-go v0.4.0/go.mod h1:KZQFwvDItf1sr5P8YhVIjjXBe1ZyeFuC4odn7/2Uie0= github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.4 h1:okxaVlaTrQowE1FA4UQ3rw54f7BUjdnzERIxbZTBZuc= github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.4/go.mod h1:jkcPErmnCECuSJajUaUq5pwCMOeBF19VzQo6bv4l1D0= github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.4 h1:1G6uLTZaqvu867DbgH7p75L6Y7Tu8LLnYJGZnWsTUu8= @@ -869,6 +873,8 @@ github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gt github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI= github.com/theupdateframework/go-tuf v0.7.0/go.mod h1:uEB7WSY+7ZIugK6R1hiBMBjQftaFzn7ZCDJcp1tCUug= +github.com/theupdateframework/go-tuf/v2 v2.0.0-20240223092044-1e7978e83f63 h1:27XWhDZHPD+cufF6qSdYx6PgGQvD2jJ6pq9sDvR6VBk= +github.com/theupdateframework/go-tuf/v2 v2.0.0-20240223092044-1e7978e83f63/go.mod h1:+gWwqe1pk4nvGeOKosGJqPgD+N/kbD9M0QVLL9TGIYU= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0= github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= @@ -928,12 +934,12 @@ go.etcd.io/etcd/client/v2 v2.305.12 h1:0m4ovXYo1CHaA/Mp3X/Fak5sRNIWf01wk/X1/G3sG go.etcd.io/etcd/client/v2 v2.305.12/go.mod h1:aQ/yhsxMu+Oht1FOupSr60oBvcS9cKXHrzBpDsPTf9E= go.etcd.io/etcd/client/v3 v3.5.13 h1:o0fHTNJLeO0MyVbc7I3fsCf6nrOqn5d+diSarKnB2js= go.etcd.io/etcd/client/v3 v3.5.13/go.mod h1:cqiAeY8b5DEEcpxvgWKsbLIWNM/8Wy2xJSDMtioMcoI= -go.etcd.io/etcd/pkg/v3 v3.5.10 h1:WPR8K0e9kWl1gAhB5A7gEa5ZBTNkT9NdNWrR8Qpo1CM= -go.etcd.io/etcd/pkg/v3 v3.5.10/go.mod h1:TKTuCKKcF1zxmfKWDkfz5qqYaE3JncKKZPFf8c1nFUs= -go.etcd.io/etcd/raft/v3 v3.5.10 h1:cgNAYe7xrsrn/5kXMSaH8kM/Ky8mAdMqGOxyYwpP0LA= -go.etcd.io/etcd/raft/v3 v3.5.10/go.mod h1:odD6kr8XQXTy9oQnyMPBOr0TVe+gT0neQhElQ6jbGRc= -go.etcd.io/etcd/server/v3 v3.5.10 h1:4NOGyOwD5sUZ22PiWYKmfxqoeh72z6EhYjNosKGLmZg= -go.etcd.io/etcd/server/v3 v3.5.10/go.mod h1:gBplPHfs6YI0L+RpGkTQO7buDbHv5HJGG/Bst0/zIPo= +go.etcd.io/etcd/pkg/v3 v3.5.12 h1:OK2fZKI5hX/+BTK76gXSTyZMrbnARyX9S643GenNGb8= +go.etcd.io/etcd/pkg/v3 v3.5.12/go.mod h1:UVwg/QIMoJncyeb/YxvJBJCE/NEwtHWashqc8A1nj/M= +go.etcd.io/etcd/raft/v3 v3.5.12 h1:7r22RufdDsq2z3STjoR7Msz6fYH8tmbkdheGfwJNRmU= +go.etcd.io/etcd/raft/v3 v3.5.12/go.mod h1:ERQuZVe79PI6vcC3DlKBukDCLja/L7YMu29B74Iwj4U= +go.etcd.io/etcd/server/v3 v3.5.12 h1:EtMjsbfyfkwZuA2JlKOiBfuGkFCekv5H178qjXypbG8= +go.etcd.io/etcd/server/v3 v3.5.12/go.mod h1:axB0oCjMy+cemo5290/CutIjoxlfA6KVYKD1w0uue10= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= diff --git a/pkg/cosign/cosign.go b/pkg/cosign/cosign.go index 16ae87d3c8..ef8dd97f41 100644 --- a/pkg/cosign/cosign.go +++ b/pkg/cosign/cosign.go @@ -47,6 +47,19 @@ func NewVerifier() images.ImageVerifier { type cosignVerifier struct{} func (v *cosignVerifier) VerifySignature(ctx context.Context, opts images.Options) (*images.Response, error) { + if opts.SigstoreBundle { + results, err := verifyBundleAndFetchAttestations(ctx, opts) + if err != nil { + return nil, err + } + + if len(results) == 0 { + return nil, fmt.Errorf("sigstore bundle verification failed: no matching signatures found") + } + + return &images.Response{Digest: results[0].Desc.Digest.String()}, nil + } + ref, err := name.ParseReference(opts.ImageRef) if err != nil { return nil, fmt.Errorf("failed to parse image %s", opts.ImageRef) @@ -266,6 +279,22 @@ func loadCertChain(pem []byte) ([]*x509.Certificate, error) { } func (v *cosignVerifier) FetchAttestations(ctx context.Context, opts images.Options) (*images.Response, error) { + if opts.SigstoreBundle { + results, err := verifyBundleAndFetchAttestations(ctx, opts) + if err != nil { + return nil, err + } + + if len(results) == 0 { + return nil, fmt.Errorf("sigstore bundle verification failed: no matching signatures found") + } + + statements, err := decodeStatementsFromBundles(results) + if err != nil { + return nil, err + } + return &images.Response{Digest: results[0].Desc.Digest.String(), Statements: statements}, nil + } cosignOpts, err := buildCosignOptions(ctx, opts) if err != nil { return nil, err diff --git a/pkg/cosign/sigstore.go b/pkg/cosign/sigstore.go new file mode 100644 index 0000000000..82cf628706 --- /dev/null +++ b/pkg/cosign/sigstore.go @@ -0,0 +1,254 @@ +package cosign + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "strings" + + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/in-toto/in-toto-golang/in_toto" + "github.com/kyverno/kyverno/pkg/images" + "github.com/kyverno/kyverno/pkg/utils/data" + "github.com/pkg/errors" + "github.com/sigstore/sigstore-go/pkg/bundle" + "github.com/sigstore/sigstore-go/pkg/root" + "github.com/sigstore/sigstore-go/pkg/verify" + "github.com/sigstore/sigstore/pkg/tuf" +) + +var ( + maxLayerSize = int64(10 * 1000 * 1000) // 10 MB + attestationlimit = 50 +) + +type VerificationResult struct { + Bundle *Bundle + Result *verify.VerificationResult + Desc *v1.Descriptor +} + +type Bundle struct { + ProtoBundle *bundle.ProtobufBundle + DSSE_Envelope *in_toto.Statement +} + +func verifyBundleAndFetchAttestations(ctx context.Context, opts images.Options) ([]*VerificationResult, error) { + ref, err := name.ParseReference(opts.ImageRef) + if err != nil { + return nil, errors.Wrapf(err, "failed to parse image reference: %v", opts.ImageRef) + } + + remoteOpts, err := opts.Client.Options(ctx) + if err != nil { + return nil, errors.Wrapf(err, "failed to create remote opts: %v", opts.ImageRef) + } + + bundles, desc, err := fetchBundles(ref, attestationlimit, opts.Type, remoteOpts) + if err != nil { + return nil, errors.Wrapf(err, "failed to fetch bundles: %v", opts.ImageRef) + } + + policy, err := buildPolicy(desc, opts) + if err != nil { + return nil, errors.Wrapf(err, "failed to build policy: %v", opts.ImageRef) + } + + verifyOpts := buildVerifyOptions(opts) + trustedMaterial, err := getTrustedRoot(ctx) + if err != nil { + return nil, errors.Wrapf(err, "failed to get trusted root: %v", opts.ImageRef) + } + + results, err := verifyBundles(bundles, desc, trustedMaterial, policy, verifyOpts) + if err != nil { + return nil, errors.Wrapf(err, "failed to get verify bundles: %v", opts.ImageRef) + } + + return results, nil +} + +func verifyBundles(bundles []*Bundle, desc *v1.Descriptor, trustedRoot *root.TrustedRoot, policy verify.PolicyBuilder, verifierOpts []verify.VerifierOption) ([]*VerificationResult, error) { + verifier, err := verify.NewSignedEntityVerifier(trustedRoot, verifierOpts...) + if err != nil { + return nil, err + } + + verificationResults := make([]*VerificationResult, 0) + for _, bundle := range bundles { + result, err := verifier.Verify(bundle.ProtoBundle, policy) + if err == nil { + verificationResults = append(verificationResults, &VerificationResult{Bundle: bundle, Result: result, Desc: desc}) + } + } + + return verificationResults, nil +} + +func fetchBundles(ref name.Reference, limit int, predicateType string, remoteOpts []remote.Option) ([]*Bundle, *v1.Descriptor, error) { + bundles := make([]*Bundle, 0) + + desc, err := remote.Head(ref, remoteOpts...) + if err != nil { + return nil, nil, err + } + + referrers, err := remote.Referrers(ref.Context().Digest(desc.Digest.String()), remoteOpts...) + if err != nil { + return nil, nil, err + } + + referrersDescs, err := referrers.IndexManifest() + if err != nil { + return nil, nil, err + } + + if len(referrersDescs.Manifests) > limit { + return nil, nil, fmt.Errorf("failed to fetch referrers: to many referrers found, max limit is %d", limit) + } + + for _, manifestDesc := range referrersDescs.Manifests { + if !strings.HasPrefix(manifestDesc.ArtifactType, "application/vnd.dev.sigstore.bundle") { + continue + } + + refImg, err := remote.Image(ref.Context().Digest(manifestDesc.Digest.String()), remoteOpts...) + if err != nil { + return nil, nil, fmt.Errorf("failed to fetch referrer image: %w", err) + } + layers, err := refImg.Layers() + if err != nil { + return nil, nil, fmt.Errorf("failed to fetch referrer layer: %w", err) + } + if len(layers) == 0 { + return nil, nil, fmt.Errorf("layers not found") + } + layer := layers[0] + layerSize, err := layer.Size() + if err != nil { + return nil, nil, err + } + if layerSize > maxLayerSize { + return nil, nil, fmt.Errorf("layer size %d exceeds %d", layerSize, maxLayerSize) + } + layerBytes, err := layer.Uncompressed() + if err != nil { + return nil, nil, fmt.Errorf("failed to fetch referrer layer: %w", err) + } + bundleBytes, err := io.ReadAll(layerBytes) + if err != nil { + return nil, nil, fmt.Errorf("failed to fetch referrer layer: %w", err) + } + b := &bundle.ProtobufBundle{} + err = b.UnmarshalJSON(bundleBytes) + if err != nil { + return nil, nil, fmt.Errorf("failed to unmarshal bundle: %w", err) + } + bundles = append(bundles, &Bundle{ProtoBundle: b}) + } + + if predicateType != "" { + filteredBundles := make([]*Bundle, 0) + for _, b := range bundles { + dsseEnvelope := b.ProtoBundle.Bundle.GetDsseEnvelope() + if dsseEnvelope != nil { + if dsseEnvelope.PayloadType != "application/vnd.in-toto+json" { + continue + } + var intotoStatement in_toto.Statement + if err := json.Unmarshal(dsseEnvelope.Payload, &intotoStatement); err != nil { + continue + } + + if intotoStatement.PredicateType == predicateType { + filteredBundles = append(filteredBundles, &Bundle{ + ProtoBundle: b.ProtoBundle, + DSSE_Envelope: &intotoStatement, + }) + } + } + } + return filteredBundles, desc, nil + } + + return bundles, desc, nil +} + +func buildPolicy(desc *v1.Descriptor, opts images.Options) (verify.PolicyBuilder, error) { + digest, err := hex.DecodeString(desc.Digest.Hex) + if err != nil { + return verify.PolicyBuilder{}, err + } + artifactDigestVerificationOption := verify.WithArtifactDigest(desc.Digest.Algorithm, digest) + + // TODO: Add full regexp support to sigstore and cosign + // Verify images only has subject field, and no subject regexp, subject cannot be passed to subject regexp + // because then string containing the subjects will also work. We should just add an issuer regexp + // Solve this in a separate PR, + // See: https://github.com/sigstore/cosign/blob/7c20052077a81d667526af879ec40168899dde1f/pkg/cosign/verify.go#L339-L356 + subjectRegexp := "" + if strings.Contains(opts.Subject, "*") { + subjectRegexp = opts.Subject + opts.Subject = "" + } + id, err := verify.NewShortCertificateIdentity(opts.Issuer, opts.Subject, "", subjectRegexp) + if err != nil { + return verify.PolicyBuilder{}, err + } + return verify.NewPolicy(artifactDigestVerificationOption, verify.WithCertificateIdentity(id)), nil +} + +func buildVerifyOptions(opts images.Options) []verify.VerifierOption { + var verifierOptions []verify.VerifierOption + if !opts.IgnoreTlog { + verifierOptions = append(verifierOptions, verify.WithTransparencyLog(1)) + } + + if !opts.IgnoreSCT { + verifierOptions = append(verifierOptions, verify.WithObserverTimestamps(1)) + } + + return verifierOptions +} + +func getTrustedRoot(ctx context.Context) (*root.TrustedRoot, error) { + tufClient, err := tuf.NewFromEnv(ctx) + if err != nil { + return nil, fmt.Errorf("initializing tuf: %w", err) + } + targetBytes, err := tufClient.GetTarget("trusted_root.json") + if err != nil { + return nil, fmt.Errorf("error getting targets: %w", err) + } + trustedRoot, err := root.NewTrustedRootFromJSON(targetBytes) + if err != nil { + return nil, fmt.Errorf("error creating trusted root: %w", err) + } + + return trustedRoot, nil +} + +func decodeStatementsFromBundles(bundles []*VerificationResult) ([]map[string]interface{}, error) { + if len(bundles) == 0 { + return []map[string]interface{}{}, nil + } + + var err error + var statement map[string]interface{} + var intotostatement in_toto.Statement + decodedStatements := make([]map[string]interface{}, len(bundles)) + for i, b := range bundles { + intotostatement = *b.Bundle.DSSE_Envelope + statement, err = data.ToMap(intotostatement) + if err != nil { + return nil, errors.Wrapf(err, "failed to decode statement: %v", intotostatement.Type) + } + statement["type"] = intotostatement.PredicateType + decodedStatements[i] = statement + } + return decodedStatements, nil +} diff --git a/pkg/cosign/sigstore_test.go b/pkg/cosign/sigstore_test.go new file mode 100644 index 0000000000..4aa4501111 --- /dev/null +++ b/pkg/cosign/sigstore_test.go @@ -0,0 +1,89 @@ +package cosign + +import ( + "context" + "testing" + + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/kyverno/kyverno/pkg/images" + "github.com/kyverno/kyverno/pkg/registryclient" + "gotest.tools/assert" +) + +func TestSigstoreBundleSignatureVerification(t *testing.T) { + opts := images.Options{ + SigstoreBundle: true, + ImageRef: "ghcr.io/vishal-chdhry/artifact-attestation-example:artifact-attestation", + Issuer: "https://token.actions.githubusercontent.com", + Subject: "https://github.com/vishal-chdhry/artifact-attestation-example/.github/workflows/build-attested-image.yaml@refs/heads/main", + } + + rc, err := registryclient.New() + assert.NilError(t, err) + opts.Client = rc + + verifier := &cosignVerifier{} + _, err = verifier.VerifySignature(context.TODO(), opts) + assert.NilError(t, err) + + opts.Subject = "invalid" + _, err = verifier.VerifySignature(context.TODO(), opts) + assert.ErrorContains(t, err, "sigstore bundle verification failed: no matching signatures found") +} + +func TestSigstoreBundleSignatureResponse(t *testing.T) { + opts := images.Options{ + SigstoreBundle: true, + ImageRef: "ghcr.io/vishal-chdhry/artifact-attestation-example:artifact-attestation", + Issuer: "https://token.actions.githubusercontent.com", + Subject: "https://github.com/vishal-chdhry/artifact-attestation-example/.github/workflows/build-attested-image.yaml@refs/heads/main", + } + + rc, err := registryclient.New() + assert.NilError(t, err) + opts.Client = rc + + verifier := &cosignVerifier{} + response, err := verifier.VerifySignature(context.TODO(), opts) + assert.NilError(t, err) + + ref, err := name.ParseReference(opts.ImageRef) + assert.NilError(t, err) + + desc, err := remote.Head(ref) + assert.NilError(t, err) + assert.Equal(t, desc.Digest.String(), response.Digest) + assert.Equal(t, len(response.Statements), 0) +} + +func TestSigstoreBundleAttestation(t *testing.T) { + opts := images.Options{ + SigstoreBundle: true, + ImageRef: "ghcr.io/vishal-chdhry/artifact-attestation-example:artifact-attestation", + Issuer: "https://token.actions.githubusercontent.com", + Subject: "https://github.com/vishal-chdhry/artifact-attestation-example/.github/workflows/build-attested-image.yaml@refs/heads/main", + Type: "https://slsa.dev/provenance/v1", + } + + rc, err := registryclient.New() + assert.NilError(t, err) + opts.Client = rc + + verifier := &cosignVerifier{} + response, err := verifier.FetchAttestations(context.TODO(), opts) + assert.NilError(t, err) + + ref, err := name.ParseReference(opts.ImageRef) + assert.NilError(t, err) + + desc, err := remote.Head(ref) + assert.NilError(t, err) + + assert.Equal(t, desc.Digest.String(), response.Digest) + assert.Assert(t, len(response.Statements) > 0) + + buildType, ok := response.Statements[0]["predicate"].(map[string]interface{})["buildDefinition"].(map[string]interface{})["buildType"].(string) + assert.Assert(t, ok) + assert.Equal(t, buildType, "https://actions.github.io/buildtypes/workflow/v1") +} diff --git a/pkg/engine/internal/imageverifier.go b/pkg/engine/internal/imageverifier.go index d248c47b0b..a628503fed 100644 --- a/pkg/engine/internal/imageverifier.go +++ b/pkg/engine/internal/imageverifier.go @@ -556,6 +556,10 @@ func (iv *ImageVerifier) buildCosignVerifier( Client: iv.rclient, } + if imageVerify.Type == kyvernov1.SigstoreBundle { + opts.SigstoreBundle = true + } + if imageVerify.Roots != "" { opts.Roots = imageVerify.Roots } diff --git a/pkg/images/verifier.go b/pkg/images/verifier.go index 13e8f6421f..de0f204cff 100644 --- a/pkg/images/verifier.go +++ b/pkg/images/verifier.go @@ -21,6 +21,7 @@ type Client interface { } type Options struct { + SigstoreBundle bool ImageRef string Client Client FetchAttestations bool diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/README.md b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/README.md new file mode 100644 index 0000000000..e8cc3d7f31 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/README.md @@ -0,0 +1,4 @@ +## Description + +This test verifies the predicate in sigstore bundle attached to an image using regex issuer + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/chainsaw-test.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/chainsaw-test.yaml new file mode 100755 index 0000000000..fd0f5064b4 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/chainsaw-test.yaml @@ -0,0 +1,20 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: sigstore-attestation-verification-regexp +spec: + steps: + - name: step-01 + try: + - apply: + file: policy.yaml + - assert: + file: policy-assert.yaml + - name: step-02 + try: + - apply: + file: pod.yaml + - assert: + file: pod-assert.yaml + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/pod-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/pod-assert.yaml new file mode 100755 index 0000000000..7ec43e84a5 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/pod-assert.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod + namespace: default + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/pod.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/pod.yaml new file mode 100755 index 0000000000..08246686e1 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod + namespace: default +spec: + containers: + - image: ghcr.io/vishal-chdhry/artifact-attestation-example:artifact-attestation + name: test-container + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/policy-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/policy-assert.yaml new file mode 100755 index 0000000000..3ebf4fa6a3 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/policy-assert.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: sigstore-attestation-verification-regexp +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/policy.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/policy.yaml new file mode 100755 index 0000000000..f8d81cc3b2 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-regexp/policy.yaml @@ -0,0 +1,36 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + pod-policies.kyverno.io/autogen-controllers: none + name: sigstore-attestation-verification-regexp +spec: + background: false + validationFailureAction: Enforce + webhookTimeoutSeconds: 30 + rules: + - match: + any: + - resources: + kinds: + - Pod + name: sigstore-attestation-verification + verifyImages: + - imageReferences: + - "*" + type: SigstoreBundle + attestations: + - attestors: + - entries: + - keyless: + issuer: https://token.actions.githubusercontent.com + subject: https://github.com/vishal-chdhry/artifact-attestation-example/.github/workflows/* + rekor: + url: https://rekor.sigstore.dev + conditions: + - all: + - key: '{{ buildDefinition.buildType }}' + operator: Equals + value: https://actions.github.io/buildtypes/workflow/v1 + type: https://slsa.dev/provenance/v1 + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/README.md b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/README.md new file mode 100644 index 0000000000..3e7e11963c --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/README.md @@ -0,0 +1,4 @@ +## Description + +This test verifies the predicate in sigstore bundle attached to an image + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/chainsaw-test.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/chainsaw-test.yaml new file mode 100755 index 0000000000..049ad3ccbe --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/chainsaw-test.yaml @@ -0,0 +1,20 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: sigstore-attestation-verification +spec: + steps: + - name: step-01 + try: + - apply: + file: policy.yaml + - assert: + file: policy-assert.yaml + - name: step-02 + try: + - apply: + file: pod.yaml + - assert: + file: pod-assert.yaml + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/pod-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/pod-assert.yaml new file mode 100755 index 0000000000..7ec43e84a5 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/pod-assert.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod + namespace: default + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/pod.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/pod.yaml new file mode 100755 index 0000000000..92af8384f3 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/pod.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod + namespace: default +spec: + containers: + - image: ghcr.io/vishal-chdhry/artifact-attestation-example:artifact-attestation + name: test-container diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/policy-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/policy-assert.yaml new file mode 100755 index 0000000000..2c0e207bd0 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/policy-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: sigstore-attestation-verification +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/policy.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/policy.yaml new file mode 100755 index 0000000000..c449c3a805 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-attestation-verification-test/policy.yaml @@ -0,0 +1,36 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + pod-policies.kyverno.io/autogen-controllers: none + name: sigstore-attestation-verification +spec: + background: false + validationFailureAction: Enforce + webhookTimeoutSeconds: 30 + rules: + - match: + any: + - resources: + kinds: + - Pod + name: sigstore-attestation-verification + verifyImages: + - imageReferences: + - "*" + type: SigstoreBundle + attestations: + - attestors: + - entries: + - keyless: + issuer: https://token.actions.githubusercontent.com + subject: https://github.com/vishal-chdhry/artifact-attestation-example/.github/workflows/build-attested-image.yaml@refs/heads/main + rekor: + url: https://rekor.sigstore.dev + conditions: + - all: + - key: '{{ buildDefinition.buildType }}' + operator: Equals + value: https://actions.github.io/buildtypes/workflow/v1 + type: https://slsa.dev/provenance/v1 + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/README.md b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/README.md new file mode 100644 index 0000000000..d34ca198bd --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/README.md @@ -0,0 +1,4 @@ +## Description + +This test verifies sigstore bundle attached to an image. + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/chainsaw-test.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/chainsaw-test.yaml new file mode 100755 index 0000000000..a98431593f --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/chainsaw-test.yaml @@ -0,0 +1,20 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: sigstore-image-verification +spec: + steps: + - name: step-01 + try: + - apply: + file: policy.yaml + - assert: + file: policy-assert.yaml + - name: step-02 + try: + - apply: + file: pod.yaml + - assert: + file: pod-assert.yaml + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/pod-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/pod-assert.yaml new file mode 100755 index 0000000000..7ec43e84a5 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/pod-assert.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod + namespace: default + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/pod.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/pod.yaml new file mode 100755 index 0000000000..08246686e1 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod + namespace: default +spec: + containers: + - image: ghcr.io/vishal-chdhry/artifact-attestation-example:artifact-attestation + name: test-container + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/policy-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/policy-assert.yaml new file mode 100755 index 0000000000..05883ad591 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/policy-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: sigstore-image-verification +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready + diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/policy.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/policy.yaml new file mode 100755 index 0000000000..1f97fe639a --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/sigstore-image-verification-test/policy.yaml @@ -0,0 +1,29 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + annotations: + pod-policies.kyverno.io/autogen-controllers: none + name: sigstore-image-verification +spec: + background: false + validationFailureAction: Enforce + webhookTimeoutSeconds: 30 + rules: + - match: + any: + - resources: + kinds: + - Pod + name: sigstore-image-verification + verifyImages: + - imageReferences: + - "*" + type: SigstoreBundle + attestors: + - entries: + - keyless: + issuer: https://token.actions.githubusercontent.com + subject: https://github.com/vishal-chdhry/artifact-attestation-example/.github/workflows/build-attested-image.yaml@refs/heads/main + rekor: + url: https://rekor.sigstore.dev +