1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 10:28:36 +00:00

Yaml signing and verification (#4235)

* enable YAML verification using k8s-manifest-sigstore

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

comment out role and rolebinding for dryrun

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

update k8s-manifest-sigstore version

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix pubkey setting

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix pubkey setting

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix log message

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

change default value of dryrun option

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

update crd

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

support gpg signature

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* upgrade manifest sigstore version and support multi sigs

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix validate.manifest rule

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

update crd and add small fix

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix manifest verify policy

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

set cosign experimental env when keyless verification

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* improve default ignoreFields

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* fix manifest verify policy

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix manifest verify policy

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix manifest verify policy

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* add unit-test for k8smanifest

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

update install yaml

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* update k8s-manifest-sigstore version and support one or more signatures

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

add unit-test for k8smanifest multi-signature

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix verifyManifest result message

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix verifyManifest result message

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* fix manifest verify policy and move dryrun rbac to dryrun dir

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* update k8s-manifest-sigstore version

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

update k8s-manifest-sigstore version

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

update k8s-manifest-sigstore version and resolve conflict

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

enable YAML verification using k8s-manifest-sigstore

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

comment out role and rolebinding for dryrun

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix pubkey setting

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix pubkey setting

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

update crd

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

upgrade manifest sigstore version and support multi sigs

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix validate.manifest rule

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

update crd and add small fix

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix manifest verify policy

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

update k8s-manifest-sigstore version and support one or more signatures

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix verifyManifest result message

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix verifyManifest result message

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

fix manifest verify policy and move dryrun rbac to dryrun dir

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

add small fix

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* remove generic name

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* fix sonatype-lift issue and unit-test error

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* fix gofumpt error

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>

* update manifest rule to use attestor

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* remove unused value

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* resolve conflict

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix install.yaml

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix to set COSIGN_EXPERIMENTAL env variable when keyless verification

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix misspell

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* enable kyverno cli in validate.manifests rule (#3)

* enable kyverno cli in validate.manifests rule

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* update k8s-manifest-sigstore version and improve error handling for better result output

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* update crds and deepcopy

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* update unit test

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* update k8s-manifest-sigstore version

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* change to use spec.rules.exclude.subjects instead of skipUsers (#4)

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* update k8s-manifest-sigstore version

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix yaml signing sigstore (#5)

* update k8s-manifest-sigstore version

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* add a comment for dryrun option field

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* enable to include ClusterPolicy/Policy in match resource

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix log style and env variable settings

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* simplify manifest verify func

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix func name

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix sonatype warning

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix default ignoreFields

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix yaml signing sigstore rbac (#6)

* fix dryrun rbac to have minimal permissions

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix lint error

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix unit-test error

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix gofumpt error

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* fix log style

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* updated CRD documentation

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* resolve go.mod conflicts

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

* updated helm stuff

Signed-off-by: Riko Kudo <rurikudo@ibm.com>

Signed-off-by: Ruriko Kudo <rurikudo@ibm.com>
Signed-off-by: Riko Kudo <rurikudo@ibm.com>
Co-authored-by: Jim Bugwadia <jim@nirmata.com>
This commit is contained in:
Riko Kudo 2022-08-31 02:14:54 +09:00 committed by GitHub
parent bfffbeabe5
commit 5f5cda9fee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 11570 additions and 44 deletions

View file

@ -3,6 +3,7 @@ package v1
import (
"encoding/json"
"github.com/sigstore/k8s-manifest-sigstore/pkg/k8smanifest"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)
@ -292,6 +293,10 @@ type Validation struct {
// +optional
Message string `json:"message,omitempty" yaml:"message,omitempty"`
// Manifest specifies conditions for manifest verification
// +optional
Manifests *Manifests `json:"manifests,omitempty" yaml:"manifests,omitempty"`
// ForEach applies validate rules to a list of sub-elements by creating a context for each entry in the list and looping over it to apply the specified logic.
// +optional
ForEachValidation []ForEachValidation `json:"foreach,omitempty" yaml:"foreach,omitempty"`
@ -462,3 +467,38 @@ type CloneFrom struct {
// Name specifies name of the resource.
Name string `json:"name,omitempty" yaml:"name,omitempty"`
}
type Manifests struct {
// Attestors specified the required attestors (i.e. authorities)
// +kubebuilder:validation:Optional
Attestors []AttestorSet `json:"attestors,omitempty" yaml:"attestors,omitempty"`
// AnnotationDomain is custom domain of annotation for message nad signature. Default is "cosign.sigstore.dev".
// +optional
AnnotationDomain string `json:"annotationDomain,omitempty" yaml:"annotationDomain,omitempty"`
// Fields which will be ignored while comparing manifests.
// +optional
IgnoreFields IgnoreFieldList `json:"ignoreFields,omitempty" yaml:"ignoreFields,omitempty"`
// DryRun configuration
// +optional
DryRunOption DryRunOption `json:"dryRun,omitempty" yaml:"dryRun,omitempty"`
// Repository is an optional alternate OCI repository to use for resource bundle reference.
// The repository can be overridden per Attestor or Attestation.
Repository string `json:"repository,omitempty" yaml:"repository,omitempty"`
}
// DryRunOption is a configuration for dryrun.
// If enable is set to "true", manifest verification performs "dryrun & compare"
// which provides robust matching against changes by defaults and other admission controllers.
// Dryrun requires additional permissions. See config/dryrun/dryrun_rbac.yaml
type DryRunOption struct {
Enable bool `json:"enable,omitempty" yaml:"enable,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
}
type IgnoreFieldList []ObjectFieldBinding
type ObjectFieldBinding k8smanifest.ObjectFieldBinding

View file

@ -97,6 +97,11 @@ func (r *Rule) HasVerifyImages() bool {
return r.VerifyImages != nil && !reflect.DeepEqual(r.VerifyImages, ImageVerification{})
}
// HasYAMLSignatureVerify checks for validate.manifests rule
func (r Rule) HasYAMLSignatureVerify() bool {
return r.Validation.Manifests != nil && len(r.Validation.Manifests.Attestors) != 0
}
// HasImagesValidationChecks checks whether the verifyImages rule has validation checks
func (r *Rule) HasImagesValidationChecks() bool {
for _, v := range r.VerifyImages {
@ -108,6 +113,17 @@ func (r *Rule) HasImagesValidationChecks() bool {
return false
}
// HasYAMLSignatureVerify checks for validate rule
func (p *ClusterPolicy) HasYAMLSignatureVerify() bool {
for _, rule := range p.Spec.Rules {
if rule.HasYAMLSignatureVerify() {
return true
}
}
return false
}
// HasValidate checks for validate rule
func (r *Rule) HasValidate() bool {
return !reflect.DeepEqual(r.Validation, Validation{})

View file

@ -153,6 +153,17 @@ func (s *Spec) HasVerifyImages() bool {
return false
}
// HasYAMLSignatureVerify checks for image verification rules invoked during resource mutation
func (s *Spec) HasYAMLSignatureVerify() bool {
for _, rule := range s.Rules {
if rule.HasYAMLSignatureVerify() {
return true
}
}
return false
}
// BackgroundProcessingEnabled checks if background is set to true
func (s *Spec) BackgroundProcessingEnabled() bool {
if s.Background == nil {

View file

@ -20,6 +20,7 @@ limitations under the License.
package v1
import (
"github.com/sigstore/k8s-manifest-sigstore/pkg/k8smanifest"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -402,6 +403,21 @@ func (in *Deny) DeepCopy() *Deny {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DryRunOption) DeepCopyInto(out *DryRunOption) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DryRunOption.
func (in *DryRunOption) DeepCopy() *DryRunOption {
if in == nil {
return nil
}
out := new(DryRunOption)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ForEachMutation) DeepCopyInto(out *ForEachMutation) {
*out = *in
@ -616,6 +632,27 @@ func (in *Generation) DeepCopy() *Generation {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in IgnoreFieldList) DeepCopyInto(out *IgnoreFieldList) {
{
in := &in
*out = make(IgnoreFieldList, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IgnoreFieldList.
func (in IgnoreFieldList) DeepCopy() IgnoreFieldList {
if in == nil {
return nil
}
out := new(IgnoreFieldList)
in.DeepCopyInto(out)
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageExtractorConfig) DeepCopyInto(out *ImageExtractorConfig) {
*out = *in
@ -750,6 +787,36 @@ func (in *KeylessAttestor) DeepCopy() *KeylessAttestor {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Manifests) DeepCopyInto(out *Manifests) {
*out = *in
if in.Attestors != nil {
in, out := &in.Attestors, &out.Attestors
*out = make([]AttestorSet, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.IgnoreFields != nil {
in, out := &in.IgnoreFields, &out.IgnoreFields
*out = make(IgnoreFieldList, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
out.DryRunOption = in.DryRunOption
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Manifests.
func (in *Manifests) DeepCopy() *Manifests {
if in == nil {
return nil
}
out := new(Manifests)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MatchResources) DeepCopyInto(out *MatchResources) {
*out = *in
@ -813,6 +880,31 @@ func (in *Mutation) DeepCopy() *Mutation {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ObjectFieldBinding) DeepCopyInto(out *ObjectFieldBinding) {
*out = *in
if in.Fields != nil {
in, out := &in.Fields, &out.Fields
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Objects != nil {
in, out := &in.Objects, &out.Objects
*out = make(k8smanifest.ObjectReferenceList, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectFieldBinding.
func (in *ObjectFieldBinding) DeepCopy() *ObjectFieldBinding {
if in == nil {
return nil
}
out := new(ObjectFieldBinding)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Policy) DeepCopyInto(out *Policy) {
*out = *in
@ -1182,6 +1274,11 @@ func (in *UserInfo) DeepCopy() *UserInfo {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Validation) DeepCopyInto(out *Validation) {
*out = *in
if in.Manifests != nil {
in, out := &in.Manifests, &out.Manifests
*out = new(Manifests)
(*in).DeepCopyInto(*out)
}
if in.ForEachValidation != nil {
in, out := &in.ForEachValidation, &out.ForEachValidation
*out = make([]ForEachValidation, len(*in))

View file

@ -1312,6 +1312,138 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors (i.e. authorities)
items:
properties:
count:
description: Count specifies the required number of entries that must match. If the count is null, all entries must match (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a value N, then N must be less than or equal to the size of entries, and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors. An attestor can be a static key, attributes for keyless verification, or a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image verification. Every specified key-value pair must exist and match in the verified payload. The payload may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet used to specify a more complex set of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one or more certificates
properties:
cert:
description: Certificate is an optional PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an optional PEM encoded set of certificates used to verify
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute used to verify a Sigstore keyless attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions used for keyless signing.
type: object
issuer:
description: Issuer is the certificate issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked and a root certificate chain is expected instead. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set of PEM encoded trusted root certificates. If not provided, the system roots are used.
type: string
subject:
description: Subject is the verified identity used for keyless signing, for example the email address
type: string
type: object
keys:
description: Keys specifies one or more public keys
properties:
publicKeys:
description: Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly specified or can be a variable reference to a key specified in a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/). When multiple keys are specified each key is processed as a separate staticKey entry (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. If specified Repository will override other OCI image repository locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI repository to use for resource bundle reference. The repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed on failure.
type: string
@ -2817,6 +2949,138 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors (i.e. authorities)
items:
properties:
count:
description: Count specifies the required number of entries that must match. If the count is null, all entries must match (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a value N, then N must be less than or equal to the size of entries, and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors. An attestor can be a static key, attributes for keyless verification, or a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image verification. Every specified key-value pair must exist and match in the verified payload. The payload may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet used to specify a more complex set of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one or more certificates
properties:
cert:
description: Certificate is an optional PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an optional PEM encoded set of certificates used to verify
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute used to verify a Sigstore keyless attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions used for keyless signing.
type: object
issuer:
description: Issuer is the certificate issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked and a root certificate chain is expected instead. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set of PEM encoded trusted root certificates. If not provided, the system roots are used.
type: string
subject:
description: Subject is the verified identity used for keyless signing, for example the email address
type: string
type: object
keys:
description: Keys specifies one or more public keys
properties:
publicKeys:
description: Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly specified or can be a variable reference to a key specified in a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/). When multiple keys are specified each key is processed as a separate staticKey entry (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. If specified Repository will override other OCI image repository locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI repository to use for resource bundle reference. The repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed on failure.
type: string
@ -5141,6 +5405,138 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors (i.e. authorities)
items:
properties:
count:
description: Count specifies the required number of entries that must match. If the count is null, all entries must match (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a value N, then N must be less than or equal to the size of entries, and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors. An attestor can be a static key, attributes for keyless verification, or a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image verification. Every specified key-value pair must exist and match in the verified payload. The payload may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet used to specify a more complex set of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one or more certificates
properties:
cert:
description: Certificate is an optional PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an optional PEM encoded set of certificates used to verify
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute used to verify a Sigstore keyless attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions used for keyless signing.
type: object
issuer:
description: Issuer is the certificate issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked and a root certificate chain is expected instead. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set of PEM encoded trusted root certificates. If not provided, the system roots are used.
type: string
subject:
description: Subject is the verified identity used for keyless signing, for example the email address
type: string
type: object
keys:
description: Keys specifies one or more public keys
properties:
publicKeys:
description: Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly specified or can be a variable reference to a key specified in a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/). When multiple keys are specified each key is processed as a separate staticKey entry (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. If specified Repository will override other OCI image repository locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI repository to use for resource bundle reference. The repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed on failure.
type: string
@ -6646,6 +7042,138 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors (i.e. authorities)
items:
properties:
count:
description: Count specifies the required number of entries that must match. If the count is null, all entries must match (a logical AND). If the count is 1, at least one entry must match (a logical OR). If the count contains a value N, then N must be less than or equal to the size of entries, and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors. An attestor can be a static key, attributes for keyless verification, or a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image verification. Every specified key-value pair must exist and match in the verified payload. The payload may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet used to specify a more complex set of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one or more certificates
properties:
cert:
description: Certificate is an optional PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an optional PEM encoded set of certificates used to verify
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute used to verify a Sigstore keyless attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions used for keyless signing.
type: object
issuer:
description: Issuer is the certificate issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked and a root certificate chain is expected instead. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set of PEM encoded trusted root certificates. If not provided, the system roots are used.
type: string
subject:
description: Subject is the verified identity used for keyless signing, for example the email address
type: string
type: object
keys:
description: Keys specifies one or more public keys
properties:
publicKeys:
description: Keys is a set of X.509 public keys used to verify image signatures. The keys can be directly specified or can be a variable reference to a key specified in a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/). When multiple keys are specified each key is processed as a separate staticKey entry (.attestors[*].entries.keys) within the set of attestors and the count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration for the Rekor transparency log service. If the value is nil, Rekor is not checked. If an empty object is provided the public instance of Rekor (https://rekor.sigstore.dev) is used.
properties:
url:
description: URL is the address of the transparency log. Defaults to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate OCI repository to use for signatures and attestations that match this rule. If specified Repository will override other OCI image repository locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI repository to use for resource bundle reference. The repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed on failure.
type: string

View file

@ -2074,6 +2074,213 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation
for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required number
of entries that must match. If the count is
null, all entries must match (a logical AND).
If the count is 1, at least one entry must match
(a logical OR). If the count contains a value
N, then N must be less than or equal to the
size of entries, and at least N entries must
match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors.
An attestor can be a static key, attributes
for keyless verification, or a nested attestor
declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image
verification. Every specified key-value
pair must exist and match in the verified
payload. The payload may contain other
key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set of
match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one
or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an
optional PEM encoded set of certificates
used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless attestor.
See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are
certificate-extensions used for keyless
signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked and a root certificate chain
is expected instead. If an empty object
is provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set
of PEM encoded trusted root certificates.
If not provided, the system roots
are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image signatures.
The keys can be directly specified
or can be a variable reference to
a key specified in a ConfigMap (see
https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified each
key is processed as a separate staticKey
entry (.attestors[*].entries.keys)
within the set of attestors and the
count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate
OCI repository to use for signatures and
attestations that match this rule. If
specified Repository will override other
OCI image repository locations for this
Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing
manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI
repository to use for resource bundle reference. The
repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed
on failure.
@ -4579,6 +4786,219 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of
annotation for message nad signature. Default
is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required
number of entries that must match. If the
count is null, all entries must match (a
logical AND). If the count is 1, at least
one entry must match (a logical OR). If
the count contains a value N, then N must
be less than or equal to the size of entries,
and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available
attestors. An attestor can be a static key,
attributes for keyless verification, or
a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for
image verification. Every specified
key-value pair must exist and match
in the verified payload. The payload
may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set
of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies
one or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is
an optional PEM encoded set of
certificates used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless
attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions
are certificate-extensions used
for keyless signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked and a root
certificate chain is expected
instead. If an empty object is
provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional
set of PEM encoded trusted root
certificates. If not provided,
the system roots are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image
signatures. The keys can be directly
specified or can be a variable
reference to a key specified in
a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified
each key is processed as a separate
staticKey entry (.attestors[*].entries.keys)
within the set of attestors and
the count is applied across the
keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional
alternate OCI repository to use for
signatures and attestations that match
this rule. If specified Repository
will override other OCI image repository
locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while
comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate
OCI repository to use for resource bundle reference.
The repository can be overridden per Attestor
or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be
displayed on failure.

View file

@ -2075,6 +2075,213 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation
for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required number
of entries that must match. If the count is
null, all entries must match (a logical AND).
If the count is 1, at least one entry must match
(a logical OR). If the count contains a value
N, then N must be less than or equal to the
size of entries, and at least N entries must
match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors.
An attestor can be a static key, attributes
for keyless verification, or a nested attestor
declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image
verification. Every specified key-value
pair must exist and match in the verified
payload. The payload may contain other
key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set of
match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one
or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an
optional PEM encoded set of certificates
used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless attestor.
See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are
certificate-extensions used for keyless
signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked and a root certificate chain
is expected instead. If an empty object
is provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set
of PEM encoded trusted root certificates.
If not provided, the system roots
are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image signatures.
The keys can be directly specified
or can be a variable reference to
a key specified in a ConfigMap (see
https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified each
key is processed as a separate staticKey
entry (.attestors[*].entries.keys)
within the set of attestors and the
count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate
OCI repository to use for signatures and
attestations that match this rule. If
specified Repository will override other
OCI image repository locations for this
Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing
manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI
repository to use for resource bundle reference. The
repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed
on failure.
@ -4581,6 +4788,219 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of
annotation for message nad signature. Default
is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required
number of entries that must match. If the
count is null, all entries must match (a
logical AND). If the count is 1, at least
one entry must match (a logical OR). If
the count contains a value N, then N must
be less than or equal to the size of entries,
and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available
attestors. An attestor can be a static key,
attributes for keyless verification, or
a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for
image verification. Every specified
key-value pair must exist and match
in the verified payload. The payload
may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set
of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies
one or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is
an optional PEM encoded set of
certificates used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless
attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions
are certificate-extensions used
for keyless signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked and a root
certificate chain is expected
instead. If an empty object is
provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional
set of PEM encoded trusted root
certificates. If not provided,
the system roots are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image
signatures. The keys can be directly
specified or can be a variable
reference to a key specified in
a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified
each key is processed as a separate
staticKey entry (.attestors[*].entries.keys)
within the set of attestors and
the count is applied across the
keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional
alternate OCI repository to use for
signatures and attestations that match
this rule. If specified Repository
will override other OCI image repository
locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while
comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate
OCI repository to use for resource bundle reference.
The repository can be overridden per Attestor
or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be
displayed on failure.

View file

@ -0,0 +1,75 @@
# Additional permission is required to enable DryRun.
# If using DryRun to validate yaml, please deploy this Role/RoleBinding.
# If validating custom resources with DryRun, please add the resources to the role.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: manifest-verify-dry-run
namespace: kyverno
rules:
- apiGroups:
- rbac.authorization.k8s.io
resources:
- roles
- rolebindings
verbs:
- create
- apiGroups:
- ""
resources:
- bindings
- configmaps
- limitranges
- persistentvolumeclaims
- pods
- podtemplates
- replicationcontrollers
- resourcequotas
- secrets
- serviceaccounts
- services
verbs:
- create
- apiGroups:
- apps
resources:
- controllerrevisions
- daemonsets
- deployments
- replicasets
- statefulsets
verbs:
- create
- apiGroups:
- networking.k8s.io
resources:
- networkpolicies
- ingresses
verbs:
- create
- apiGroups:
- policy
resources:
- poddisruptionbudgets
verbs:
- create
- apiGroups:
- storage.k8s.io
resources:
- csistoragecapacities
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: manifest-verify-dry-run
namespace: kyverno
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: manifest-verify-dry-run
subjects:
- kind: ServiceAccount
name: kyverno-service-account
namespace: kyverno

View file

@ -2091,6 +2091,213 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation
for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required number
of entries that must match. If the count is
null, all entries must match (a logical AND).
If the count is 1, at least one entry must match
(a logical OR). If the count contains a value
N, then N must be less than or equal to the
size of entries, and at least N entries must
match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors.
An attestor can be a static key, attributes
for keyless verification, or a nested attestor
declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image
verification. Every specified key-value
pair must exist and match in the verified
payload. The payload may contain other
key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set of
match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one
or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an
optional PEM encoded set of certificates
used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless attestor.
See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are
certificate-extensions used for keyless
signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked and a root certificate chain
is expected instead. If an empty object
is provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set
of PEM encoded trusted root certificates.
If not provided, the system roots
are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image signatures.
The keys can be directly specified
or can be a variable reference to
a key specified in a ConfigMap (see
https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified each
key is processed as a separate staticKey
entry (.attestors[*].entries.keys)
within the set of attestors and the
count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate
OCI repository to use for signatures and
attestations that match this rule. If
specified Repository will override other
OCI image repository locations for this
Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing
manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI
repository to use for resource bundle reference. The
repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed
on failure.
@ -4596,6 +4803,219 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of
annotation for message nad signature. Default
is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required
number of entries that must match. If the
count is null, all entries must match (a
logical AND). If the count is 1, at least
one entry must match (a logical OR). If
the count contains a value N, then N must
be less than or equal to the size of entries,
and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available
attestors. An attestor can be a static key,
attributes for keyless verification, or
a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for
image verification. Every specified
key-value pair must exist and match
in the verified payload. The payload
may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set
of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies
one or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is
an optional PEM encoded set of
certificates used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless
attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions
are certificate-extensions used
for keyless signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked and a root
certificate chain is expected
instead. If an empty object is
provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional
set of PEM encoded trusted root
certificates. If not provided,
the system roots are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image
signatures. The keys can be directly
specified or can be a variable
reference to a key specified in
a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified
each key is processed as a separate
staticKey entry (.attestors[*].entries.keys)
within the set of attestors and
the count is applied across the
keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional
alternate OCI repository to use for
signatures and attestations that match
this rule. If specified Repository
will override other OCI image repository
locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while
comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate
OCI repository to use for resource bundle reference.
The repository can be overridden per Attestor
or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be
displayed on failure.
@ -8089,6 +8509,213 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation
for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required number
of entries that must match. If the count is
null, all entries must match (a logical AND).
If the count is 1, at least one entry must match
(a logical OR). If the count contains a value
N, then N must be less than or equal to the
size of entries, and at least N entries must
match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors.
An attestor can be a static key, attributes
for keyless verification, or a nested attestor
declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image
verification. Every specified key-value
pair must exist and match in the verified
payload. The payload may contain other
key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set of
match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one
or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an
optional PEM encoded set of certificates
used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless attestor.
See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are
certificate-extensions used for keyless
signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked and a root certificate chain
is expected instead. If an empty object
is provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set
of PEM encoded trusted root certificates.
If not provided, the system roots
are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image signatures.
The keys can be directly specified
or can be a variable reference to
a key specified in a ConfigMap (see
https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified each
key is processed as a separate staticKey
entry (.attestors[*].entries.keys)
within the set of attestors and the
count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate
OCI repository to use for signatures and
attestations that match this rule. If
specified Repository will override other
OCI image repository locations for this
Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing
manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI
repository to use for resource bundle reference. The
repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed
on failure.
@ -10595,6 +11222,219 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of
annotation for message nad signature. Default
is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required
number of entries that must match. If the
count is null, all entries must match (a
logical AND). If the count is 1, at least
one entry must match (a logical OR). If
the count contains a value N, then N must
be less than or equal to the size of entries,
and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available
attestors. An attestor can be a static key,
attributes for keyless verification, or
a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for
image verification. Every specified
key-value pair must exist and match
in the verified payload. The payload
may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set
of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies
one or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is
an optional PEM encoded set of
certificates used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless
attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions
are certificate-extensions used
for keyless signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked and a root
certificate chain is expected
instead. If an empty object is
provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional
set of PEM encoded trusted root
certificates. If not provided,
the system roots are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image
signatures. The keys can be directly
specified or can be a variable
reference to a key specified in
a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified
each key is processed as a separate
staticKey entry (.attestors[*].entries.keys)
within the set of attestors and
the count is applied across the
keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional
alternate OCI repository to use for
signatures and attestations that match
this rule. If specified Repository
will override other OCI image repository
locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while
comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate
OCI repository to use for resource bundle reference.
The repository can be overridden per Attestor
or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be
displayed on failure.

View file

@ -2089,6 +2089,213 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation
for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required number
of entries that must match. If the count is
null, all entries must match (a logical AND).
If the count is 1, at least one entry must match
(a logical OR). If the count contains a value
N, then N must be less than or equal to the
size of entries, and at least N entries must
match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors.
An attestor can be a static key, attributes
for keyless verification, or a nested attestor
declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image
verification. Every specified key-value
pair must exist and match in the verified
payload. The payload may contain other
key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set of
match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one
or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an
optional PEM encoded set of certificates
used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless attestor.
See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are
certificate-extensions used for keyless
signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked and a root certificate chain
is expected instead. If an empty object
is provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set
of PEM encoded trusted root certificates.
If not provided, the system roots
are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image signatures.
The keys can be directly specified
or can be a variable reference to
a key specified in a ConfigMap (see
https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified each
key is processed as a separate staticKey
entry (.attestors[*].entries.keys)
within the set of attestors and the
count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate
OCI repository to use for signatures and
attestations that match this rule. If
specified Repository will override other
OCI image repository locations for this
Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing
manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI
repository to use for resource bundle reference. The
repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed
on failure.
@ -4594,6 +4801,219 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of
annotation for message nad signature. Default
is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required
number of entries that must match. If the
count is null, all entries must match (a
logical AND). If the count is 1, at least
one entry must match (a logical OR). If
the count contains a value N, then N must
be less than or equal to the size of entries,
and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available
attestors. An attestor can be a static key,
attributes for keyless verification, or
a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for
image verification. Every specified
key-value pair must exist and match
in the verified payload. The payload
may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set
of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies
one or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is
an optional PEM encoded set of
certificates used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless
attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions
are certificate-extensions used
for keyless signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked and a root
certificate chain is expected
instead. If an empty object is
provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional
set of PEM encoded trusted root
certificates. If not provided,
the system roots are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image
signatures. The keys can be directly
specified or can be a variable
reference to a key specified in
a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified
each key is processed as a separate
staticKey entry (.attestors[*].entries.keys)
within the set of attestors and
the count is applied across the
keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional
alternate OCI repository to use for
signatures and attestations that match
this rule. If specified Repository
will override other OCI image repository
locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while
comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate
OCI repository to use for resource bundle reference.
The repository can be overridden per Attestor
or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be
displayed on failure.
@ -8083,6 +8503,213 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of annotation
for message nad signature. Default is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required number
of entries that must match. If the count is
null, all entries must match (a logical AND).
If the count is 1, at least one entry must match
(a logical OR). If the count contains a value
N, then N must be less than or equal to the
size of entries, and at least N entries must
match.
minimum: 1
type: integer
entries:
description: Entries contains the available attestors.
An attestor can be a static key, attributes
for keyless verification, or a nested attestor
declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for image
verification. Every specified key-value
pair must exist and match in the verified
payload. The payload may contain other
key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set of
match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies one
or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is an
optional PEM encoded set of certificates
used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless attestor.
See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are
certificate-extensions used for keyless
signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked and a root certificate chain
is expected instead. If an empty object
is provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional set
of PEM encoded trusted root certificates.
If not provided, the system roots
are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image signatures.
The keys can be directly specified
or can be a variable reference to
a key specified in a ConfigMap (see
https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified each
key is processed as a separate staticKey
entry (.attestors[*].entries.keys)
within the set of attestors and the
count is applied across the keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log service.
If the value is nil, Rekor is not
checked. If an empty object is provided
the public instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional alternate
OCI repository to use for signatures and
attestations that match this rule. If
specified Repository will override other
OCI image repository locations for this
Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while comparing
manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate OCI
repository to use for resource bundle reference. The
repository can be overridden per Attestor or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be displayed
on failure.
@ -10589,6 +11216,219 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
manifests:
description: Manifest specifies conditions for manifest
verification
properties:
annotationDomain:
description: AnnotationDomain is custom domain of
annotation for message nad signature. Default
is "cosign.sigstore.dev".
type: string
attestors:
description: Attestors specified the required attestors
(i.e. authorities)
items:
properties:
count:
description: Count specifies the required
number of entries that must match. If the
count is null, all entries must match (a
logical AND). If the count is 1, at least
one entry must match (a logical OR). If
the count contains a value N, then N must
be less than or equal to the size of entries,
and at least N entries must match.
minimum: 1
type: integer
entries:
description: Entries contains the available
attestors. An attestor can be a static key,
attributes for keyless verification, or
a nested attestor declaration.
items:
properties:
annotations:
additionalProperties:
type: string
description: Annotations are used for
image verification. Every specified
key-value pair must exist and match
in the verified payload. The payload
may contain other key-value pairs.
type: object
attestor:
description: Attestor is a nested AttestorSet
used to specify a more complex set
of match authorities
x-kubernetes-preserve-unknown-fields: true
certificates:
description: Certificates specifies
one or more certificates
properties:
cert:
description: Certificate is an optional
PEM encoded public certificate.
type: string
certChain:
description: CertificateChain is
an optional PEM encoded set of
certificates used to verify
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
keyless:
description: Keyless is a set of attribute
used to verify a Sigstore keyless
attestor. See https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions
are certificate-extensions used
for keyless signing.
type: object
issuer:
description: Issuer is the certificate
issuer used for keyless signing.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked and a root
certificate chain is expected
instead. If an empty object is
provided the public instance of
Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
roots:
description: Roots is an optional
set of PEM encoded trusted root
certificates. If not provided,
the system roots are used.
type: string
subject:
description: Subject is the verified
identity used for keyless signing,
for example the email address
type: string
type: object
keys:
description: Keys specifies one or more
public keys
properties:
publicKeys:
description: Keys is a set of X.509
public keys used to verify image
signatures. The keys can be directly
specified or can be a variable
reference to a key specified in
a ConfigMap (see https://kyverno.io/docs/writing-policies/variables/).
When multiple keys are specified
each key is processed as a separate
staticKey entry (.attestors[*].entries.keys)
within the set of attestors and
the count is applied across the
keys.
type: string
rekor:
description: Rekor provides configuration
for the Rekor transparency log
service. If the value is nil,
Rekor is not checked. If an empty
object is provided the public
instance of Rekor (https://rekor.sigstore.dev)
is used.
properties:
url:
description: URL is the address
of the transparency log. Defaults
to the public log https://rekor.sigstore.dev.
type: string
required:
- url
type: object
type: object
repository:
description: Repository is an optional
alternate OCI repository to use for
signatures and attestations that match
this rule. If specified Repository
will override other OCI image repository
locations for this Attestor.
type: string
type: object
type: array
type: object
type: array
dryRun:
description: DryRun configuration
properties:
enable:
type: boolean
namespace:
type: string
type: object
ignoreFields:
description: Fields which will be ignored while
comparing manifests.
items:
properties:
fields:
items:
type: string
type: array
objects:
items:
properties:
group:
type: string
kind:
type: string
name:
type: string
namespace:
type: string
version:
type: string
type: object
type: array
type: object
type: array
repository:
description: Repository is an optional alternate
OCI repository to use for resource bundle reference.
The repository can be overridden per Attestor
or Attestation.
type: string
type: object
message:
description: Message specifies a custom message to be
displayed on failure.

File diff suppressed because it is too large Load diff

View file

@ -792,7 +792,8 @@ If specified Repository will override other OCI image repository locations for t
</h3>
<p>
(<em>Appears on:</em>
<a href="#kyverno.io/v1.ImageVerification">ImageVerification</a>)
<a href="#kyverno.io/v1.ImageVerification">ImageVerification</a>,
<a href="#kyverno.io/v1.Manifests">Manifests</a>)
</p>
<p>
</p>
@ -1239,6 +1240,49 @@ See: <a href="https://kyverno.io/docs/writing-policies/validate/#deny-rules">htt
</tbody>
</table>
<hr />
<h3 id="kyverno.io/v1.DryRunOption">DryRunOption
</h3>
<p>
(<em>Appears on:</em>
<a href="#kyverno.io/v1.Manifests">Manifests</a>)
</p>
<p>
<p>DryRunOption is a configuration for dryrun.
If enable is set to &ldquo;true&rdquo;, manifest verification performs &ldquo;dryrun &amp; compare&rdquo;
which provides robust matching against changes by defaults and other admission controllers.
Dryrun requires additional permissions. See config/dryrun/dryrun_rbac.yaml</p>
</p>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>enable</code></br>
<em>
bool
</em>
</td>
<td>
</td>
</tr>
<tr>
<td>
<code>namespace</code></br>
<em>
string
</em>
</td>
<td>
</td>
</tr>
</tbody>
</table>
<hr />
<h3 id="kyverno.io/v1.FailurePolicyType">FailurePolicyType
(<code>string</code> alias)</p></h3>
<p>
@ -2206,6 +2250,90 @@ map[string]string
</tbody>
</table>
<hr />
<h3 id="kyverno.io/v1.Manifests">Manifests
</h3>
<p>
(<em>Appears on:</em>
<a href="#kyverno.io/v1.Validation">Validation</a>)
</p>
<p>
</p>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>attestors</code></br>
<em>
<a href="#kyverno.io/v1.AttestorSet">
[]AttestorSet
</a>
</em>
</td>
<td>
<p>Attestors specified the required attestors (i.e. authorities)</p>
</td>
</tr>
<tr>
<td>
<code>annotationDomain</code></br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>AnnotationDomain is custom domain of annotation for message nad signature. Default is &ldquo;cosign.sigstore.dev&rdquo;.</p>
</td>
</tr>
<tr>
<td>
<code>ignoreFields</code></br>
<em>
<a href="#kyverno.io/v1.IgnoreFieldList">
IgnoreFieldList
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Fields which will be ignored while comparing manifests.</p>
</td>
</tr>
<tr>
<td>
<code>dryRun</code></br>
<em>
<a href="#kyverno.io/v1.DryRunOption">
DryRunOption
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>DryRun configuration</p>
</td>
</tr>
<tr>
<td>
<code>repository</code></br>
<em>
string
</em>
</td>
<td>
<p>Repository is an optional alternate OCI repository to use for resource bundle reference.
The repository can be overridden per Attestor or Attestation.</p>
</td>
</tr>
</tbody>
</table>
<hr />
<h3 id="kyverno.io/v1.MatchResources">MatchResources
</h3>
<p>
@ -2365,6 +2493,41 @@ See <a href="https://tools.ietf.org/html/rfc6902">https://tools.ietf.org/html/rf
</tbody>
</table>
<hr />
<h3 id="kyverno.io/v1.ObjectFieldBinding">ObjectFieldBinding
</h3>
<p>
</p>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>fields</code></br>
<em>
[]string
</em>
</td>
<td>
</td>
</tr>
<tr>
<td>
<code>objects</code></br>
<em>
github.com/sigstore/k8s-manifest-sigstore/pkg/k8smanifest.ObjectReferenceList
</em>
</td>
<td>
</td>
</tr>
</tbody>
</table>
<hr />
<h3 id="kyverno.io/v1.PolicyInterface">PolicyInterface
</h3>
<p>
@ -3209,6 +3372,20 @@ string
</tr>
<tr>
<td>
<code>manifests</code></br>
<em>
<a href="#kyverno.io/v1.Manifests">
Manifests
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Manifest specifies conditions for manifest verification</p>
</td>
</tr>
<tr>
<td>
<code>foreach</code></br>
<em>
<a href="#kyverno.io/v1.ForEachValidation">

40
go.mod
View file

@ -48,7 +48,7 @@ require (
k8s.io/api v0.23.5
k8s.io/apiextensions-apiserver v0.23.4
k8s.io/apimachinery v0.23.5
k8s.io/cli-runtime v0.23.2
k8s.io/cli-runtime v0.23.5
k8s.io/client-go v0.23.5
k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89
k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf
@ -76,13 +76,17 @@ require (
google.golang.org/grpc v1.48.0
)
require github.com/sigstore/k8s-manifest-sigstore v0.3.1-0.20220810053329-14f7cab4fd52
require (
bitbucket.org/creachadair/shell v0.0.7 // indirect
cloud.google.com/go v0.103.0 // indirect
cloud.google.com/go/compute v1.7.0 // indirect
cloud.google.com/go/iam v0.3.0 // indirect
cloud.google.com/go/kms v1.4.0 // indirect
cuelang.org/go v0.4.3 // indirect
github.com/Azure/azure-sdk-for-go v66.0.0+incompatible // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.28 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect
@ -93,9 +97,13 @@ require (
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c // indirect
github.com/ThalesIgnite/crypto11 v1.2.5 // indirect
github.com/agnivade/levenshtein v1.0.1 // indirect
github.com/armon/go-metrics v0.4.0 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
@ -121,8 +129,10 @@ require (
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 // indirect
github.com/cockroachdb/apd/v2 v2.0.1 // indirect
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
github.com/containerd/stargz-snapshotter/estargz v0.12.0 // indirect
github.com/coreos/go-oidc/v3 v3.2.0 // indirect
@ -132,16 +142,20 @@ require (
github.com/cyberphone/json-canonicalization v0.0.0-20210823021906-dc406ceaf94b // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/djherbis/times v1.5.0 // indirect
github.com/docker/cli v20.10.17+incompatible // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker v20.10.17+incompatible // indirect
github.com/docker/docker-credential-helpers v0.6.4 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/emicklei/proto v1.6.15 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect
github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/fullstorydev/grpcurl v1.8.6 // indirect
github.com/fvbommel/sortorder v1.0.1 // indirect
github.com/go-chi/chi v4.1.2+incompatible // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
@ -156,9 +170,11 @@ require (
github.com/go-openapi/strfmt v0.21.3 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-openapi/validate v0.22.0 // indirect
github.com/go-piv/piv-go v1.10.0 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
@ -208,6 +224,7 @@ require (
github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b // indirect
github.com/jellydator/ttlcache/v2 v2.11.1 // indirect
github.com/jhump/protoreflect v1.12.0 // indirect
github.com/jinzhu/copier v0.3.2 // indirect
github.com/jonboulle/clockwork v0.3.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@ -226,15 +243,22 @@ require (
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect
github.com/open-policy-agent/gatekeeper v0.0.0-20210824170141-dd97b8a7e966 // indirect
github.com/open-policy-agent/opa v0.43.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
@ -246,8 +270,11 @@ require (
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/protocolbuffers/txtpbfmt v0.0.0-20201118171849-f6a6b3f636fc // indirect
github.com/r3labs/diff v1.1.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/russross/blackfriday v1.5.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74 // indirect
@ -265,8 +292,10 @@ require (
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.12.0 // indirect
github.com/spiffe/go-spiffe/v2 v2.1.1 // indirect
github.com/subosito/gotenv v1.3.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tektoncd/chains v0.3.0 // indirect
github.com/tent/canonical-json-go v0.0.0-20130607151641-96e4ba3a7613 // indirect
github.com/thales-e-security/pool v0.0.2 // indirect
github.com/theupdateframework/go-tuf v0.3.1 // indirect
@ -275,9 +304,14 @@ require (
github.com/transparency-dev/merkle v0.0.1 // indirect
github.com/urfave/cli v1.22.7 // indirect
github.com/vbatts/tar-split v0.11.2 // indirect
github.com/vektah/gqlparser/v2 v2.4.6 // indirect
github.com/xanzy/go-gitlab v0.73.1 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
github.com/yashtewari/glob-intersection v0.1.0 // indirect
github.com/zeebo/errs v1.2.2 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 // indirect
@ -317,6 +351,8 @@ require (
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
k8s.io/component-base v0.23.5 // indirect
k8s.io/kubectl v0.23.5 // indirect
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
sigs.k8s.io/release-utils v0.7.3 // indirect

802
go.sum

File diff suppressed because it is too large Load diff

401
pkg/engine/k8smanifest.go Normal file
View file

@ -0,0 +1,401 @@
package engine
import (
"crypto/rand"
"crypto/x509"
_ "embed"
"encoding/json"
"fmt"
"math"
"math/big"
"os"
"strconv"
"strings"
"github.com/ghodss/yaml"
"github.com/go-logr/logr"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/auth"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/engine/response"
"github.com/pkg/errors"
"github.com/sigstore/k8s-manifest-sigstore/pkg/k8smanifest"
"go.uber.org/multierr"
admissionv1 "k8s.io/api/admission/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
const (
DefaultAnnotationKeyDomain = "cosign.sigstore.dev"
CosignEnvVariable = "COSIGN_EXPERIMENTAL"
)
//go:embed resources/default-config.yaml
var defaultConfigBytes []byte
func processYAMLValidationRule(log logr.Logger, ctx *PolicyContext, rule *kyvernov1.Rule) *response.RuleResponse {
if isDeleteRequest(ctx) {
return nil
}
ruleResp := handleVerifyManifest(ctx, rule, log)
return ruleResp
}
func handleVerifyManifest(ctx *PolicyContext, rule *kyvernov1.Rule, logger logr.Logger) *response.RuleResponse {
verified, reason, err := verifyManifest(ctx, *rule.Validation.Manifests, logger)
if err != nil {
logger.V(3).Info("verifyManifest return err", "error", err.Error())
return ruleError(rule, response.Validation, "error occurred during manifest verification", err)
}
logger.V(3).Info("verifyManifest result", "verified", strconv.FormatBool(verified), "reason", reason)
if !verified {
return ruleResponse(*rule, response.Validation, reason, response.RuleStatusFail, nil)
}
return ruleResponse(*rule, response.Validation, reason, response.RuleStatusPass, nil)
}
func verifyManifest(policyContext *PolicyContext, verifyRule kyvernov1.Manifests, logger logr.Logger) (bool, string, error) {
// load AdmissionRequest
request, err := policyContext.JSONContext.Query("request")
if err != nil {
return false, "", errors.Wrapf(err, "failed to get a request from policyContext")
}
reqByte, _ := json.Marshal(request)
var adreq *admissionv1.AdmissionRequest
err = json.Unmarshal(reqByte, &adreq)
if err != nil {
return false, "", errors.Wrapf(err, "failed to unmarshal a request from requestByte")
}
// unmarshal admission request object
var resource unstructured.Unstructured
objectBytes := adreq.Object.Raw
err = json.Unmarshal(objectBytes, &resource)
if err != nil {
return false, "", errors.Wrapf(err, "failed to Unmarshal a requested object")
}
logger.V(4).Info("verifying manifest", "namespace", adreq.Namespace, "kind", adreq.Kind.Kind,
"name", adreq.Name, "username", adreq.UserInfo.Username)
// allow dryrun request
if adreq.DryRun != nil && *adreq.DryRun {
return true, "allowed because of DryRun request", nil
}
// prepare verifyResource option
vo := &k8smanifest.VerifyResourceOption{}
// adding default ignoreFields from
// github.com/sigstore/k8s-manifest-sigstore/blob/main/pkg/k8smanifest/resources/default-config.yaml
vo = k8smanifest.AddDefaultConfig(vo)
// adding default ignoreFields from pkg/engine/resources/default-config.yaml
vo = addDefaultConfig(vo)
// adding ignoreFields from Policy
for _, i := range verifyRule.IgnoreFields {
converted := k8smanifest.ObjectFieldBinding(i)
vo.IgnoreFields = append(vo.IgnoreFields, converted)
}
// dryrun setting
vo.DisableDryRun = !verifyRule.DryRunOption.Enable
if verifyRule.DryRunOption.Namespace != "" {
vo.DryRunNamespace = verifyRule.DryRunOption.Namespace
} else {
vo.DryRunNamespace = config.KyvernoNamespace()
}
if !vo.DisableDryRun {
// check if kyverno can 'create' dryrun resource
ok, err := checkDryRunPermission(policyContext.Client, adreq.Kind.Kind, vo.DryRunNamespace)
if err != nil {
logger.V(1).Info("failed to check permissions to 'create' resource. disabled DryRun option.", "dryrun namespace", vo.DryRunNamespace, "kind", adreq.Kind.Kind, "error", err.Error())
vo.DisableDryRun = true
}
if !ok {
logger.V(1).Info("kyverno does not have permissions to 'create' resource. disabled DryRun option.", "dryrun namespace", vo.DryRunNamespace, "kind", adreq.Kind.Kind)
vo.DisableDryRun = true
}
}
// can be overridden per Attestor
if verifyRule.Repository != "" {
vo.ResourceBundleRef = verifyRule.Repository
}
// signature annotation
// set default annotation domain
if verifyRule.AnnotationDomain != "" && verifyRule.AnnotationDomain != DefaultAnnotationKeyDomain {
vo.AnnotationConfig.AnnotationKeyDomain = verifyRule.AnnotationDomain
}
// signature verification by each attestor
verifiedMsgs := []string{}
for i, attestorSet := range verifyRule.Attestors {
path := fmt.Sprintf(".attestors[%d]", i)
verified, reason, err := verifyManifestAttestorSet(resource, attestorSet, vo, path, string(adreq.UID), logger)
if err != nil {
return verified, reason, err
}
if !verified {
return verified, reason, err
} else {
verifiedMsgs = append(verifiedMsgs, reason)
}
}
msg := fmt.Sprintf("verified manifest signatures; %s", strings.Join(verifiedMsgs, ","))
return true, msg, nil
}
func verifyManifestAttestorSet(resource unstructured.Unstructured, attestorSet kyvernov1.AttestorSet, vo *k8smanifest.VerifyResourceOption, path string, uid string, logger logr.Logger) (bool, string, error) {
verifiedCount := 0
attestorSet = expandStaticKeys(attestorSet)
requiredCount := getRequiredCount(attestorSet)
errorList := []error{}
verifiedMessageList := []string{}
failedMessageList := []string{}
for i, a := range attestorSet.Entries {
var entryError error
var verified bool
var reason string
attestorPath := fmt.Sprintf("%s.entries[%d]", path, i)
if a.Attestor != nil {
nestedAttestorSet, err := kyvernov1.AttestorSetUnmarshal(a.Attestor)
if err != nil {
entryError = errors.Wrapf(err, "failed to unmarshal nested attestor %s", attestorPath)
} else {
attestorPath += ".attestor"
verified, reason, err = verifyManifestAttestorSet(resource, *nestedAttestorSet, vo, attestorPath, uid, logger)
if err != nil {
entryError = errors.Wrapf(err, "failed to verify signature; %s", attestorPath)
}
}
} else {
verified, reason, entryError = k8sVerifyResource(resource, a, vo, attestorPath, uid, i, logger)
}
if entryError != nil {
errorList = append(errorList, entryError)
} else if verified {
// verification success.
verifiedCount++
verifiedMessageList = append(verifiedMessageList, reason)
} else {
failedMessageList = append(failedMessageList, reason)
}
if verifiedCount >= requiredCount {
logger.V(2).Info("manifest verification succeeded", "verifiedCount", verifiedCount, "requiredCount", requiredCount)
reason := fmt.Sprintf("manifest verification succeeded; verifiedCount %d; requiredCount %d; message %s",
verifiedCount, requiredCount, strings.Join(verifiedMessageList, ","))
return true, reason, nil
}
}
if len(errorList) != 0 {
err := multierr.Combine(errorList...)
logger.V(2).Info("manifest verification failed", "verifiedCount", verifiedCount, "requiredCount",
requiredCount, "errors", errorList)
return false, "", err
}
reason := fmt.Sprintf("manifest verification failed; verifiedCount %d; requiredCount %d; message %s",
verifiedCount, requiredCount, strings.Join(failedMessageList, ","))
logger.V(2).Info("manifest verification failed", "verifiedCount", verifiedCount, "requiredCount",
requiredCount, "reason", failedMessageList)
return false, reason, nil
}
func k8sVerifyResource(resource unstructured.Unstructured, a kyvernov1.Attestor, vo *k8smanifest.VerifyResourceOption, attestorPath, uid string, i int, logger logr.Logger) (bool, string, error) {
// check annotations
if a.Annotations != nil {
mnfstAnnotations := resource.GetAnnotations()
err := checkManifestAnnotations(mnfstAnnotations, a.Annotations)
if err != nil {
return false, "", err
}
}
// build verify option
vo, subPath, envVariables, err := buildVerifyResourceOptionsAndPath(a, vo, uid, i)
// unset env variables after verification
defer cleanEnvVariables(envVariables)
if err != nil {
logger.V(4).Info("failed to build verify option", err.Error())
return false, "", errors.Wrapf(err, attestorPath+subPath)
}
logger.V(4).Info("verifying resource by k8s-manifest-sigstore")
result, err := k8smanifest.VerifyResource(resource, vo)
if err != nil {
logger.V(4).Info("verifyResoource return err", err.Error())
if k8smanifest.IsSignatureNotFoundError(err) {
// no signature found
failReason := fmt.Sprintf("%s: %s", attestorPath+subPath, err.Error())
return false, failReason, nil
} else if k8smanifest.IsMessageNotFoundError(err) {
// no signature and message found
failReason := fmt.Sprintf("%s: %s", attestorPath+subPath, err.Error())
return false, failReason, nil
} else {
return false, "", errors.Wrapf(err, attestorPath+subPath)
}
} else {
resBytes, _ := json.Marshal(result)
logger.V(4).Info("verify result", string(resBytes))
if result.Verified {
// verification success.
reason := fmt.Sprintf("singed by a valid signer: %s", result.Signer)
return true, reason, nil
} else {
failReason := fmt.Sprintf("%s: %s", attestorPath+subPath, "failed to verify signature.")
if result.Diff != nil && result.Diff.Size() > 0 {
failReason = fmt.Sprintf("%s: failed to verify signature. diff found; %s", attestorPath+subPath, result.Diff.String())
} else if result.Signer != "" {
failReason = fmt.Sprintf("%s: no signer matches with this resource. signed by %s", attestorPath+subPath, result.Signer)
}
return false, failReason, nil
}
}
}
func buildVerifyResourceOptionsAndPath(a kyvernov1.Attestor, vo *k8smanifest.VerifyResourceOption, uid string, i int) (*k8smanifest.VerifyResourceOption, string, []string, error) {
subPath := ""
var entryError error
envVariables := []string{}
if a.Keys != nil {
subPath = subPath + ".keys"
Key := a.Keys.PublicKeys
if strings.HasPrefix(Key, "-----BEGIN PUBLIC KEY-----") || strings.HasPrefix(Key, "-----BEGIN PGP PUBLIC KEY BLOCK-----") {
// prepare env variable for pubkey
// it consists of admission request ID, key index and random num
n, _ := rand.Int(rand.Reader, big.NewInt(int64(math.MaxInt64)))
pubkeyEnv := fmt.Sprintf("_PK_%s_%d_%d", uid, i, n)
err := os.Setenv(pubkeyEnv, Key)
envVariables = append(envVariables, pubkeyEnv)
if err != nil {
entryError = errors.Wrapf(err, "failed to set env variable; %s", pubkeyEnv)
} else {
keyPath := fmt.Sprintf("env://%s", pubkeyEnv)
vo.KeyPath = keyPath
}
} else {
// this supports Kubernetes secrets and kms
vo.KeyPath = Key
}
if a.Keys.Rekor != nil {
vo.RekorURL = a.Keys.Rekor.URL
}
} else if a.Certificates != nil {
subPath = subPath + ".certificates"
if a.Certificates.Certificate != "" {
Cert := a.Certificates.Certificate
n, _ := rand.Int(rand.Reader, big.NewInt(int64(math.MaxInt64)))
certEnv := fmt.Sprintf("_CERT_%s_%d_%d", uid, i, n)
err := os.Setenv(certEnv, Cert)
envVariables = append(envVariables, certEnv)
if err != nil {
entryError = errors.Wrapf(err, "failed to set env variable; %s", certEnv)
} else {
certPath := fmt.Sprintf("env://%s", certEnv)
vo.Certificate = certPath
}
}
if a.Certificates.CertificateChain != "" {
CertChain := a.Certificates.CertificateChain
n, _ := rand.Int(rand.Reader, big.NewInt(int64(math.MaxInt64)))
certChainEnv := fmt.Sprintf("_CC_%s_%d_%d", uid, i, n)
err := os.Setenv(certChainEnv, CertChain)
envVariables = append(envVariables, certChainEnv)
if err != nil {
entryError = errors.Wrapf(err, "failed to set env variable; %s", certChainEnv)
} else {
certChainPath := fmt.Sprintf("env://%s", certChainEnv)
vo.CertificateChain = certChainPath
}
}
if a.Certificates.Rekor != nil {
vo.RekorURL = a.Keys.Rekor.URL
}
} else if a.Keyless != nil {
subPath = subPath + ".keyless"
_ = os.Setenv(CosignEnvVariable, "1")
envVariables = append(envVariables, CosignEnvVariable)
if a.Keyless.Rekor != nil {
vo.RekorURL = a.Keyless.Rekor.URL
}
if a.Keyless.Roots != "" {
Roots := a.Keyless.Roots
cp, err := loadCertPool([]byte(Roots))
if err != nil {
entryError = errors.Wrap(err, "failed to load Root certificates")
} else {
vo.RootCerts = cp
}
}
Issuer := a.Keyless.Issuer
vo.OIDCIssuer = Issuer
Subject := a.Keyless.Subject
vo.Signers = k8smanifest.SignerList{Subject}
}
if a.Repository != "" {
vo.ResourceBundleRef = a.Repository
}
return vo, subPath, envVariables, entryError
}
func cleanEnvVariables(envVariables []string) {
for _, ev := range envVariables {
os.Unsetenv(ev)
}
}
func addConfig(vo, defaultConfig *k8smanifest.VerifyResourceOption) *k8smanifest.VerifyResourceOption {
if vo == nil {
return nil
}
ignoreFields := []k8smanifest.ObjectFieldBinding(vo.IgnoreFields)
ignoreFields = append(ignoreFields, []k8smanifest.ObjectFieldBinding(defaultConfig.IgnoreFields)...)
vo.IgnoreFields = ignoreFields
return vo
}
func loadDefaultConfig() *k8smanifest.VerifyResourceOption {
var defaultConfig *k8smanifest.VerifyResourceOption
err := yaml.Unmarshal(defaultConfigBytes, &defaultConfig)
if err != nil {
return nil
}
return defaultConfig
}
func addDefaultConfig(vo *k8smanifest.VerifyResourceOption) *k8smanifest.VerifyResourceOption {
dvo := loadDefaultConfig()
return addConfig(vo, dvo)
}
func loadCertPool(roots []byte) (*x509.CertPool, error) {
cp := x509.NewCertPool()
if !cp.AppendCertsFromPEM(roots) {
return nil, fmt.Errorf("error creating root cert pool")
}
return cp, nil
}
func checkManifestAnnotations(mnfstAnnotations map[string]string, annotations map[string]string) error {
for key, val := range annotations {
if val != mnfstAnnotations[key] {
return fmt.Errorf("annotations mismatch: %s does not match expected value %s for key %s",
mnfstAnnotations[key], val, key)
}
}
return nil
}
func checkDryRunPermission(dclient dclient.Interface, kind, namespace string) (bool, error) {
canI := auth.NewCanI(dclient, kind, namespace, "create")
ok, err := canI.RunAccessCheck()
if err != nil {
return false, err
}
return ok, nil
}

View file

@ -0,0 +1,766 @@
package engine
import (
"encoding/json"
"testing"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"gotest.tools/assert"
v1 "k8s.io/api/admission/v1"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)
var test_policy = `{}`
var signed_resource = `{
"apiVersion": "v1",
"data": {
"comment": "comment1",
"key1": "val1",
"key2": "val2"
},
"kind": "ConfigMap",
"metadata": {
"annotations": {
"cosign.sigstore.dev/message": "H4sIAAAAAAAA/wD8AAP/H4sIAAAAAAAA/+zRu27DIBQGYGaeghdIOVzsNKydu1Vdq9MYW5Y54AKJmjx9leuYsVUlf8vPz2U4Qu4xyz6Fzuci41EqeJ7C19DpGj+BDNFHMGS/LQDAEOWb3Caasy9ljMOqYl4Nx2azMQBGyYI0B7/a0tMBKbC709vW2nOu2+acoC/9RDVrpqyGprXQasPAQKvWTAD7BbtSMTOAPO269OBeqdj3D86vs9zzn8B5fPe5jCk6sVd8GmPnxEuK/Ti84szJV+ywouNCRCTvxP2T+W1/8gflxB6DuhR9LpoLsU1EPlZ3Wyj+1+MuFovF4uonAAD//3weCWIACAAAAQAA//+Nc9ey/AAAAA==",
"cosign.sigstore.dev/signature": "MEYCIQCTNFfObr0DiBCbDYEq0clxRw0FeoY35LhEiIFrGU7bZAIhAJR7AEYHIXkCPGlPIXA8ao0L99s3RWAjjzoxwcvOfmeT"
},
"name": "sample-cm",
"namespace": "sample-ns"
}
}`
var signed_adreq = `{
"uid": "2529b894-5fca-4df9-a92b-7110f42bfa09",
"kind": {
"group": "",
"version": "v1",
"kind": "ConfigMap"
},
"resource": {
"group": "",
"version": "v1",
"resource": "configmaps"
},
"requestKind": {
"group": "",
"version": "v1",
"kind": "ConfigMap"
},
"requestResource": {
"group": "",
"version": "v1",
"resource": "configmaps"
},
"name": "sample-cm",
"namespace": "sample-ns",
"operation": "CREATE",
"userInfo": {
"username": "kubernetes-admin",
"groups": [
"system:masters",
"system:authenticated"
]
},
"object": {
"apiVersion": "v1",
"data": {
"comment": "comment1",
"key1": "val1",
"key2": "val2"
},
"kind": "ConfigMap",
"metadata": {
"annotations": {
"cosign.sigstore.dev/message": "H4sIAAAAAAAA/wD8AAP/H4sIAAAAAAAA/+zRu27DIBQGYGaeghdIOVzsNKydu1Vdq9MYW5Y54AKJmjx9leuYsVUlf8vPz2U4Qu4xyz6Fzuci41EqeJ7C19DpGj+BDNFHMGS/LQDAEOWb3Caasy9ljMOqYl4Nx2azMQBGyYI0B7/a0tMBKbC709vW2nOu2+acoC/9RDVrpqyGprXQasPAQKvWTAD7BbtSMTOAPO269OBeqdj3D86vs9zzn8B5fPe5jCk6sVd8GmPnxEuK/Ti84szJV+ywouNCRCTvxP2T+W1/8gflxB6DuhR9LpoLsU1EPlZ3Wyj+1+MuFovF4uonAAD//3weCWIACAAAAQAA//+Nc9ey/AAAAA==",
"cosign.sigstore.dev/signature": "MEYCIQCTNFfObr0DiBCbDYEq0clxRw0FeoY35LhEiIFrGU7bZAIhAJR7AEYHIXkCPGlPIXA8ao0L99s3RWAjjzoxwcvOfmeT"
},
"creationTimestamp": "2022-03-04T07:43:10Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:data": {
".": {},
"f:comment": {},
"f:key1": {},
"f:key2": {}
},
"f:metadata": {
"f:annotations": {
".": {},
"f:integrityshield.io/message": {},
"f:integrityshield.io/signature": {}
}
}
},
"manager": "oc",
"operation": "Update",
"time": "2022-03-04T07:43:10Z"
}
],
"name": "sample-cm",
"namespace": "sample-ns",
"uid": "44725451-0fd5-47ec-98a1-f53f938e9b4d"
}
},
"oldObject": null,
"dryRun": false,
"options": {
"apiVersion": "meta.k8s.io/v1",
"kind": "CreateOptions"
}
}`
var unsigned_resource = `{
"apiVersion": "v1",
"data": {
"comment": "comment1",
"key1": "val1",
"key2": "val2"
},
"kind": "ConfigMap",
"metadata": {
"name": "sample-cm",
"namespace": "sample-ns"
}
}`
var unsigned_adreq = `{
"uid": "2529b894-5fca-4df9-a92b-7110f42bfa09",
"kind": {
"group": "",
"version": "v1",
"kind": "ConfigMap"
},
"resource": {
"group": "",
"version": "v1",
"resource": "configmaps"
},
"requestKind": {
"group": "",
"version": "v1",
"kind": "ConfigMap"
},
"requestResource": {
"group": "",
"version": "v1",
"resource": "configmaps"
},
"name": "sample-cm",
"namespace": "sample-ns",
"operation": "CREATE",
"userInfo": {
"username": "kubernetes-admin",
"groups": [
"system:masters",
"system:authenticated"
]
},
"object": {
"apiVersion": "v1",
"data": {
"comment": "comment1",
"key1": "val1",
"key2": "val2"
},
"kind": "ConfigMap",
"metadata": {
"creationTimestamp": "2022-03-04T07:43:10Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:data": {
".": {},
"f:comment": {},
"f:key1": {},
"f:key2": {}
},
"f:metadata": {
"f:annotations": {
".": {},
"f:integrityshield.io/message": {},
"f:integrityshield.io/signature": {}
}
}
},
"manager": "oc",
"operation": "Update",
"time": "2022-03-04T07:43:10Z"
}
],
"name": "sample-cm",
"namespace": "sample-ns",
"uid": "44725451-0fd5-47ec-98a1-f53f938e9b4d"
}
},
"oldObject": null,
"dryRun": false,
"options": {
"apiVersion": "meta.k8s.io/v1",
"kind": "CreateOptions"
}
}`
var invalid_resource = `{
"apiVersion": "v1",
"data": {
"comment": "comment1",
"key1": "val1",
"key2": "val2",
"key3": "val3"
},
"kind": "ConfigMap",
"metadata": {
"name": "sample-cm",
"namespace": "sample-ns",
"annotations": {
"cosign.sigstore.dev/message": "H4sIAAAAAAAA/wAIAff+H4sIAAAAAAAA/+yQu07DMBSGM+cp/ALB97T1ysyGWNHBcYKVHDuy3UL79Ii0ha0jCJFv+S/+Pdj0AIn2cepcyvSoqVZb+Rwwb076pStod+M7onx7ZYyxIdBHaiPOyeXsw9AUSM1w2raca7UTdB98aYrLpbF4dwScqjOfd1ulFt20elEmznmxTFdcCS0ka7USFZNcKlkRVv0A+1wgVYylcd/FG7tcoO9vnF/e8qV/BJj9k0vZx2DIgdejD50h9zH0fniAuUZXoIMCpiYkADpDMuA8ucbipckz2O865Po6txHRhWKuhteEjO7IDTnAdAliCeK3P2FlZWXlH/IRAAD//2efbt8ACAAAAQAA//91Gk76CAEAAA==",
"cosign.sigstore.dev/signature": "MEQCIFrMmrKUOAzbp0/5oe7TEotfqbAH9L5ao6iaIOlDZQCOAiAYcUnBFbn4GqgayTtcLN+Yi/2hH6hFz4MBUydO6DREAQ=="
}
}
}`
var invalid_adreq = `{
"clusterRoles": null,
"dryRun": false,
"kind": {
"group": "",
"kind": "ConfigMap",
"version": "v1"
},
"name": "sample-cm",
"namespace": "sample-ns",
"object": {
"apiVersion": "v1",
"data": {
"comment": "comment1",
"key1": "val1",
"key2": "val2",
"key3": "val3"
},
"kind": "ConfigMap",
"metadata": {
"annotations": {
"cosign.sigstore.dev/message": "H4sIAAAAAAAA/wAIAff+H4sIAAAAAAAA/+yQu07DMBSGM+cp/ALB97T1ysyGWNHBcYKVHDuy3UL79Ii0ha0jCJFv+S/+Pdj0AIn2cepcyvSoqVZb+Rwwb076pStod+M7onx7ZYyxIdBHaiPOyeXsw9AUSM1w2raca7UTdB98aYrLpbF4dwScqjOfd1ulFt20elEmznmxTFdcCS0ka7USFZNcKlkRVv0A+1wgVYylcd/FG7tcoO9vnF/e8qV/BJj9k0vZx2DIgdejD50h9zH0fniAuUZXoIMCpiYkADpDMuA8ucbipckz2O865Po6txHRhWKuhteEjO7IDTnAdAliCeK3P2FlZWXlH/IRAAD//2efbt8ACAAAAQAA//91Gk76CAEAAA==",
"cosign.sigstore.dev/signature": "MEQCIFrMmrKUOAzbp0/5oe7TEotfqbAH9L5ao6iaIOlDZQCOAiAYcUnBFbn4GqgayTtcLN+Yi/2hH6hFz4MBUydO6DREAQ=="
},
"creationTimestamp": "2022-06-15T08:11:51Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:data": {
".": {},
"f:comment": {},
"f:key1": {},
"f:key2": {},
"f:key3": {}
},
"f:metadata": {
"f:annotations": {
".": {},
"f:cosign.sigstore.dev/message": {},
"f:cosign.sigstore.dev/signature": {}
}
}
},
"manager": "kubectl-create",
"operation": "Update",
"time": "2022-06-15T08:11:51Z"
}
],
"name": "sample-cm",
"namespace": "sample-ns",
"uid": "5b4e13e5-898d-4fd2-95a9-8d7a95f3b469"
}
},
"oldObject": null,
"operation": "CREATE",
"options": {
"apiVersion": "meta.k8s.io/v1",
"fieldManager": "kubectl-create",
"fieldValidation": "Strict",
"kind": "CreateOptions"
},
"requestKind": {
"group": "",
"kind": "ConfigMap",
"version": "v1"
},
"requestResource": {
"group": "",
"resource": "configmaps",
"version": "v1"
},
"resource": {
"group": "",
"resource": "configmaps",
"version": "v1"
},
"roles": null,
"uid": "eecf91e9-4bba-420a-8094-261c8099a04c",
"userInfo": {
"groups": [
"system:masters",
"system:authenticated"
],
"username": "kubernetes-admin"
}
}`
var multi_sig_resource = `{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"cosign.sigstore.dev/message": "H4sIAAAAAAAA/yyKzQrCQAwG7/sU3wsUFMGf3MSzUFC8h22QxXY3JKHg20sXb8PMsJaXmJdWCes+fUqdCA+xtWRJiwRPHEwJqLwIIcRj8H92lbwlbRa+wdCRcN4lAFBr0XKbCc/b2E2wvSXGPl0Op2MCXGbJ0Yz6wKqE+/eqmn4BAAD//3vEXUSaAAAA",
"cosign.sigstore.dev/signature": "MEUCIQDpI/7Ncl8iJJ/Kc8JlL5FLbePZprMSRRjvXYlaybjU2wIgaPYh93JMerk2L+vTOwQ4pYlZ43Eq86QnQ8wuKPXmnWE="
},
"name": "test-service"
},
"spec": {
"ports": [
{
"port": 80,
"protocol": "TCP",
"targetPort": 9376
}
],
"selector": {
"app": "MyApp"
}
}
}`
var multi_sig_adreq = `{
"clusterRoles": null,
"dryRun": false,
"kind": {
"group": "",
"kind": "Service",
"version": "v1"
},
"name": "test-service",
"namespace": "test-ns",
"object": {
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"cosign.sigstore.dev/message": "H4sIAAAAAAAA/yyKzQrCQAwG7/sU3wsUFMGf3MSzUFC8h22QxXY3JKHg20sXb8PMsJaXmJdWCes+fUqdCA+xtWRJiwRPHEwJqLwIIcRj8H92lbwlbRa+wdCRcN4lAFBr0XKbCc/b2E2wvSXGPl0Op2MCXGbJ0Yz6wKqE+/eqmn4BAAD//3vEXUSaAAAA",
"cosign.sigstore.dev/signature": "MEUCIQDpI/7Ncl8iJJ/Kc8JlL5FLbePZprMSRRjvXYlaybjU2wIgaPYh93JMerk2L+vTOwQ4pYlZ43Eq86QnQ8wuKPXmnWE="
},
"creationTimestamp": "2022-06-16T07:15:34Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:cosign.sigstore.dev/message": {},
"f:cosign.sigstore.dev/signature": {}
}
},
"f:spec": {
"f:internalTrafficPolicy": {},
"f:ports": {
".": {},
"k:{\"port\":80,\"protocol\":\"TCP\"}": {
".": {},
"f:port": {},
"f:protocol": {},
"f:targetPort": {}
}
},
"f:selector": {},
"f:sessionAffinity": {},
"f:type": {}
}
},
"manager": "kubectl-create",
"operation": "Update",
"time": "2022-06-16T07:15:34Z"
}
],
"name": "test-service",
"namespace": "test-ns",
"uid": "7011a06e-50cb-46b8-bf88-40582294d2b2"
},
"spec": {
"clusterIP": "10.96.122.111",
"clusterIPs": [
"10.96.122.111"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"port": 80,
"protocol": "TCP",
"targetPort": 9376
}
],
"selector": {
"app": "MyApp"
},
"sessionAffinity": "None",
"type": "ClusterIP"
},
"status": {
"loadBalancer": {}
}
},
"oldObject": null,
"operation": "CREATE",
"options": {
"apiVersion": "meta.k8s.io/v1",
"fieldManager": "kubectl-create",
"fieldValidation": "Strict",
"kind": "CreateOptions"
},
"requestKind": {
"group": "",
"kind": "Service",
"version": "v1"
},
"requestResource": {
"group": "",
"resource": "services",
"version": "v1"
},
"resource": {
"group": "",
"resource": "services",
"version": "v1"
},
"roles": null,
"uid": "cb2aed81-39ca-43c0-b565-0621b9a5d38c",
"userInfo": {
"groups": [
"system:masters",
"system:authenticated"
],
"username": "kubernetes-admin"
}
}`
var multi_sig2_resource = `{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"cosign.sigstore.dev/message": "H4sIAAAAAAAA/yyKzQrCQAwG7/sU3wsUFMGf3MSzUFC8h22QxXY3JKHg20sXb8PMsJaXmJdWCes+fUqdCA+xtWRJiwRPHEwJqLwIIcRj8H92lbwlbRa+wdCRcN4lAFBr0XKbCc/b2E2wvSXGPl0Op2MCXGbJ0Yz6wKqE+/eqmn4BAAD//3vEXUSaAAAA",
"cosign.sigstore.dev/signature": "MEUCIQDpI/7Ncl8iJJ/Kc8JlL5FLbePZprMSRRjvXYlaybjU2wIgaPYh93JMerk2L+vTOwQ4pYlZ43Eq86QnQ8wuKPXmnWE=",
"cosign.sigstore.dev/signature_1": "MEMCICxbOY2HKophxyUVxhBOAJo+kt+WYleDttBCVFrmA/7PAh8lgr5u3d2rFM8gSTBEYgzRzXIwAZEByrpq0SVRwqq7"
},
"name": "test-service"
},
"spec": {
"ports": [
{
"port": 80,
"protocol": "TCP",
"targetPort": 9376
}
],
"selector": {
"app": "MyApp"
}
}
}`
var multi_sig2_adreq = `{
"clusterRoles": null,
"dryRun": false,
"kind": {
"group": "",
"kind": "Service",
"version": "v1"
},
"name": "test-service",
"namespace": "test-ns",
"object": {
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"cosign.sigstore.dev/message": "H4sIAAAAAAAA/yyKzQrCQAwG7/sU3wsUFMGf3MSzUFC8h22QxXY3JKHg20sXb8PMsJaXmJdWCes+fUqdCA+xtWRJiwRPHEwJqLwIIcRj8H92lbwlbRa+wdCRcN4lAFBr0XKbCc/b2E2wvSXGPl0Op2MCXGbJ0Yz6wKqE+/eqmn4BAAD//3vEXUSaAAAA",
"cosign.sigstore.dev/signature": "MEUCIQDpI/7Ncl8iJJ/Kc8JlL5FLbePZprMSRRjvXYlaybjU2wIgaPYh93JMerk2L+vTOwQ4pYlZ43Eq86QnQ8wuKPXmnWE=",
"cosign.sigstore.dev/signature_1": "MEMCICxbOY2HKophxyUVxhBOAJo+kt+WYleDttBCVFrmA/7PAh8lgr5u3d2rFM8gSTBEYgzRzXIwAZEByrpq0SVRwqq7"
},
"creationTimestamp": "2022-06-16T07:16:23Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:cosign.sigstore.dev/message": {},
"f:cosign.sigstore.dev/signature": {},
"f:cosign.sigstore.dev/signature_1": {}
}
},
"f:spec": {
"f:internalTrafficPolicy": {},
"f:ports": {
".": {},
"k:{\"port\":80,\"protocol\":\"TCP\"}": {
".": {},
"f:port": {},
"f:protocol": {},
"f:targetPort": {}
}
},
"f:selector": {},
"f:sessionAffinity": {},
"f:type": {}
}
},
"manager": "kubectl-create",
"operation": "Update",
"time": "2022-06-16T07:16:23Z"
}
],
"name": "test-service",
"namespace": "test-ns",
"uid": "3e146f89-bd8a-4738-a7d4-41c5872d18ad"
},
"spec": {
"clusterIP": "10.96.223.193",
"clusterIPs": [
"10.96.223.193"
],
"internalTrafficPolicy": "Cluster",
"ipFamilies": [
"IPv4"
],
"ipFamilyPolicy": "SingleStack",
"ports": [
{
"port": 80,
"protocol": "TCP",
"targetPort": 9376
}
],
"selector": {
"app": "MyApp"
},
"sessionAffinity": "None",
"type": "ClusterIP"
},
"status": {
"loadBalancer": {}
}
},
"oldObject": null,
"operation": "CREATE",
"options": {
"apiVersion": "meta.k8s.io/v1",
"fieldManager": "kubectl-create",
"fieldValidation": "Strict",
"kind": "CreateOptions"
},
"requestKind": {
"group": "",
"kind": "Service",
"version": "v1"
},
"requestResource": {
"group": "",
"resource": "services",
"version": "v1"
},
"resource": {
"group": "",
"resource": "services",
"version": "v1"
},
"roles": null,
"uid": "8a2891d0-351a-4363-92e4-0c99b10e5f26",
"userInfo": {
"groups": [
"system:masters",
"system:authenticated"
],
"username": "kubernetes-admin"
}
}`
const ecdsaPub = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyQfmL5YwHbn9xrrgG3vgbU0KJxMY
BibYLJ5L4VSMvGxeMLnBGdM48w5IE//6idUPj3rscigFdHs7GDMH4LLAng==
-----END PUBLIC KEY-----`
const ecdsaPub2 = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEE8uGVnyDWPPlB7M5KOHRzxzPHtAy
FdGxexVrR4YqO1pRViKxmD9oMu4I7K/4sM51nbH65ycB2uRiDfIdRoV/+A==
-----END PUBLIC KEY-----
`
func Test_VerifyManifest_SignedYAML(t *testing.T) {
policyContext := buildContext(t, test_policy, signed_resource, "")
var request *v1.AdmissionRequest
_ = json.Unmarshal([]byte(signed_adreq), &request)
policyContext.JSONContext.AddRequest(request)
policyContext.Policy.SetName("test-policy")
verifyRule := kyvernov1.Manifests{}
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
Entries: []kyvernov1.Attestor{
{
Keys: &kyvernov1.StaticKeyAttestor{
PublicKeys: ecdsaPub,
},
},
},
})
logger := buildLogger(policyContext)
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
assert.NilError(t, err)
assert.Equal(t, verified, true)
}
func Test_VerifyManifest_UnsignedYAML(t *testing.T) {
policyContext := buildContext(t, test_policy, unsigned_resource, "")
var request *v1.AdmissionRequest
_ = json.Unmarshal([]byte(unsigned_adreq), &request)
policyContext.JSONContext.AddRequest(request)
policyContext.Policy.SetName("test-policy")
verifyRule := kyvernov1.Manifests{}
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
Entries: []kyvernov1.Attestor{
{
Keys: &kyvernov1.StaticKeyAttestor{
PublicKeys: ecdsaPub,
},
},
},
})
logger := buildLogger(policyContext)
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
assert.NilError(t, err)
assert.Equal(t, verified, false)
}
func Test_VerifyManifest_InvalidYAML(t *testing.T) {
policyContext := buildContext(t, test_policy, invalid_resource, "")
var request *v1.AdmissionRequest
_ = json.Unmarshal([]byte(invalid_adreq), &request)
policyContext.JSONContext.AddRequest(request)
policyContext.Policy.SetName("test-policy")
verifyRule := kyvernov1.Manifests{}
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
Entries: []kyvernov1.Attestor{
{
Keys: &kyvernov1.StaticKeyAttestor{
PublicKeys: ecdsaPub,
},
},
},
})
logger := buildLogger(policyContext)
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
assert.NilError(t, err)
assert.Equal(t, verified, false)
}
func Test_VerifyManifest_MustAll_InvalidYAML(t *testing.T) {
policyContext := buildContext(t, test_policy, multi_sig_resource, "")
var request *v1.AdmissionRequest
_ = json.Unmarshal([]byte(multi_sig_adreq), &request)
policyContext.JSONContext.AddRequest(request)
policyContext.Policy.SetName("test-policy")
verifyRule := kyvernov1.Manifests{}
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
Entries: []kyvernov1.Attestor{
{
Keys: &kyvernov1.StaticKeyAttestor{
PublicKeys: ecdsaPub,
},
},
{
Keys: &kyvernov1.StaticKeyAttestor{
PublicKeys: ecdsaPub2,
},
},
},
})
logger := buildLogger(policyContext)
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
errMsg := `.attestors[0].entries[1].keys: failed to verify signature: verification failed for 1 signature. all trials: ["[publickey 1/1] [signature 1/1] error: cosign.VerifyBlobCmd() returned an error: invalid signature when validating ASN.1 encoded signature"]`
assert.Error(t, err, errMsg)
assert.Equal(t, verified, false)
}
func Test_VerifyManifest_MustAll_ValidYAML(t *testing.T) {
policyContext := buildContext(t, test_policy, multi_sig2_resource, "")
var request *v1.AdmissionRequest
_ = json.Unmarshal([]byte(multi_sig2_adreq), &request)
policyContext.JSONContext.AddRequest(request)
policyContext.Policy.SetName("test-policy")
verifyRule := kyvernov1.Manifests{}
count := 3
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
Count: &count,
Entries: []kyvernov1.Attestor{
{
Keys: &kyvernov1.StaticKeyAttestor{
PublicKeys: ecdsaPub,
},
},
{
Keys: &kyvernov1.StaticKeyAttestor{
PublicKeys: ecdsaPub2,
},
},
{
Attestor: &apiextv1.JSON{Raw: []byte(`{"entries":[{"keys":{"publicKeys":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyQfmL5YwHbn9xrrgG3vgbU0KJxMY\nBibYLJ5L4VSMvGxeMLnBGdM48w5IE//6idUPj3rscigFdHs7GDMH4LLAng==\n-----END PUBLIC KEY----- "}}]}`)},
},
},
})
logger := buildLogger(policyContext)
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
assert.NilError(t, err)
assert.Equal(t, verified, true)
}
func Test_VerifyManifest_AtLeastOne(t *testing.T) {
policyContext := buildContext(t, test_policy, multi_sig_resource, "")
var request *v1.AdmissionRequest
_ = json.Unmarshal([]byte(multi_sig_adreq), &request)
policyContext.JSONContext.AddRequest(request)
policyContext.Policy.SetName("test-policy")
verifyRule := kyvernov1.Manifests{}
count := 1
verifyRule.Attestors = append(verifyRule.Attestors, kyvernov1.AttestorSet{
Count: &count,
Entries: []kyvernov1.Attestor{
{
Keys: &kyvernov1.StaticKeyAttestor{
PublicKeys: ecdsaPub,
},
},
{
Keys: &kyvernov1.StaticKeyAttestor{
PublicKeys: ecdsaPub2,
},
},
},
})
logger := buildLogger(policyContext)
verified, _, err := verifyManifest(policyContext, verifyRule, logger)
assert.NilError(t, err)
assert.Equal(t, verified, true)
}

