mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 02:18:15 +00:00
feat: add skipImageReferences in verify images (#8633)
* feat: add skipImageReferences in verify images Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: chainsaw tests Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: chainsaw-test.yaml Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: typo in assert Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> --------- Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
d47684c0d9
commit
87c7ce254a
37 changed files with 899 additions and 94 deletions
|
@ -56,6 +56,13 @@ type ImageVerification struct {
|
|||
// +kubebuilder:validation:Optional
|
||||
ImageReferences []string `json:"imageReferences,omitempty" yaml:"imageReferences,omitempty"`
|
||||
|
||||
// SkipImageReferences is a list of matching image reference patterns that should be skipped.
|
||||
// At least one pattern in the list must match the image for the rule to be skipped. Each image reference
|
||||
// consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest).
|
||||
// Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.
|
||||
// +kubebuilder:validation:Optional
|
||||
SkipImageReferences []string `json:"skipImageReferences,omitempty" yaml:"skipImageReferences,omitempty"`
|
||||
|
||||
// Deprecated. Use StaticKeyAttestor instead.
|
||||
Key string `json:"key,omitempty" yaml:"key,omitempty"`
|
||||
|
||||
|
|
|
@ -758,6 +758,11 @@ func (in *ImageVerification) DeepCopyInto(out *ImageVerification) {
|
|||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.SkipImageReferences != nil {
|
||||
in, out := &in.SkipImageReferences, &out.SkipImageReferences
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.AdditionalExtensions != nil {
|
||||
in, out := &in.AdditionalExtensions, &out.AdditionalExtensions
|
||||
*out = make(map[string]string, len(*in))
|
||||
|
|
|
@ -21,6 +21,13 @@ type ImageVerification struct {
|
|||
// +kubebuilder:validation:Optional
|
||||
ImageReferences []string `json:"imageReferences,omitempty" yaml:"imageReferences,omitempty"`
|
||||
|
||||
// SkipImageReferences is a list of matching image reference patterns that should be skipped.
|
||||
// At least one pattern in the list must match the image for the rule to be skipped. Each image reference
|
||||
// consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest).
|
||||
// Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.
|
||||
// +kubebuilder:validation:Optional
|
||||
SkipImageReferences []string `json:"skipImageReferences,omitempty" yaml:"skipImageReferences,omitempty"`
|
||||
|
||||
// Attestors specified the required attestors (i.e. authorities)
|
||||
// +kubebuilder:validation:Optional
|
||||
Attestors []kyvernov1.AttestorSet `json:"attestors,omitempty" yaml:"attestors,omitempty"`
|
||||
|
|
|
@ -376,6 +376,11 @@ func (in *ImageVerification) DeepCopyInto(out *ImageVerification) {
|
|||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.SkipImageReferences != nil {
|
||||
in, out := &in.SkipImageReferences, &out.SkipImageReferences
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Attestors != nil {
|
||||
in, out := &in.Attestors, &out.Attestors
|
||||
*out = make([]v1.AttestorSet, len(*in))
|
||||
|
|
|
@ -14291,6 +14291,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -18849,6 +18860,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -23048,6 +23070,17 @@ spec:
|
|||
i.e. have matched passed a signature or attestation
|
||||
check.
|
||||
type: boolean
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type:
|
||||
description: Type specifies the method of signature validation.
|
||||
The allowed options are Cosign and Notary. By default
|
||||
|
@ -27603,6 +27636,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -32099,6 +32143,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -36658,6 +36713,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -40858,6 +40924,17 @@ spec:
|
|||
i.e. have matched passed a signature or attestation
|
||||
check.
|
||||
type: boolean
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type:
|
||||
description: Type specifies the method of signature validation.
|
||||
The allowed options are Cosign and Notary. By default
|
||||
|
@ -45413,6 +45490,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
|
|
@ -4340,6 +4340,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -8898,6 +8909,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -13097,6 +13119,17 @@ spec:
|
|||
i.e. have matched passed a signature or attestation
|
||||
check.
|
||||
type: boolean
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type:
|
||||
description: Type specifies the method of signature validation.
|
||||
The allowed options are Cosign and Notary. By default
|
||||
|
@ -17652,6 +17685,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
|
|
@ -4341,6 +4341,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -8900,6 +8911,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -13100,6 +13122,17 @@ spec:
|
|||
i.e. have matched passed a signature or attestation
|
||||
check.
|
||||
type: boolean
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type:
|
||||
description: Type specifies the method of signature validation.
|
||||
The allowed options are Cosign and Notary. By default
|
||||
|
@ -17655,6 +17688,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
|
|
@ -4340,6 +4340,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -8898,6 +8909,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -13097,6 +13119,17 @@ spec:
|
|||
i.e. have matched passed a signature or attestation
|
||||
check.
|
||||
type: boolean
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type:
|
||||
description: Type specifies the method of signature validation.
|
||||
The allowed options are Cosign and Notary. By default
|
||||
|
@ -17652,6 +17685,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
|
|
@ -4341,6 +4341,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -8900,6 +8911,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -13100,6 +13122,17 @@ spec:
|
|||
i.e. have matched passed a signature or attestation
|
||||
check.
|
||||
type: boolean
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type:
|
||||
description: Type specifies the method of signature validation.
|
||||
The allowed options are Cosign and Notary. By default
|
||||
|
@ -17655,6 +17688,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
|
|
@ -14510,6 +14510,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -19068,6 +19079,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -23267,6 +23289,17 @@ spec:
|
|||
i.e. have matched passed a signature or attestation
|
||||
check.
|
||||
type: boolean
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type:
|
||||
description: Type specifies the method of signature validation.
|
||||
The allowed options are Cosign and Notary. By default
|
||||
|
@ -27822,6 +27855,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -32320,6 +32364,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -36879,6 +36934,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
@ -41079,6 +41145,17 @@ spec:
|
|||
i.e. have matched passed a signature or attestation
|
||||
check.
|
||||
type: boolean
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped. At
|
||||
least one pattern in the list must match the image for
|
||||
the rule to be skipped. Each image reference consists
|
||||
of a registry address (defaults to docker.io), repository,
|
||||
image, and tag (defaults to latest). Wildcards (''*''
|
||||
and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type:
|
||||
description: Type specifies the method of signature validation.
|
||||
The allowed options are Cosign and Notary. By default
|
||||
|
@ -45634,6 +45711,17 @@ spec:
|
|||
roots:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
skipImageReferences:
|
||||
description: 'SkipImageReferences is a list of matching
|
||||
image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the
|
||||
image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io),
|
||||
repository, image, and tag (defaults to latest).
|
||||
Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
subject:
|
||||
description: Deprecated. Use KeylessAttestor instead.
|
||||
type: string
|
||||
|
|
|
@ -2187,6 +2187,20 @@ Wildcards (‘*’ and ‘?’) are allowed. See: <a href="https
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>skipImageReferences</code><br/>
|
||||
<em>
|
||||
[]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>SkipImageReferences is a list of matching image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest).
|
||||
Wildcards (‘*’ and ‘?’) are allowed. See: <a href="https://kubernetes.io/docs/concepts/containers/images">https://kubernetes.io/docs/concepts/containers/images</a>.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>key</code><br/>
|
||||
<em>
|
||||
string
|
||||
|
@ -9033,6 +9047,20 @@ Wildcards (‘*’ and ‘?’) are allowed. See: <a href="https
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>skipImageReferences</code><br/>
|
||||
<em>
|
||||
[]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>SkipImageReferences is a list of matching image reference patterns that should be skipped.
|
||||
At least one pattern in the list must match the image for the rule to be skipped. Each image reference
|
||||
consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest).
|
||||
Wildcards (‘*’ and ‘?’) are allowed. See: <a href="https://kubernetes.io/docs/concepts/containers/images">https://kubernetes.io/docs/concepts/containers/images</a>.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>attestors</code><br/>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.AttestorSet">
|
||||
|
|
|
@ -28,6 +28,7 @@ type ImageVerificationApplyConfiguration struct {
|
|||
Type *v1.ImageVerificationType `json:"type,omitempty"`
|
||||
Image *string `json:"image,omitempty"`
|
||||
ImageReferences []string `json:"imageReferences,omitempty"`
|
||||
SkipImageReferences []string `json:"skipImageReferences,omitempty"`
|
||||
Key *string `json:"key,omitempty"`
|
||||
Roots *string `json:"roots,omitempty"`
|
||||
Subject *string `json:"subject,omitempty"`
|
||||
|
@ -76,6 +77,16 @@ func (b *ImageVerificationApplyConfiguration) WithImageReferences(values ...stri
|
|||
return b
|
||||
}
|
||||
|
||||
// WithSkipImageReferences adds the given value to the SkipImageReferences field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the SkipImageReferences field.
|
||||
func (b *ImageVerificationApplyConfiguration) WithSkipImageReferences(values ...string) *ImageVerificationApplyConfiguration {
|
||||
for i := range values {
|
||||
b.SkipImageReferences = append(b.SkipImageReferences, values[i])
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// WithKey sets the Key field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Key field is set to the value of the last call.
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
type ImageVerificationApplyConfiguration struct {
|
||||
Type *v1.ImageVerificationType `json:"type,omitempty"`
|
||||
ImageReferences []string `json:"imageReferences,omitempty"`
|
||||
SkipImageReferences []string `json:"skipImageReferences,omitempty"`
|
||||
Attestors []kyvernov1.AttestorSetApplyConfiguration `json:"attestors,omitempty"`
|
||||
Attestations []kyvernov1.AttestationApplyConfiguration `json:"attestations,omitempty"`
|
||||
Repository *string `json:"repository,omitempty"`
|
||||
|
@ -62,6 +63,16 @@ func (b *ImageVerificationApplyConfiguration) WithImageReferences(values ...stri
|
|||
return b
|
||||
}
|
||||
|
||||
// WithSkipImageReferences adds the given value to the SkipImageReferences field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the SkipImageReferences field.
|
||||
func (b *ImageVerificationApplyConfiguration) WithSkipImageReferences(values ...string) *ImageVerificationApplyConfiguration {
|
||||
for i := range values {
|
||||
b.SkipImageReferences = append(b.SkipImageReferences, values[i])
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// WithAttestors adds the given value to the Attestors field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the Attestors field.
|
||||
|
|
|
@ -10,13 +10,21 @@ import (
|
|||
"gomodules.xyz/jsonpatch/v2"
|
||||
)
|
||||
|
||||
type ImageVerificationMetadataStatus string
|
||||
|
||||
const (
|
||||
ImageVerificationPass ImageVerificationMetadataStatus = "pass"
|
||||
ImageVerificationFail ImageVerificationMetadataStatus = "fail"
|
||||
ImageVerificationSkip ImageVerificationMetadataStatus = "skip"
|
||||
)
|
||||
|
||||
type ImageVerificationMetadata struct {
|
||||
Data map[string]bool `json:"data"`
|
||||
Data map[string]ImageVerificationMetadataStatus `json:"data"`
|
||||
}
|
||||
|
||||
func (ivm *ImageVerificationMetadata) Add(image string, verified bool) {
|
||||
func (ivm *ImageVerificationMetadata) Add(image string, verified ImageVerificationMetadataStatus) {
|
||||
if ivm.Data == nil {
|
||||
ivm.Data = make(map[string]bool)
|
||||
ivm.Data = make(map[string]ImageVerificationMetadataStatus)
|
||||
}
|
||||
ivm.Data[image] = verified
|
||||
}
|
||||
|
@ -29,11 +37,22 @@ func (ivm *ImageVerificationMetadata) IsVerified(image string) bool {
|
|||
if !ok {
|
||||
return false
|
||||
}
|
||||
return verified == ImageVerificationPass || verified == ImageVerificationSkip
|
||||
}
|
||||
|
||||
func (ivm *ImageVerificationMetadata) ImageVerificationStatus(image string) ImageVerificationMetadataStatus {
|
||||
if ivm.Data == nil {
|
||||
return ImageVerificationFail
|
||||
}
|
||||
verified, ok := ivm.Data[image]
|
||||
if !ok {
|
||||
return ImageVerificationFail
|
||||
}
|
||||
return verified
|
||||
}
|
||||
|
||||
func ParseImageMetadata(jsonData string) (*ImageVerificationMetadata, error) {
|
||||
var data map[string]bool
|
||||
var data map[string]ImageVerificationMetadataStatus
|
||||
if err := json.Unmarshal([]byte(jsonData), &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
func TestImageVerificationMetadata_IsVerified(t *testing.T) {
|
||||
type fields struct {
|
||||
Data map[string]bool
|
||||
Data map[string]ImageVerificationMetadataStatus
|
||||
}
|
||||
type args struct {
|
||||
image string
|
||||
|
@ -22,8 +22,8 @@ func TestImageVerificationMetadata_IsVerified(t *testing.T) {
|
|||
want bool
|
||||
}{{
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -32,8 +32,8 @@ func TestImageVerificationMetadata_IsVerified(t *testing.T) {
|
|||
want: true,
|
||||
}, {
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -42,8 +42,8 @@ func TestImageVerificationMetadata_IsVerified(t *testing.T) {
|
|||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test2": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test2": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -70,11 +70,11 @@ func TestImageVerificationMetadata_IsVerified(t *testing.T) {
|
|||
|
||||
func TestImageVerificationMetadata_Add(t *testing.T) {
|
||||
type fields struct {
|
||||
Data map[string]bool
|
||||
Data map[string]ImageVerificationMetadataStatus
|
||||
}
|
||||
type args struct {
|
||||
image string
|
||||
verified bool
|
||||
verified ImageVerificationMetadataStatus
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -83,43 +83,43 @@ func TestImageVerificationMetadata_Add(t *testing.T) {
|
|||
want *ImageVerificationMetadata
|
||||
}{{
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
image: "test",
|
||||
verified: false,
|
||||
verified: ImageVerificationFail,
|
||||
},
|
||||
want: &ImageVerificationMetadata{
|
||||
Data: map[string]bool{
|
||||
"test": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
args: args{
|
||||
image: "test",
|
||||
verified: false,
|
||||
verified: ImageVerificationFail,
|
||||
},
|
||||
want: &ImageVerificationMetadata{
|
||||
Data: map[string]bool{
|
||||
"test": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
image: "test2",
|
||||
verified: false,
|
||||
verified: ImageVerificationFail,
|
||||
},
|
||||
want: &ImageVerificationMetadata{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
"test2": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
"test2": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
@ -152,21 +152,21 @@ func TestParseImageMetadata(t *testing.T) {
|
|||
wantErr: true,
|
||||
}, {
|
||||
args: args{
|
||||
jsonData: `{"test":true}`,
|
||||
jsonData: `{"test":"pass"}`,
|
||||
},
|
||||
want: &ImageVerificationMetadata{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
args: args{
|
||||
jsonData: `{"test":true,"test2":false}`,
|
||||
jsonData: `{"test":"pass","test2":"fail"}`,
|
||||
},
|
||||
want: &ImageVerificationMetadata{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
"test2": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
"test2": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
@ -186,7 +186,7 @@ func TestParseImageMetadata(t *testing.T) {
|
|||
|
||||
func TestImageVerificationMetadata_IsEmpty(t *testing.T) {
|
||||
type fields struct {
|
||||
Data map[string]bool
|
||||
Data map[string]ImageVerificationMetadataStatus
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -194,8 +194,8 @@ func TestImageVerificationMetadata_IsEmpty(t *testing.T) {
|
|||
want bool
|
||||
}{{
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
|
@ -216,7 +216,7 @@ func TestImageVerificationMetadata_IsEmpty(t *testing.T) {
|
|||
|
||||
func TestImageVerificationMetadata_Merge(t *testing.T) {
|
||||
type fields struct {
|
||||
Data map[string]bool
|
||||
Data map[string]ImageVerificationMetadataStatus
|
||||
}
|
||||
type args struct {
|
||||
other ImageVerificationMetadata
|
||||
|
@ -230,39 +230,39 @@ func TestImageVerificationMetadata_Merge(t *testing.T) {
|
|||
want: &ImageVerificationMetadata{},
|
||||
}, {
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
other: ImageVerificationMetadata{
|
||||
Data: map[string]bool{
|
||||
"test": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &ImageVerificationMetadata{
|
||||
Data: map[string]bool{
|
||||
"test": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
other: ImageVerificationMetadata{
|
||||
Data: map[string]bool{
|
||||
"test2": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test2": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &ImageVerificationMetadata{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
"test2": false,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
"test2": ImageVerificationFail,
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
@ -297,7 +297,7 @@ func Test_makeAnnotationKeyForJSONPatch(t *testing.T) {
|
|||
|
||||
func TestImageVerificationMetadata_Patches(t *testing.T) {
|
||||
type fields struct {
|
||||
Data map[string]bool
|
||||
Data map[string]ImageVerificationMetadataStatus
|
||||
}
|
||||
type args struct {
|
||||
hasAnnotations bool
|
||||
|
@ -311,8 +311,8 @@ func TestImageVerificationMetadata_Patches(t *testing.T) {
|
|||
wantErr bool
|
||||
}{{
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -321,12 +321,12 @@ func TestImageVerificationMetadata_Patches(t *testing.T) {
|
|||
},
|
||||
want: []string{
|
||||
`{"op":"add","path":"/metadata/annotations","value":{}}`,
|
||||
`{"op":"add","path":"/metadata/annotations/kyverno.io~1verify-images","value":"{\"test\":true}"}`,
|
||||
`{"op":"add","path":"/metadata/annotations/kyverno.io~1verify-images","value":"{\"test\":\"pass\"}"}`,
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
Data: map[string]bool{
|
||||
"test": true,
|
||||
Data: map[string]ImageVerificationMetadataStatus{
|
||||
"test": ImageVerificationPass,
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -334,7 +334,7 @@ func TestImageVerificationMetadata_Patches(t *testing.T) {
|
|||
log: logr.Discard(),
|
||||
},
|
||||
want: []string{
|
||||
`{"op":"add","path":"/metadata/annotations/kyverno.io~1verify-images","value":"{\"test\":true}"}`,
|
||||
`{"op":"add","path":"/metadata/annotations/kyverno.io~1verify-images","value":"{\"test\":\"pass\"}"}`,
|
||||
},
|
||||
}, {
|
||||
args: args{
|
||||
|
|
|
@ -44,14 +44,21 @@ type RuleResponse struct {
|
|||
podSecurityChecks *PodSecurityChecks
|
||||
// exception is the exception applied (if any)
|
||||
exception *kyvernov2beta1.PolicyException
|
||||
// emitWarning enable passing rule message as warning to api server warning header
|
||||
emitWarning bool
|
||||
}
|
||||
|
||||
func NewRuleResponse(name string, ruleType RuleType, msg string, status RuleStatus) *RuleResponse {
|
||||
emitWarn := false
|
||||
if status == RuleStatusError || status == RuleStatusFail || status == RuleStatusWarn {
|
||||
emitWarn = true
|
||||
}
|
||||
return &RuleResponse{
|
||||
name: name,
|
||||
ruleType: ruleType,
|
||||
message: msg,
|
||||
status: status,
|
||||
name: name,
|
||||
ruleType: ruleType,
|
||||
message: msg,
|
||||
status: status,
|
||||
emitWarning: emitWarn,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,6 +112,11 @@ func (r RuleResponse) WithStats(stats ExecutionStats) RuleResponse {
|
|||
return r
|
||||
}
|
||||
|
||||
func (r RuleResponse) WithEmitWarning(emitWarning bool) *RuleResponse {
|
||||
r.emitWarning = emitWarning
|
||||
return &r
|
||||
}
|
||||
|
||||
func (r *RuleResponse) Stats() ExecutionStats {
|
||||
return r.stats
|
||||
}
|
||||
|
@ -145,6 +157,10 @@ func (r *RuleResponse) Status() RuleStatus {
|
|||
return r.status
|
||||
}
|
||||
|
||||
func (r *RuleResponse) EmitWarning() bool {
|
||||
return r.emitWarning
|
||||
}
|
||||
|
||||
// HasStatus checks if rule status is in a given list
|
||||
func (r *RuleResponse) HasStatus(status ...RuleStatus) bool {
|
||||
for _, s := range status {
|
||||
|
|
|
@ -3,6 +3,7 @@ package validation
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
|
@ -61,6 +62,8 @@ func (h validateImageHandler) Process(
|
|||
}
|
||||
}
|
||||
|
||||
skippedImages := make([]string, 0)
|
||||
passedImages := make([]string, 0)
|
||||
for _, v := range rule.VerifyImages {
|
||||
imageVerify := v.Convert()
|
||||
for _, infoMap := range policyContext.JSONContext().ImageInfo() {
|
||||
|
@ -73,31 +76,45 @@ func (h validateImageHandler) Process(
|
|||
}
|
||||
|
||||
logger.V(4).Info("validating image", "image", image)
|
||||
if err := validateImage(policyContext, imageVerify, name, imageInfo, logger); err != nil {
|
||||
if v, err := validateImage(policyContext, imageVerify, name, imageInfo, logger); err != nil {
|
||||
return resource, handlers.WithFail(rule, engineapi.ImageVerify, err.Error())
|
||||
} else if v == engineapi.ImageVerificationSkip {
|
||||
skippedImages = append(skippedImages, image)
|
||||
} else if v == engineapi.ImageVerificationPass {
|
||||
passedImages = append(passedImages, image)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.V(4).Info("validated image", "rule", rule.Name)
|
||||
return resource, handlers.WithPass(rule, engineapi.Validation, "image verified")
|
||||
if len(passedImages) > 0 || len(passedImages)+len(skippedImages) == 0 {
|
||||
if len(skippedImages) > 0 {
|
||||
return resource, handlers.WithPass(rule, engineapi.Validation, strings.Join(append([]string{"image verified, skipped images:"}, skippedImages...), " "))
|
||||
}
|
||||
return resource, handlers.WithPass(rule, engineapi.Validation, "image verified")
|
||||
} else {
|
||||
return resource, handlers.WithSkip(rule, engineapi.Validation, strings.Join(append([]string{"image skipped, skipped images:"}, skippedImages...), " "))
|
||||
}
|
||||
}
|
||||
|
||||
func validateImage(ctx engineapi.PolicyContext, imageVerify *kyvernov1.ImageVerification, name string, imageInfo apiutils.ImageInfo, log logr.Logger) error {
|
||||
func validateImage(ctx engineapi.PolicyContext, imageVerify *kyvernov1.ImageVerification, name string, imageInfo apiutils.ImageInfo, log logr.Logger) (engineapi.ImageVerificationMetadataStatus, error) {
|
||||
var verified engineapi.ImageVerificationMetadataStatus
|
||||
var err error
|
||||
image := imageInfo.String()
|
||||
if imageVerify.VerifyDigest && imageInfo.Digest == "" {
|
||||
log.V(2).Info("missing digest", "image", imageInfo.String())
|
||||
return fmt.Errorf("missing digest for %s", image)
|
||||
return engineapi.ImageVerificationFail, fmt.Errorf("missing digest for %s", image)
|
||||
}
|
||||
newResource := ctx.NewResource()
|
||||
if imageVerify.Required && newResource.Object != nil {
|
||||
verified, err := engineutils.IsImageVerified(newResource, image, log)
|
||||
verified, err = engineutils.IsImageVerified(newResource, image, log)
|
||||
if err != nil {
|
||||
return err
|
||||
return engineapi.ImageVerificationFail, err
|
||||
}
|
||||
if !verified {
|
||||
return fmt.Errorf("unverified image %s", image)
|
||||
if verified == engineapi.ImageVerificationFail {
|
||||
return engineapi.ImageVerificationFail, fmt.Errorf("unverified image %s", image)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return verified, nil
|
||||
}
|
||||
|
|
|
@ -972,7 +972,7 @@ func Test_MarkImageVerified(t *testing.T) {
|
|||
|
||||
verified, err := engineutils.IsImageVerified(resource, image, logr.Discard())
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, verified, true)
|
||||
assert.Equal(t, verified, engineapi.ImageVerificationPass)
|
||||
}
|
||||
|
||||
func testApplyPatches(t *testing.T, patches []jsonpatch.JsonPatchOperation) unstructured.Unstructured {
|
||||
|
@ -1360,3 +1360,126 @@ func Test_changePolicyCacheVerificationNotary(t *testing.T) {
|
|||
errorAssertionUtil(t, image, ivm, er)
|
||||
assert.Check(t, secondOperationTime > firstOperationTime/10 && secondOperationTime < firstOperationTime*10, "cache entry not found, so image verification should not be from cache.", firstOperationTime, secondOperationTime)
|
||||
}
|
||||
|
||||
var excludeVerifyImageNotaryPolicy = `{
|
||||
"apiVersion": "kyverno.io/v2beta1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {
|
||||
"name": "check-image-notary"
|
||||
},
|
||||
"spec": {
|
||||
"validationFailureAction": "Enforce",
|
||||
"webhookTimeoutSeconds": 30,
|
||||
"failurePolicy": "Fail",
|
||||
"rules": [
|
||||
{
|
||||
"name": "verify-signature-notary",
|
||||
"match": {
|
||||
"any": [
|
||||
{
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Pod"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"verifyImages": [
|
||||
{
|
||||
"type": "Notary",
|
||||
"imageReferences": [
|
||||
"ghcr.io/*"
|
||||
],
|
||||
"skipImageReferences" : [
|
||||
"ghcr.io/invalid-user*"
|
||||
],
|
||||
"attestors": [
|
||||
{
|
||||
"count": 1,
|
||||
"entries": [
|
||||
{
|
||||
"certificates": {
|
||||
"cert": "-----BEGIN CERTIFICATE-----\nMIIDTTCCAjWgAwIBAgIJAPI+zAzn4s0xMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV\nBAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEPMA0GA1UECgwG\nTm90YXJ5MQ0wCwYDVQQDDAR0ZXN0MB4XDTIzMDUyMjIxMTUxOFoXDTMzMDUxOTIx\nMTUxOFowTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0\ndGxlMQ8wDQYDVQQKDAZOb3RhcnkxDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQDNhTwv+QMk7jEHufFfIFlBjn2NiJaYPgL4eBS+\nb+o37ve5Zn9nzRppV6kGsa161r9s2KkLXmJrojNy6vo9a6g6RtZ3F6xKiWLUmbAL\nhVTCfYw/2n7xNlVMjyyUpE+7e193PF8HfQrfDFxe2JnX5LHtGe+X9vdvo2l41R6m\nIia04DvpMdG4+da2tKPzXIuLUz/FDb6IODO3+qsqQLwEKmmUee+KX+3yw8I6G1y0\nVp0mnHfsfutlHeG8gazCDlzEsuD4QJ9BKeRf2Vrb0ywqNLkGCbcCWF2H5Q80Iq/f\nETVO9z88R7WheVdEjUB8UrY7ZMLdADM14IPhY2Y+tLaSzEVZAgMBAAGjMjAwMAkG\nA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0G\nCSqGSIb3DQEBCwUAA4IBAQBX7x4Ucre8AIUmXZ5PUK/zUBVOrZZzR1YE8w86J4X9\nkYeTtlijf9i2LTZMfGuG0dEVFN4ae3CCpBst+ilhIndnoxTyzP+sNy4RCRQ2Y/k8\nZq235KIh7uucq96PL0qsF9s2RpTKXxyOGdtp9+HO0Ty5txJE2txtLDUIVPK5WNDF\nByCEQNhtHgN6V20b8KU2oLBZ9vyB8V010dQz0NRTDLhkcvJig00535/LUylECYAJ\n5/jn6XKt6UYCQJbVNzBg/YPGc1RF4xdsGVDBben/JXpeGEmkdmXPILTKd9tZ5TC0\nuOKpF5rWAruB5PCIrquamOejpXV9aQA/K2JQDuc0mcKz\n-----END CERTIFICATE-----"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}`
|
||||
|
||||
var excludeVerifyImageNotaryResourcePass = `{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"creationTimestamp": null,
|
||||
"labels": {
|
||||
"run": "test"
|
||||
},
|
||||
"name": "test",
|
||||
"namespace": "default"
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": "ghcr.io/kyverno/test-verify-image:signed",
|
||||
"name": "test",
|
||||
"resources": {}
|
||||
}
|
||||
],
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"restartPolicy": "Always"
|
||||
},
|
||||
"status": {}
|
||||
}`
|
||||
|
||||
var excludeVerifyImageNotaryResourceSkip = `{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"creationTimestamp": null,
|
||||
"labels": {
|
||||
"run": "test"
|
||||
},
|
||||
"name": "testskip",
|
||||
"namespace": "default"
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": "ghcr.io/invalid-user/invalid-image:v1",
|
||||
"name": "test",
|
||||
"resources": {}
|
||||
}
|
||||
],
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"restartPolicy": "Always"
|
||||
},
|
||||
"status": {}
|
||||
}`
|
||||
|
||||
func Test_SkipImageReferences(t *testing.T) {
|
||||
policyContextPass := buildContext(t, excludeVerifyImageNotaryPolicy, excludeVerifyImageNotaryResourcePass, "")
|
||||
|
||||
// Passes as image is included and not excluded
|
||||
erPass, ivm := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContextPass, cfg)
|
||||
assert.Equal(t, len(erPass.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, erPass.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass,
|
||||
fmt.Sprintf("expected: %v, got: %v, failure: %v",
|
||||
engineapi.RuleStatusPass, erPass.PolicyResponse.Rules[0].Status(), erPass.PolicyResponse.Rules[0].Message()))
|
||||
assert.Equal(t, ivm.IsEmpty(), false)
|
||||
|
||||
policyContextSkip := buildContext(t, excludeVerifyImageNotaryPolicy, excludeVerifyImageNotaryResourceSkip, "")
|
||||
|
||||
// Skipped as image is excluded
|
||||
erSkip, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContextSkip, cfg)
|
||||
assert.Equal(t, len(erSkip.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, erSkip.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusSkip,
|
||||
fmt.Sprintf("expected: %v, got: %v, failure: %v",
|
||||
engineapi.RuleStatusPass, erSkip.PolicyResponse.Rules[0].Status(), erSkip.PolicyResponse.Rules[0].Message()))
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ func HasImageVerifiedAnnotationChanged(ctx engineapi.PolicyContext, log logr.Log
|
|||
if newValue == oldValue {
|
||||
return false
|
||||
}
|
||||
var newValueObj, oldValueObj map[string]bool
|
||||
var newValueObj, oldValueObj map[string]engineapi.ImageVerificationMetadataStatus
|
||||
err := json.Unmarshal([]byte(newValue), &newValueObj)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to parse new resource annotation.")
|
||||
|
@ -93,7 +93,7 @@ func HasImageVerifiedAnnotationChanged(ctx engineapi.PolicyContext, log logr.Log
|
|||
return false
|
||||
}
|
||||
|
||||
func matchImageReferences(imageReferences []string, image string) bool {
|
||||
func matchReferences(imageReferences []string, image string) bool {
|
||||
for _, imageRef := range imageReferences {
|
||||
if wildcard.Match(imageRef, image) {
|
||||
return true
|
||||
|
@ -102,6 +102,23 @@ func matchImageReferences(imageReferences []string, image string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func ruleStatusToImageVerificationStatus(ruleStatus engineapi.RuleStatus) engineapi.ImageVerificationMetadataStatus {
|
||||
var imageVerificationResult engineapi.ImageVerificationMetadataStatus
|
||||
switch ruleStatus {
|
||||
case engineapi.RuleStatusPass:
|
||||
imageVerificationResult = engineapi.ImageVerificationPass
|
||||
case engineapi.RuleStatusSkip:
|
||||
imageVerificationResult = engineapi.ImageVerificationSkip
|
||||
case engineapi.RuleStatusWarn:
|
||||
imageVerificationResult = engineapi.ImageVerificationSkip
|
||||
case engineapi.RuleStatusFail:
|
||||
imageVerificationResult = engineapi.ImageVerificationFail
|
||||
default:
|
||||
imageVerificationResult = engineapi.ImageVerificationFail
|
||||
}
|
||||
return imageVerificationResult
|
||||
}
|
||||
|
||||
func isImageVerified(resource unstructured.Unstructured, image string, log logr.Logger) (bool, error) {
|
||||
if resource.Object == nil {
|
||||
return false, fmt.Errorf("nil resource")
|
||||
|
@ -234,14 +251,14 @@ func (iv *ImageVerifier) Verify(
|
|||
changed, err := iv.policyContext.JSONContext().HasChanged(pointer)
|
||||
if err == nil && !changed {
|
||||
iv.logger.V(4).Info("no change in image, skipping check", "image", image)
|
||||
iv.ivm.Add(image, true)
|
||||
iv.ivm.Add(image, engineapi.ImageVerificationPass)
|
||||
continue
|
||||
}
|
||||
|
||||
verified, err := isImageVerified(iv.policyContext.NewResource(), image, iv.logger)
|
||||
if err == nil && verified {
|
||||
iv.logger.Info("image was previously verified, skipping check", "image", image)
|
||||
iv.ivm.Add(image, true)
|
||||
iv.ivm.Add(image, engineapi.ImageVerificationPass)
|
||||
continue
|
||||
}
|
||||
start := time.Now()
|
||||
|
@ -295,7 +312,7 @@ func (iv *ImageVerifier) Verify(
|
|||
|
||||
if ruleResp != nil {
|
||||
if len(imageVerify.Attestors) > 0 || len(imageVerify.Attestations) > 0 {
|
||||
iv.ivm.Add(image, ruleResp.Status() == engineapi.RuleStatusPass)
|
||||
iv.ivm.Add(image, ruleStatusToImageVerificationStatus(ruleResp.Status()))
|
||||
}
|
||||
responses = append(responses, ruleResp)
|
||||
}
|
||||
|
@ -324,8 +341,14 @@ func (iv *ImageVerifier) verifyImage(
|
|||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("failed to add image to context %s", image), err), ""
|
||||
}
|
||||
if len(imageVerify.Attestors) > 0 {
|
||||
if !matchImageReferences(imageVerify.ImageReferences, image) {
|
||||
return nil, ""
|
||||
if !matchReferences(imageVerify.ImageReferences, image) {
|
||||
return engineapi.RuleSkip(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("skipping image reference image %s, policy %s ruleName %s", image, iv.policyContext.Policy().GetName(), iv.rule.Name)), ""
|
||||
}
|
||||
|
||||
if matchReferences(imageVerify.SkipImageReferences, image) {
|
||||
iv.logger.Info("skipping image reference", "image", image, "policy", iv.policyContext.Policy().GetName(), "ruleName", iv.rule.Name)
|
||||
iv.ivm.Add(image, engineapi.ImageVerificationSkip)
|
||||
return engineapi.RuleSkip(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("skipping image reference image %s, policy %s ruleName %s", image, iv.policyContext.Policy().GetName(), iv.rule.Name)).WithEmitWarning(true), ""
|
||||
}
|
||||
ruleResp, cosignResp := iv.verifyAttestors(ctx, imageVerify.Attestors, imageVerify, imageInfo, "")
|
||||
if ruleResp.Status() != engineapi.RuleStatusPass {
|
||||
|
|
|
@ -21,7 +21,6 @@ func ImageMatches(image string, imagePatterns []string) bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -66,19 +65,19 @@ func ExtractMatchingImages(
|
|||
return matchingImages, imageRefs, nil
|
||||
}
|
||||
|
||||
func IsImageVerified(resource unstructured.Unstructured, image string, log logr.Logger) (bool, error) {
|
||||
func IsImageVerified(resource unstructured.Unstructured, image string, log logr.Logger) (engineapi.ImageVerificationMetadataStatus, error) {
|
||||
if resource.Object == nil {
|
||||
return false, fmt.Errorf("nil resource")
|
||||
return engineapi.ImageVerificationFail, fmt.Errorf("nil resource")
|
||||
}
|
||||
if annotations := resource.GetAnnotations(); len(annotations) == 0 {
|
||||
return false, nil
|
||||
return engineapi.ImageVerificationFail, nil
|
||||
} else if data, ok := annotations[kyverno.AnnotationImageVerify]; !ok {
|
||||
log.V(2).Info("missing image metadata in annotation", "key", kyverno.AnnotationImageVerify)
|
||||
return false, fmt.Errorf("image is not verified")
|
||||
return engineapi.ImageVerificationFail, fmt.Errorf("image is not verified")
|
||||
} else if ivm, err := engineapi.ParseImageMetadata(data); err != nil {
|
||||
log.Error(err, "failed to parse image verification metadata", "data", data)
|
||||
return false, fmt.Errorf("failed to parse image metadata: %w", err)
|
||||
return engineapi.ImageVerificationFail, fmt.Errorf("failed to parse image metadata: %w", err)
|
||||
} else {
|
||||
return ivm.IsVerified(image), nil
|
||||
return ivm.ImageVerificationStatus(image), nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ func GetWarningMessages(engineResponses []engineapi.EngineResponse) []string {
|
|||
var warnings []string
|
||||
for _, er := range engineResponses {
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
if rule.Status() != engineapi.RuleStatusPass && rule.Status() != engineapi.RuleStatusSkip {
|
||||
if rule.EmitWarning() {
|
||||
msg := fmt.Sprintf("policy %s.%s: %s", er.Policy().GetName(), rule.Name(), rule.Message())
|
||||
warnings = append(warnings, msg)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: v1
|
|||
kind: Pod
|
||||
metadata:
|
||||
annotations:
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}'
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}'
|
||||
name: zulu
|
||||
namespace: default
|
||||
spec:
|
||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: v1
|
|||
kind: Pod
|
||||
metadata:
|
||||
annotations:
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}'
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}'
|
||||
name: zulu
|
||||
namespace: default
|
||||
spec:
|
||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: v1
|
|||
kind: Pod
|
||||
metadata:
|
||||
annotations:
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}'
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}'
|
||||
name: zulu
|
||||
namespace: default
|
||||
spec:
|
||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: v1
|
|||
kind: Pod
|
||||
metadata:
|
||||
annotations:
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}'
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}'
|
||||
name: zulu
|
||||
namespace: default
|
||||
spec:
|
||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: v1
|
|||
kind: Pod
|
||||
metadata:
|
||||
annotations:
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}'
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}'
|
||||
name: zulu
|
||||
namespace: default
|
||||
spec:
|
||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: v1
|
|||
kind: Pod
|
||||
metadata:
|
||||
annotations:
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu:latest":true}'
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu:latest":"pass"}'
|
||||
name: zulu
|
||||
namespace: default
|
||||
spec:
|
||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: v1
|
|||
kind: Pod
|
||||
metadata:
|
||||
annotations:
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu:latest":true}'
|
||||
kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu:latest":"pass"}'
|
||||
name: zulu
|
||||
namespace: default
|
||||
spec:
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
## Description
|
||||
|
||||
This test tests the exclude image references attribute.
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
This test creates a cluster policy with exclude image references attribute.
|
||||
The pod that is not excluded will be verified and the pod that is excluded will be skipped
|
||||
|
||||
## Reference Issue(s)
|
||||
|
||||
8592
|
|
@ -0,0 +1,19 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
run: test-bad
|
||||
name: test-bad
|
||||
namespace: exclude-refs
|
||||
spec:
|
||||
containers:
|
||||
- image: ghcr.io/chipzoller/zulu:v0.0.14@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db
|
||||
name: test
|
||||
resources: {}
|
||||
- image: ghcr.io/kyverno/kyverno:latest
|
||||
name: test
|
||||
resources: {}
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Always
|
||||
status: {}
|
|
@ -0,0 +1,34 @@
|
|||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||
kind: Test
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: skip-image-reference
|
||||
spec:
|
||||
timeouts:
|
||||
delete: 2m
|
||||
steps:
|
||||
- name: step-01
|
||||
try:
|
||||
- apply:
|
||||
file: policy.yaml
|
||||
- assert:
|
||||
file: policy-ready.yaml
|
||||
- name: step-02
|
||||
try:
|
||||
- apply:
|
||||
file: pod.yaml
|
||||
- assert:
|
||||
file: pod-assert.yaml
|
||||
- name: step-03
|
||||
try:
|
||||
- apply:
|
||||
file: skipped.yaml
|
||||
- assert:
|
||||
file: skipped-assert.yaml
|
||||
- name: step-04
|
||||
try:
|
||||
- apply:
|
||||
expect:
|
||||
- check:
|
||||
($error != null): true
|
||||
file: bad.yaml
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test
|
||||
namespace: exclude-refs
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
run: test
|
||||
name: test
|
||||
namespace: exclude-refs
|
||||
spec:
|
||||
containers:
|
||||
- image: ghcr.io/kyverno/test-verify-image:signed
|
||||
name: test
|
||||
resources: {}
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Always
|
||||
status: {}
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: kyverno.io/v2beta1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: verify-exclude-refs
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,66 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: exclude-refs
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: keys
|
||||
namespace: exclude-refs
|
||||
data:
|
||||
certificate: |-
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDTTCCAjWgAwIBAgIJAPI+zAzn4s0xMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEPMA0GA1UECgwG
|
||||
Tm90YXJ5MQ0wCwYDVQQDDAR0ZXN0MB4XDTIzMDUyMjIxMTUxOFoXDTMzMDUxOTIx
|
||||
MTUxOFowTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0
|
||||
dGxlMQ8wDQYDVQQKDAZOb3RhcnkxDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQDNhTwv+QMk7jEHufFfIFlBjn2NiJaYPgL4eBS+
|
||||
b+o37ve5Zn9nzRppV6kGsa161r9s2KkLXmJrojNy6vo9a6g6RtZ3F6xKiWLUmbAL
|
||||
hVTCfYw/2n7xNlVMjyyUpE+7e193PF8HfQrfDFxe2JnX5LHtGe+X9vdvo2l41R6m
|
||||
Iia04DvpMdG4+da2tKPzXIuLUz/FDb6IODO3+qsqQLwEKmmUee+KX+3yw8I6G1y0
|
||||
Vp0mnHfsfutlHeG8gazCDlzEsuD4QJ9BKeRf2Vrb0ywqNLkGCbcCWF2H5Q80Iq/f
|
||||
ETVO9z88R7WheVdEjUB8UrY7ZMLdADM14IPhY2Y+tLaSzEVZAgMBAAGjMjAwMAkG
|
||||
A1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0G
|
||||
CSqGSIb3DQEBCwUAA4IBAQBX7x4Ucre8AIUmXZ5PUK/zUBVOrZZzR1YE8w86J4X9
|
||||
kYeTtlijf9i2LTZMfGuG0dEVFN4ae3CCpBst+ilhIndnoxTyzP+sNy4RCRQ2Y/k8
|
||||
Zq235KIh7uucq96PL0qsF9s2RpTKXxyOGdtp9+HO0Ty5txJE2txtLDUIVPK5WNDF
|
||||
ByCEQNhtHgN6V20b8KU2oLBZ9vyB8V010dQz0NRTDLhkcvJig00535/LUylECYAJ
|
||||
5/jn6XKt6UYCQJbVNzBg/YPGc1RF4xdsGVDBben/JXpeGEmkdmXPILTKd9tZ5TC0
|
||||
uOKpF5rWAruB5PCIrquamOejpXV9aQA/K2JQDuc0mcKz
|
||||
-----END CERTIFICATE-----
|
||||
---
|
||||
apiVersion: kyverno.io/v2beta1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: verify-exclude-refs
|
||||
spec:
|
||||
validationFailureAction: Enforce
|
||||
webhookTimeoutSeconds: 30
|
||||
failurePolicy: Fail
|
||||
rules:
|
||||
- name: verify-exclude-refs
|
||||
context:
|
||||
- name: keys
|
||||
configMap:
|
||||
name: keys
|
||||
namespace: exclude-refs
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
verifyImages:
|
||||
- type: Notary
|
||||
imageReferences:
|
||||
- "ghcr.io/*"
|
||||
skipImageReferences:
|
||||
- "ghcr.io/chipzoller*"
|
||||
attestors:
|
||||
- count: 1
|
||||
entries:
|
||||
- certificates:
|
||||
cert: "{{ keys.data.certificate }}"
|
||||
name: keys
|
||||
namespace: test-verify-images
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-skipped
|
||||
namespace: exclude-refs
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
run: test-skipped
|
||||
name: test-skipped
|
||||
namespace: exclude-refs
|
||||
spec:
|
||||
containers:
|
||||
- image: ghcr.io/chipzoller/zulu:v0.0.14@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db
|
||||
name: test
|
||||
resources: {}
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Always
|
||||
status: {}
|
Loading…
Add table
Reference in a new issue