View file

@ -0,0 +1,77 @@
ignoreFields:
- fields:
- metadata.namespace
- spec.containers.*.imagePullPolicy
- spec.containers.*.terminationMessagePath
- spec.containers.*.terminationMessagePolicy
- spec.dnsPolicy
- spec.restartPolicy
- spec.schedulerName
- spec.terminationGracePeriodSeconds
- metadata.labels.app.kubernetes.io/instance
- metadata.managedFields.*
- metadata.resourceVersion
- metadata.selfLink
- metadata.annotations.control-plane.alpha.kubernetes.io/leader
- metadata.annotations.kubectl.kubernetes.io/last-applied-configuration
- metadata.finalizers*
- metadata.annotations.namespace
- metadata.annotations.deprecated.daemonset.template.generation
- metadata.creationTimestamp
- metadata.uid
- metadata.generation
- status
- metadata.annotations.deployment.kubernetes.io/revision
objects:
- kind: '*'
- fields:
- spec.volumes.*.name
- spec.volumes.*.projected.*
- spec.volumes.*.configMap.defaultMode
- spec.containers.*.volumeMounts.*
- spec.tolerations.*
- spec.enableServiceLinks
- spec.preemptionPolicy
- spec.priority
- spec.serviceAccount
objects:
- kind: Pod
- fields:
- spec.progressDeadlineSeconds
- spec.revisionHistoryLimit
- spec.strategy.*
- spec.template.metadata.creationTimestamp
- spec.containers.*.ports.*.protocol
- spec.containers.*.resources
- spec.securityContext
objects:
- kind: Deployment
- fields:
- spec.conversion.strategy
- spec.names.listKind
objects:
- kind: CustomResourceDefinition
- fields:
- spec.ports.*.nodePort
- spec.clusterIP
- spec.clusterIPs.0
- spec.sessionAffinity
- spec.type
- spec.ipFamilies.*
- spec.ipFamilyPolicy
- spec.internalTrafficPolicy
objects:
- kind: Service
- fields:
- metadata.annotations.pod-policies.kyverno.io/autogen-controllers
- spec.failurePolicy
- spec.background
- spec.validationFailureAction
objects:
- kind: ClusterPolicy
- kind: Policy
- fields:
- secrets.*.name
- imagePullSecrets.*.name
objects:
- kind: ServiceAccount

View file

@ -97,6 +97,7 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
rule := &rules[i]
hasValidate := rule.HasValidate()
hasValidateImage := rule.HasImagesValidationChecks()
hasYAMLSignatureVerify := rule.HasYAMLSignatureVerify()
if !hasValidate && !hasValidateImage {
continue
}
@ -111,10 +112,12 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
startTime := time.Now()
var ruleResp *response.RuleResponse
if hasValidate {
if hasValidate && !hasYAMLSignatureVerify {
ruleResp = processValidationRule(log, ctx, rule)
} else if hasValidateImage {
ruleResp = processImageValidationRule(log, ctx, rule)
} else if hasYAMLSignatureVerify {
ruleResp = processYAMLValidationRule(log, ctx, rule)
}
if ruleResp != nil {

View file

@ -1065,9 +1065,6 @@ func podControllerAutoGenExclusion(policy kyvernov1.PolicyInterface) bool {
func validateKinds(kinds []string, mock bool, client dclient.Interface, p kyvernov1.PolicyInterface) error {
for _, kind := range kinds {
gv, k := kubeutils.GetKindFromGVK(kind)
if k == p.GetKind() {
return fmt.Errorf("kind and match resource kind should not be the same")
}
if !mock && !kubeutils.SkipSubResources(k) && !strings.Contains(kind, "*") {
_, _, err := client.Discovery().FindResource(gv, k)

View file

@ -94,6 +94,10 @@ func validationElemCount(v *kyvernov1.Validation) int {
count++
}
if v.Manifests != nil && len(v.Manifests.Attestors) != 0 {
count++
}
return count
}

View file

@ -97,7 +97,7 @@ func (m *policyMap) set(key string, policy kyvernov1.PolicyInterface) {
enforcePolicy := computeEnforcePolicy(policy.GetSpec())
m.policies[key] = policy
type state struct {
hasMutate, hasValidate, hasGenerate, hasVerifyImages, hasImagesValidationChecks bool
hasMutate, hasValidate, hasGenerate, hasVerifyImages, hasImagesValidationChecks, hasVerifyYAML bool
}
kindStates := map[string]state{}
for _, rule := range autogen.ComputeRules(policy) {
@ -121,6 +121,7 @@ func (m *policyMap) set(key string, policy kyvernov1.PolicyInterface) {
Generate: sets.NewString(),
VerifyImagesMutate: sets.NewString(),
VerifyImagesValidate: sets.NewString(),
VerifyYAML: sets.NewString(),
}
}
m.kindType[kind][Mutate] = set(m.kindType[kind][Mutate], key, state.hasMutate)
@ -129,6 +130,7 @@ func (m *policyMap) set(key string, policy kyvernov1.PolicyInterface) {
m.kindType[kind][Generate] = set(m.kindType[kind][Generate], key, state.hasGenerate)
m.kindType[kind][VerifyImagesMutate] = set(m.kindType[kind][VerifyImagesMutate], key, state.hasVerifyImages)
m.kindType[kind][VerifyImagesValidate] = set(m.kindType[kind][VerifyImagesValidate], key, state.hasVerifyImages && state.hasImagesValidationChecks)
m.kindType[kind][VerifyYAML] = set(m.kindType[kind][VerifyYAML], key, state.hasVerifyYAML)
}
}

View file

@ -11,4 +11,5 @@ const (
Generate
VerifyImagesMutate
VerifyImagesValidate
VerifyYAML
)

View file

@ -390,7 +390,7 @@ func (m *webhookConfigManager) buildWebhooks(namespace string) (res []*webhook,
for _, p := range policies {
spec := p.GetSpec()
if spec.HasValidate() || spec.HasGenerate() || spec.HasMutate() || spec.HasImagesValidationChecks() {
if spec.HasValidate() || spec.HasGenerate() || spec.HasMutate() || spec.HasImagesValidationChecks() || spec.HasYAMLSignatureVerify() {
if spec.GetFailurePolicy() == kyvernov1.Ignore {
m.mergeWebhook(validateIgnore, p, true)
} else {
@ -572,7 +572,7 @@ func (m *webhookConfigManager) mergeWebhook(dst *webhook, policy kyvernov1.Polic
if (updateValidate && rule.HasValidate() || rule.HasImagesValidationChecks()) ||
(updateValidate && rule.HasMutate() && rule.IsMutateExisting()) ||
(!updateValidate && rule.HasMutate()) && !rule.IsMutateExisting() ||
(!updateValidate && rule.HasVerifyImages()) {
(!updateValidate && rule.HasVerifyImages()) || (!updateValidate && rule.HasYAMLSignatureVerify()) {
matchedGVK = append(matchedGVK, rule.MatchResources.GetKinds()...)
}
}

View file

@ -34,7 +34,10 @@ var FluxValidateTests = []struct {
},
}
var podGVR = e2e.GetGVR("", "v1", "pods")
var (
podGVR = e2e.GetGVR("", "v1", "pods")
deploymentGVR = e2e.GetGVR("apps", "v1", "deployments")
)
var ValidateTests = []struct {
// TestDescription - Description of the Test
@ -131,4 +134,26 @@ var ValidateTests = []struct {
ResourceRaw: kyverno_pod_with_large_image,
MustSucceed: false,
},
{
// Case for yaml signing validation
TestDescription: "checks that unsigned yaml manifest is blocked",
PolicyName: "check-yaml-signing",
PolicyRaw: kyverno_yaml_signing_validate_policy,
ResourceName: "test-deployment",
ResourceNamespace: "test-validate",
ResourceGVR: deploymentGVR,
ResourceRaw: kyverno_yaml_signing_validate_resource_1,
MustSucceed: false,
},
{
// Case for yaml signing validation
TestDescription: "checks that signed yaml manifest is created",
PolicyName: "check-yaml-signing",
PolicyRaw: kyverno_yaml_signing_validate_policy,
ResourceName: "test-deployment",
ResourceNamespace: "test-validate",
ResourceGVR: deploymentGVR,
ResourceRaw: kyverno_yaml_signing_validate_resource_2,
MustSucceed: true,
},
}

View file

@ -796,3 +796,102 @@ spec:
- name: large-image
image: nvidia/cuda:11.6.0-devel-ubi8
`)
var kyverno_yaml_signing_validate_policy = []byte(`
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: validate-resources
spec:
validationFailureAction: enforce
background: false
webhookTimeoutSeconds: 30
failurePolicy: Fail
rules:
- name: validate-resources
match:
any:
- resources:
kinds:
- Deployment
- Pod
name: test*
exclude:
any:
- resources:
kinds:
- Pod
subjects:
- kind: ServiceAccount
namespace: kube-system
name: replicaset-controller
- resources:
kinds:
- ReplicaSet
subjects:
- kind: ServiceAccount
namespace: kube-system
name: deployment-controller
validate:
manifests:
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyQfmL5YwHbn9xrrgG3vgbU0KJxMY
BibYLJ5L4VSMvGxeMLnBGdM48w5IE//6idUPj3rscigFdHs7GDMH4LLAng==
-----END PUBLIC KEY-----
`)
var kyverno_yaml_signing_validate_resource_1 = []byte(`
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: test-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
name: nginx
ports:
- containerPort: 80
`)
var kyverno_yaml_signing_validate_resource_2 = []byte(`
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
cosign.sigstore.dev/message: H4sIAAAAAAAA/wBaAaX+H4sIAAAAAAAA/+ySz27bMAzGffZT8AUcSf6TpDrvuMMOw64DazOeEP2bxBZtn35wnXhegOW4oYB/F9rg930gQYlnTOIU7EApC/8mlDye7c9xqNk/Stc49902rn1ppZRy9OKr6IOLiXI2fqwYUzW+KXmQDw9tUx8FU+ZqoGjDqyPPu1d0tigm775t3+th371XWc//E12zL1Rbq042XacOhWzquusKkMU/4CkzpkLKdH4awh1dZjyd7vQvuyz1g4DRfKOUTfAaMMYsnlV5Nn7Q8Gk5Y+mIcUBGXQJYfCSbpy+YDBr8aPxLCeDRkYabF1DmSP0kThSt6TFrUCVAJks9hzTHOOT+x+dV7k0yk4sWmS7q1TAT9g/jjRXgOsBEHzyj8ZRW8gqMw5EuFq12qt3VS/e61u+8mRgSr0LmoCX+S0is4SjL/33djY2Njb/zKwAA//+MAMwjAAgAAAEAAP//7NcJ9loBAAA=
cosign.sigstore.dev/signature: MEUCICLCfb3LGKXcdKV3gTXl6qba3T2goZMbVX/54gyNR05UAiEAlvPuWVsCPuBx5wVqvtyT7hr/AfR9Fl7cNLDACaNIbx8=
labels:
app: nginx
name: test-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
name: nginx
ports:
- containerPort: 80
`)