mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-21 07:12:42 +00:00
feat: enable mutating webhook for ivpol (#12423)
* feat: enable mutating webhook for ivpol Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: unit tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: add objects to payload Signed-off-by: ShutingZhao <shuting@nirmata.com> * chore: add chainsaw test Signed-off-by: ShutingZhao <shuting@nirmata.com> * chore: add update codegen Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: propagate policy response to admission reponse Signed-off-by: ShutingZhao <shuting@nirmata.com> * chore: update chainsaw tests Signed-off-by: ShutingZhao <shuting@nirmata.com> --------- Signed-off-by: ShutingZhao <shuting@nirmata.com>
This commit is contained in:
parent
1982ebca47
commit
4f9b07070a
24 changed files with 525 additions and 376 deletions
|
@ -18,7 +18,6 @@ import (
|
|||
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
|
||||
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.ready`
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
type ImageVerificationPolicy struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
@ -29,7 +28,7 @@ type ImageVerificationPolicy struct {
|
|||
}
|
||||
|
||||
type IvpolStatus struct {
|
||||
ConditionStatus *ConditionStatus `json:",inline"`
|
||||
ConditionStatus `json:"conditionStatus,inline"`
|
||||
|
||||
// +optional
|
||||
Autogen IvpolAutogenStatus `json:"autogen,omitempty"`
|
||||
|
@ -114,10 +113,6 @@ func (s ImageVerificationPolicySpec) BackgroundEnabled() bool {
|
|||
}
|
||||
|
||||
func (status *IvpolStatus) SetReadyByCondition(c PolicyConditionType, s metav1.ConditionStatus, message string) {
|
||||
if status.ConditionStatus == nil {
|
||||
status.ConditionStatus = &ConditionStatus{}
|
||||
}
|
||||
|
||||
reason := "Succeeded"
|
||||
if s != metav1.ConditionTrue {
|
||||
reason = "Failed"
|
||||
|
@ -133,10 +128,7 @@ func (status *IvpolStatus) SetReadyByCondition(c PolicyConditionType, s metav1.C
|
|||
}
|
||||
|
||||
func (status *IvpolStatus) GetConditionStatus() *ConditionStatus {
|
||||
if status.ConditionStatus != nil {
|
||||
return status.ConditionStatus
|
||||
}
|
||||
return &ConditionStatus{}
|
||||
return &status.ConditionStatus
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
|
|
@ -44,7 +44,7 @@ func (status *ConditionStatus) SetReadyByCondition(c PolicyConditionType, s meta
|
|||
meta.SetStatusCondition(&status.Conditions, newCondition)
|
||||
}
|
||||
|
||||
func (status *ConditionStatus) IsReady() bool {
|
||||
func (status ConditionStatus) IsReady() bool {
|
||||
if status.Ready != nil {
|
||||
return *status.Ready
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ func TestPolicyStatus_IsReady(t *testing.T) {
|
|||
}, {
|
||||
name: "true",
|
||||
status: VpolStatus{
|
||||
ConditionStatus: &ConditionStatus{
|
||||
ConditionStatus: ConditionStatus{
|
||||
Ready: ptr.To(true),
|
||||
},
|
||||
},
|
||||
|
@ -29,7 +29,7 @@ func TestPolicyStatus_IsReady(t *testing.T) {
|
|||
}, {
|
||||
name: "false",
|
||||
status: VpolStatus{
|
||||
ConditionStatus: &ConditionStatus{
|
||||
ConditionStatus: ConditionStatus{
|
||||
Ready: ptr.To(false),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -24,7 +24,7 @@ type ValidatingPolicy struct {
|
|||
}
|
||||
|
||||
type VpolStatus struct {
|
||||
ConditionStatus *ConditionStatus `json:",inline"`
|
||||
ConditionStatus `json:"conditionStatus,inline"`
|
||||
|
||||
// +optional
|
||||
Autogen AutogenStatus `json:"autogen"`
|
||||
|
@ -87,10 +87,7 @@ func (s *ValidatingPolicy) GetKind() string {
|
|||
}
|
||||
|
||||
func (status *VpolStatus) GetConditionStatus() *ConditionStatus {
|
||||
if status.ConditionStatus != nil {
|
||||
return status.ConditionStatus
|
||||
}
|
||||
return &ConditionStatus{}
|
||||
return &status.ConditionStatus
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
|
|
@ -714,11 +714,7 @@ func (in *IvpolAutogenStatus) DeepCopy() *IvpolAutogenStatus {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *IvpolStatus) DeepCopyInto(out *IvpolStatus) {
|
||||
*out = *in
|
||||
if in.ConditionStatus != nil {
|
||||
in, out := &in.ConditionStatus, &out.ConditionStatus
|
||||
*out = new(ConditionStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
in.ConditionStatus.DeepCopyInto(&out.ConditionStatus)
|
||||
in.Autogen.DeepCopyInto(&out.Autogen)
|
||||
return
|
||||
}
|
||||
|
@ -1009,11 +1005,7 @@ func (in *ValidatingPolicySpec) DeepCopy() *ValidatingPolicySpec {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *VpolStatus) DeepCopyInto(out *VpolStatus) {
|
||||
*out = *in
|
||||
if in.ConditionStatus != nil {
|
||||
in, out := &in.ConditionStatus, &out.ConditionStatus
|
||||
*out = new(ConditionStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
in.ConditionStatus.DeepCopyInto(&out.ConditionStatus)
|
||||
in.Autogen.DeepCopyInto(&out.Autogen)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -731,10 +731,11 @@ func main() {
|
|||
Validation: webhooks.HandlerFunc(policyHandlers.Validate),
|
||||
},
|
||||
webhooks.ResourceHandlers{
|
||||
Mutation: webhooks.HandlerFunc(resourceHandlers.Mutate),
|
||||
Validation: webhooks.HandlerFunc(resourceHandlers.Validate),
|
||||
ValidatingPolicies: webhooks.HandlerFunc(voplHandlers.Validate),
|
||||
ImageVerificationPolicies: webhooks.HandlerFunc(ivpolHandlers.Validate),
|
||||
Mutation: webhooks.HandlerFunc(resourceHandlers.Mutate),
|
||||
ImageVerificationPoliciesMutation: webhooks.HandlerFunc(ivpolHandlers.Mutate),
|
||||
Validation: webhooks.HandlerFunc(resourceHandlers.Validate),
|
||||
ValidatingPolicies: webhooks.HandlerFunc(voplHandlers.Validate),
|
||||
ImageVerificationPolicies: webhooks.HandlerFunc(ivpolHandlers.Validate),
|
||||
},
|
||||
webhooks.ExceptionHandlers{
|
||||
Validation: webhooks.HandlerFunc(exceptionHandlers.Validate),
|
||||
|
|
|
@ -10176,8 +10176,6 @@ Resource Types:
|
|||
<ul><li>
|
||||
<a href="#policies.kyverno.io/v1alpha1.CELPolicyException">CELPolicyException</a>
|
||||
</li><li>
|
||||
<a href="#policies.kyverno.io/v1alpha1.ImageVerificationPolicy">ImageVerificationPolicy</a>
|
||||
</li><li>
|
||||
<a href="#policies.kyverno.io/v1alpha1.ValidatingPolicy">ValidatingPolicy</a>
|
||||
</li></ul>
|
||||
<hr />
|
||||
|
@ -10272,307 +10270,6 @@ CELPolicyExceptionSpec
|
|||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="policies.kyverno.io/v1alpha1.ImageVerificationPolicy">ImageVerificationPolicy
|
||||
</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>apiVersion</code><br/>
|
||||
string</td>
|
||||
<td>
|
||||
<code>
|
||||
policies.kyverno.io/v1alpha1
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>kind</code><br/>
|
||||
string
|
||||
</td>
|
||||
<td><code>ImageVerificationPolicy</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>metadata</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#objectmeta-v1-meta">
|
||||
Kubernetes meta/v1.ObjectMeta
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
Refer to the Kubernetes API documentation for the fields of the
|
||||
<code>metadata</code> field.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>spec</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.ImageVerificationPolicySpec">
|
||||
ImageVerificationPolicySpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<br/>
|
||||
<br/>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<td>
|
||||
<code>matchConstraints</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#matchresources-v1-admissionregistration">
|
||||
Kubernetes admissionregistration/v1.MatchResources
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>MatchConstraints specifies what resources this policy is designed to validate.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>failurePolicy</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#failurepolicytype-v1-admissionregistration">
|
||||
Kubernetes admissionregistration/v1.FailurePolicyType
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>FailurePolicy defines how to handle failures for the admission policy. Failures can
|
||||
occur from CEL expression parse errors, type check errors, runtime errors and invalid
|
||||
or mis-configured policy definitions or bindings.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>validationActions</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#validationaction-v1-admissionregistration">
|
||||
[]Kubernetes admissionregistration/v1.ValidationAction
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>ValidationAction specifies the action to be taken when the matched resource violates the policy.
|
||||
Required.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>matchConditions</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#matchcondition-v1-admissionregistration">
|
||||
[]Kubernetes admissionregistration/v1.MatchCondition
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>MatchConditions is a list of conditions that must be met for a request to be validated.
|
||||
Match conditions filter requests that have already been matched by the rules,
|
||||
namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests.
|
||||
There are a maximum of 64 match conditions allowed.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>variables</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#variable-v1-admissionregistration">
|
||||
[]Kubernetes admissionregistration/v1.Variable
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Variables contain definitions of variables that can be used in composition of other expressions.
|
||||
Each variable is defined as a named CEL expression.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>imageRules</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.ImageRule">
|
||||
[]ImageRule
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>ImagesRules is a list of Glob and CELExpressions to match images.
|
||||
Any image that matches one of the rules is considered for validation
|
||||
Any image that does not match a rule is skipped, even when they are passed as arguments to
|
||||
image verification functions</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>mutateDigest</code><br/>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>MutateDigest enables replacement of image tags with digests.
|
||||
Defaults to true.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>verifyDigest</code><br/>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>VerifyDigest validates that images have a digest.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>required</code><br/>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Required validates that images are verified i.e. have matched passed a signature or attestation check.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>credentials</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.Credentials">
|
||||
Credentials
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Credentials provides credentials that will be used for authentication with registry.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>images</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.Image">
|
||||
[]Image
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Images is a list of CEL expression to extract images from the resource</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>attestors</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.Attestor">
|
||||
[]Attestor
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Attestors provides a list of trusted authorities.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>attestations</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.Attestation">
|
||||
[]Attestation
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Attestations provides a list of image metadata to verify</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>verifications</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#validation-v1-admissionregistration">
|
||||
[]Kubernetes admissionregistration/v1.Validation
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Verifications contain CEL expressions which is used to apply the image verification checks.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>webhookConfiguration</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.WebhookConfiguration">
|
||||
WebhookConfiguration
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>WebhookConfiguration defines the configuration for the webhook.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>evaluation</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.EvaluationConfiguration">
|
||||
EvaluationConfiguration
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>EvaluationConfiguration defines the configuration for the policy evaluation.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>status</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.IvpolStatus">
|
||||
IvpolStatus
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Status contains policy runtime data.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="policies.kyverno.io/v1alpha1.ValidatingPolicy">ValidatingPolicy
|
||||
</h3>
|
||||
<p>
|
||||
|
@ -11782,6 +11479,290 @@ string
|
|||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="policies.kyverno.io/v1alpha1.ImageVerificationPolicy">ImageVerificationPolicy
|
||||
</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>metadata</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#objectmeta-v1-meta">
|
||||
Kubernetes meta/v1.ObjectMeta
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
Refer to the Kubernetes API documentation for the fields of the
|
||||
<code>metadata</code> field.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>spec</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.ImageVerificationPolicySpec">
|
||||
ImageVerificationPolicySpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<br/>
|
||||
<br/>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<td>
|
||||
<code>matchConstraints</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#matchresources-v1-admissionregistration">
|
||||
Kubernetes admissionregistration/v1.MatchResources
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>MatchConstraints specifies what resources this policy is designed to validate.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>failurePolicy</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#failurepolicytype-v1-admissionregistration">
|
||||
Kubernetes admissionregistration/v1.FailurePolicyType
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>FailurePolicy defines how to handle failures for the admission policy. Failures can
|
||||
occur from CEL expression parse errors, type check errors, runtime errors and invalid
|
||||
or mis-configured policy definitions or bindings.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>validationActions</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#validationaction-v1-admissionregistration">
|
||||
[]Kubernetes admissionregistration/v1.ValidationAction
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>ValidationAction specifies the action to be taken when the matched resource violates the policy.
|
||||
Required.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>matchConditions</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#matchcondition-v1-admissionregistration">
|
||||
[]Kubernetes admissionregistration/v1.MatchCondition
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>MatchConditions is a list of conditions that must be met for a request to be validated.
|
||||
Match conditions filter requests that have already been matched by the rules,
|
||||
namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests.
|
||||
There are a maximum of 64 match conditions allowed.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>variables</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#variable-v1-admissionregistration">
|
||||
[]Kubernetes admissionregistration/v1.Variable
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Variables contain definitions of variables that can be used in composition of other expressions.
|
||||
Each variable is defined as a named CEL expression.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>imageRules</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.ImageRule">
|
||||
[]ImageRule
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>ImagesRules is a list of Glob and CELExpressions to match images.
|
||||
Any image that matches one of the rules is considered for validation
|
||||
Any image that does not match a rule is skipped, even when they are passed as arguments to
|
||||
image verification functions</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>mutateDigest</code><br/>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>MutateDigest enables replacement of image tags with digests.
|
||||
Defaults to true.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>verifyDigest</code><br/>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>VerifyDigest validates that images have a digest.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>required</code><br/>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Required validates that images are verified i.e. have matched passed a signature or attestation check.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>credentials</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.Credentials">
|
||||
Credentials
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Credentials provides credentials that will be used for authentication with registry.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>images</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.Image">
|
||||
[]Image
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Images is a list of CEL expression to extract images from the resource</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>attestors</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.Attestor">
|
||||
[]Attestor
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Attestors provides a list of trusted authorities.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>attestations</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.Attestation">
|
||||
[]Attestation
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Attestations provides a list of image metadata to verify</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>verifications</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#validation-v1-admissionregistration">
|
||||
[]Kubernetes admissionregistration/v1.Validation
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Verifications contain CEL expressions which is used to apply the image verification checks.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>webhookConfiguration</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.WebhookConfiguration">
|
||||
WebhookConfiguration
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>WebhookConfiguration defines the configuration for the webhook.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>evaluation</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.EvaluationConfiguration">
|
||||
EvaluationConfiguration
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>EvaluationConfiguration defines the configuration for the policy evaluation.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>status</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.IvpolStatus">
|
||||
IvpolStatus
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Status contains policy runtime data.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="policies.kyverno.io/v1alpha1.ImageVerificationPolicySpec">ImageVerificationPolicySpec
|
||||
</h3>
|
||||
<p>
|
||||
|
@ -12378,7 +12359,7 @@ EvaluationConfiguration
|
|||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>ConditionStatus</code><br/>
|
||||
<code>conditionStatus</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.ConditionStatus">
|
||||
ConditionStatus
|
||||
|
@ -12387,7 +12368,7 @@ ConditionStatus
|
|||
</td>
|
||||
<td>
|
||||
<p>
|
||||
(Members of <code>ConditionStatus</code> are embedded into this type.)
|
||||
(Members of <code>conditionStatus</code> are embedded into this type.)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -13006,7 +12987,7 @@ EvaluationConfiguration
|
|||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>ConditionStatus</code><br/>
|
||||
<code>conditionStatus</code><br/>
|
||||
<em>
|
||||
<a href="#policies.kyverno.io/v1alpha1.ConditionStatus">
|
||||
ConditionStatus
|
||||
|
@ -13015,7 +12996,7 @@ ConditionStatus
|
|||
</td>
|
||||
<td>
|
||||
<p>
|
||||
(Members of <code>ConditionStatus</code> are embedded into this type.)
|
||||
(Members of <code>conditionStatus</code> are embedded into this type.)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -120,14 +120,6 @@ func convertMatchConditions(conditions []admissionregistrationv1.MatchCondition,
|
|||
m.Expression = expression + m.Expression
|
||||
matchConditions = append(matchConditions, m)
|
||||
}
|
||||
// if bytes, err := json.Marshal(matchConditions); err != nil {
|
||||
// return nil, err
|
||||
// } else {
|
||||
// bytes = updateFields(bytes, resource)
|
||||
// if err := json.Unmarshal(bytes, &matchConditions); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// }
|
||||
return matchConditions, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -292,6 +292,7 @@ func (e *ivengine) handleValidation(policies []CompiledImageVerificationPolicy,
|
|||
} else {
|
||||
resp.Result = *engineapi.NewRuleResponse(o.Name, engineapi.ImageVerify, o.Message, o.Status, o.Properties)
|
||||
}
|
||||
responses[pol.Policy.GetName()] = resp
|
||||
}
|
||||
}
|
||||
return maps.Values(responses), nil
|
||||
|
|
|
@ -54,8 +54,10 @@ const (
|
|||
VerifyMutatingWebhookName = "monitor-webhooks.kyverno.svc"
|
||||
// ValidatingPolicyWebhookName defines default webhook name for validatingpolicies
|
||||
ValidatingPolicyWebhookName = "vpol.validate.kyverno.svc"
|
||||
// ImageVerificationPolicyWebhookName defines default webhook name for imageverificationpolicies
|
||||
ImageVerificationPolicyWebhookName = "ivpol.validate.kyverno.svc"
|
||||
// ImageVerificationPolicyWebhookName defines default validating webhook name for imageverificationpolicies
|
||||
ImageVerificationPolicyValidateWebhookName = "ivpol.validate.kyverno.svc"
|
||||
// ImageVerificationPolicyWebhookName defines default mutating webhook name for imageverificationpolicies
|
||||
ImageVerificationPolicyMutateWebhookName = "ivpol.mutate.kyverno.svc"
|
||||
)
|
||||
|
||||
// paths
|
||||
|
|
|
@ -38,7 +38,7 @@ func (c controller) updateIvpolStatus(ctx context.Context, ivpol *policiesv1alph
|
|||
if conditionStatus.Ready == nil || conditionStatus.IsReady() != ready {
|
||||
conditionStatus.Ready = &ready
|
||||
}
|
||||
status.ConditionStatus = conditionStatus
|
||||
status.ConditionStatus = *conditionStatus
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ func (c controller) updateVpolStatus(ctx context.Context, vpol *policiesv1alpha1
|
|||
if conditionStatus.Ready == nil || conditionStatus.IsReady() != ready {
|
||||
conditionStatus.Ready = &ready
|
||||
}
|
||||
status.ConditionStatus = conditionStatus
|
||||
status.ConditionStatus = *conditionStatus
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -811,17 +811,68 @@ func (c *controller) buildDefaultResourceMutatingWebhookConfiguration(_ context.
|
|||
}
|
||||
|
||||
func (c *controller) buildResourceMutatingWebhookConfiguration(ctx context.Context, cfg config.Configuration, caBundle []byte) (*admissionregistrationv1.MutatingWebhookConfiguration, error) {
|
||||
result := admissionregistrationv1.MutatingWebhookConfiguration{
|
||||
result := &admissionregistrationv1.MutatingWebhookConfiguration{
|
||||
ObjectMeta: objectMeta(config.MutatingWebhookConfigurationName, cfg.GetWebhookAnnotations(), cfg.GetWebhookLabels(), c.buildOwner()...),
|
||||
Webhooks: []admissionregistrationv1.MutatingWebhook{},
|
||||
}
|
||||
|
||||
var errs []error
|
||||
if err := c.buildForPoliciesMutation(ctx, cfg, caBundle, result); err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to build webhook rules for policies: %v", err))
|
||||
}
|
||||
|
||||
if err := c.buildForJSONPoliciesMutation(cfg, caBundle, result); err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to build webhook rules for imageverificationpolicies: %v", err))
|
||||
}
|
||||
return result, multierr.Combine(errs...)
|
||||
}
|
||||
|
||||
func (c *controller) buildForJSONPoliciesMutation(cfg config.Configuration, caBundle []byte, result *admissionregistrationv1.MutatingWebhookConfiguration) error {
|
||||
if !c.watchdogCheck() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ivpols, err := c.getImageVerificationPolicy()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
validate := buildWebhookRules(cfg,
|
||||
c.server,
|
||||
config.ImageVerificationPolicyMutateWebhookName,
|
||||
config.PolicyServicePath+config.ImageVerificationPolicyServicePath+config.MutatingWebhookServicePath,
|
||||
c.servicePort,
|
||||
caBundle,
|
||||
ivpols)
|
||||
|
||||
mutate := make([]admissionregistrationv1.MutatingWebhook, 0, len(validate))
|
||||
for _, w := range validate {
|
||||
mutate = append(mutate, admissionregistrationv1.MutatingWebhook{
|
||||
Name: w.Name,
|
||||
ClientConfig: w.ClientConfig,
|
||||
FailurePolicy: w.FailurePolicy,
|
||||
SideEffects: w.SideEffects,
|
||||
AdmissionReviewVersions: w.AdmissionReviewVersions,
|
||||
NamespaceSelector: w.NamespaceSelector,
|
||||
ObjectSelector: w.ObjectSelector,
|
||||
Rules: w.Rules,
|
||||
MatchConditions: w.MatchConditions,
|
||||
TimeoutSeconds: w.TimeoutSeconds,
|
||||
})
|
||||
}
|
||||
result.Webhooks = append(result.Webhooks, mutate...)
|
||||
// todo(shuting): record policy state?
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *controller) buildForPoliciesMutation(ctx context.Context, cfg config.Configuration, caBundle []byte, result *admissionregistrationv1.MutatingWebhookConfiguration) error {
|
||||
if c.watchdogCheck() {
|
||||
webhookCfg := cfg.GetWebhook()
|
||||
ignoreWebhook := newWebhook(c.defaultTimeout, ignore, cfg.GetMatchConditions())
|
||||
failWebhook := newWebhook(c.defaultTimeout, fail, cfg.GetMatchConditions())
|
||||
policies, err := c.getAllPolicies()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
var fineGrainedIgnoreList, fineGrainedFailList []*webhook
|
||||
c.recordKyvernoPolicyState(config.MutatingWebhookConfigurationName, policies...)
|
||||
|
@ -856,7 +907,7 @@ func (c *controller) buildResourceMutatingWebhookConfiguration(ctx context.Conte
|
|||
} else {
|
||||
c.recordKyvernoPolicyState(config.MutatingWebhookConfigurationName)
|
||||
}
|
||||
return &result, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *controller) buildResourceMutatingWebhookRules(caBundle []byte, webhookCfg config.WebhookConfig, sideEffects *admissionregistrationv1.SideEffectClass, webhooks []*webhook) []admissionregistrationv1.MutatingWebhook {
|
||||
|
@ -954,18 +1005,18 @@ func (c *controller) buildResourceValidatingWebhookConfiguration(ctx context.Con
|
|||
}
|
||||
|
||||
var errs []error
|
||||
if err := c.buildForPolicies(ctx, cfg, caBundle, webhookConfig); err != nil {
|
||||
if err := c.buildForPoliciesValidation(ctx, cfg, caBundle, webhookConfig); err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to build webhook rules for policies: %v", err))
|
||||
}
|
||||
|
||||
if err := c.buildForValidatingPolicies(cfg, caBundle, webhookConfig); err != nil {
|
||||
if err := c.buildForJSONPoliciesValidation(cfg, caBundle, webhookConfig); err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to build webhook rules for validatingpolicies: %v", err))
|
||||
}
|
||||
|
||||
return webhookConfig, multierr.Combine(errs...)
|
||||
}
|
||||
|
||||
func (c *controller) buildForValidatingPolicies(cfg config.Configuration, caBundle []byte, result *admissionregistrationv1.ValidatingWebhookConfiguration) error {
|
||||
func (c *controller) buildForJSONPoliciesValidation(cfg config.Configuration, caBundle []byte, result *admissionregistrationv1.ValidatingWebhookConfiguration) error {
|
||||
if !c.watchdogCheck() {
|
||||
return nil
|
||||
}
|
||||
|
@ -977,7 +1028,7 @@ func (c *controller) buildForValidatingPolicies(cfg config.Configuration, caBund
|
|||
result.Webhooks = append(result.Webhooks, buildWebhookRules(cfg,
|
||||
c.server,
|
||||
config.ValidatingPolicyWebhookName,
|
||||
config.PolicyServicePath+config.ValidatingPolicyServicePath,
|
||||
config.PolicyServicePath+config.ValidatingPolicyServicePath+config.ValidatingWebhookServicePath,
|
||||
c.servicePort,
|
||||
caBundle,
|
||||
pols)...)
|
||||
|
@ -988,8 +1039,8 @@ func (c *controller) buildForValidatingPolicies(cfg config.Configuration, caBund
|
|||
}
|
||||
result.Webhooks = append(result.Webhooks, buildWebhookRules(cfg,
|
||||
c.server,
|
||||
config.ImageVerificationPolicyWebhookName,
|
||||
config.PolicyServicePath+config.ImageVerificationPolicyServicePath,
|
||||
config.ImageVerificationPolicyValidateWebhookName,
|
||||
config.PolicyServicePath+config.ImageVerificationPolicyServicePath+config.ValidatingWebhookServicePath,
|
||||
c.servicePort,
|
||||
caBundle,
|
||||
ivpols)...)
|
||||
|
@ -998,7 +1049,7 @@ func (c *controller) buildForValidatingPolicies(cfg config.Configuration, caBund
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *controller) buildForPolicies(ctx context.Context, cfg config.Configuration, caBundle []byte, result *admissionregistrationv1.ValidatingWebhookConfiguration) error {
|
||||
func (c *controller) buildForPoliciesValidation(ctx context.Context, cfg config.Configuration, caBundle []byte, result *admissionregistrationv1.ValidatingWebhookConfiguration) error {
|
||||
if c.watchdogCheck() {
|
||||
webhookCfg := cfg.GetWebhook()
|
||||
ignoreWebhook := newWebhook(c.defaultTimeout, ignore, cfg.GetMatchConditions())
|
||||
|
|
|
@ -139,7 +139,7 @@ func TestBuildWebhookRules_ValidatingPolicy(t *testing.T) {
|
|||
expectedWebhooks: []admissionregistrationv1.ValidatingWebhook{
|
||||
{
|
||||
Name: config.ValidatingPolicyWebhookName + "-ignore-finegrained-test-fine-grained-ignore",
|
||||
ClientConfig: newClientConfig("", 0, nil, "/policies/vpol/ignore"+config.FineGrainedWebhookPath+"/test-fine-grained-ignore"),
|
||||
ClientConfig: newClientConfig("", 0, nil, "/policies/vpol/validate/ignore"+config.FineGrainedWebhookPath+"/test-fine-grained-ignore"),
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
|
||||
|
@ -197,7 +197,7 @@ func TestBuildWebhookRules_ValidatingPolicy(t *testing.T) {
|
|||
expectedWebhooks: []admissionregistrationv1.ValidatingWebhook{
|
||||
{
|
||||
Name: config.ValidatingPolicyWebhookName + "-fail-finegrained-test-fine-grained-fail",
|
||||
ClientConfig: newClientConfig("", 0, nil, "/policies/vpol/fail"+config.FineGrainedWebhookPath+"/test-fine-grained-fail"),
|
||||
ClientConfig: newClientConfig("", 0, nil, "/policies/vpol/validate/fail"+config.FineGrainedWebhookPath+"/test-fine-grained-fail"),
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
|
||||
|
@ -230,7 +230,7 @@ func TestBuildWebhookRules_ValidatingPolicy(t *testing.T) {
|
|||
vpols = append(vpols, engineapi.NewValidatingPolicy(vpol))
|
||||
}
|
||||
webhooks := buildWebhookRules(config.NewDefaultConfiguration(false), "", config.ValidatingPolicyWebhookName,
|
||||
config.PolicyServicePath+config.ValidatingPolicyServicePath, 0, nil, vpols)
|
||||
config.PolicyServicePath+config.ValidatingPolicyServicePath+config.ValidatingWebhookServicePath, 0, nil, vpols)
|
||||
assert.Equal(t, len(tt.expectedWebhooks), len(webhooks))
|
||||
for i, expect := range tt.expectedWebhooks {
|
||||
assert.Equal(t, expect.Name, webhooks[i].Name)
|
||||
|
@ -286,7 +286,7 @@ func TestBuildWebhookRules_ImageVerificationPolicy(t *testing.T) {
|
|||
},
|
||||
expectedWebhooks: []admissionregistrationv1.ValidatingWebhook{
|
||||
{
|
||||
Name: config.ImageVerificationPolicyWebhookName + "-ignore",
|
||||
Name: config.ImageVerificationPolicyValidateWebhookName + "-ignore",
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
|
||||
|
@ -367,8 +367,8 @@ func TestBuildWebhookRules_ImageVerificationPolicy(t *testing.T) {
|
|||
},
|
||||
expectedWebhooks: []admissionregistrationv1.ValidatingWebhook{
|
||||
{
|
||||
Name: config.ImageVerificationPolicyWebhookName + "-ignore-finegrained-ivpol-sample",
|
||||
ClientConfig: newClientConfig("", 0, nil, "/policies/ivpol/ignore"+config.FineGrainedWebhookPath+"/ivpol-sample"),
|
||||
Name: config.ImageVerificationPolicyValidateWebhookName + "-ignore-finegrained-ivpol-sample",
|
||||
ClientConfig: newClientConfig("", 0, nil, "/policies/ivpol/validate/ignore"+config.FineGrainedWebhookPath+"/ivpol-sample"),
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
|
||||
|
@ -433,8 +433,8 @@ func TestBuildWebhookRules_ImageVerificationPolicy(t *testing.T) {
|
|||
for _, ivpol := range tt.ivpols {
|
||||
ivpols = append(ivpols, engineapi.NewImageVerificationPolicy(ivpol))
|
||||
}
|
||||
webhooks := buildWebhookRules(config.NewDefaultConfiguration(false), "", config.ImageVerificationPolicyWebhookName,
|
||||
config.PolicyServicePath+config.ImageVerificationPolicyServicePath, 0, nil, ivpols)
|
||||
webhooks := buildWebhookRules(config.NewDefaultConfiguration(false), "", config.ImageVerificationPolicyValidateWebhookName,
|
||||
config.PolicyServicePath+config.ImageVerificationPolicyServicePath+config.ValidatingWebhookServicePath, 0, nil, ivpols)
|
||||
assert.Equal(t, len(tt.expectedWebhooks), len(webhooks), tt.name)
|
||||
for i, expect := range tt.expectedWebhooks {
|
||||
assert.Equal(t, expect.Name, webhooks[i].Name)
|
||||
|
|
|
@ -148,8 +148,18 @@ func (p *compiledPolicy) match(
|
|||
if err != nil {
|
||||
return false, fmt.Errorf("failed to prepare request variable for evaluation: %w", err)
|
||||
}
|
||||
objectVal, err := objectToResolveVal(attr.GetObject())
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to prepare object variable for evaluation: %w", err)
|
||||
}
|
||||
oldObjectVal, err := objectToResolveVal(attr.GetOldObject())
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to prepare oldObject variable for evaluation: %w", err)
|
||||
}
|
||||
data[NamespaceObjectKey] = namespaceVal
|
||||
data[RequestKey] = requestVal.Object
|
||||
data[ObjectKey] = objectVal
|
||||
data[OldObjectKey] = oldObjectVal
|
||||
} else {
|
||||
data[ObjectKey] = request
|
||||
}
|
||||
|
|
|
@ -88,6 +88,23 @@ func NewServer(
|
|||
WithAdmission(resourceLogger.WithName("mutate"))
|
||||
},
|
||||
)
|
||||
registerWebhookHandlersWithAll(
|
||||
mux,
|
||||
"IVPOL-MUTATE",
|
||||
config.PolicyServicePath+config.ImageVerificationPolicyServicePath+config.MutatingWebhookServicePath,
|
||||
resourceHandlers.ImageVerificationPoliciesMutation,
|
||||
func(handler handlers.AdmissionHandler) handlers.HttpHandler {
|
||||
return handler.
|
||||
WithFilter(configuration).
|
||||
WithProtection(toggle.FromContext(ctx).ProtectManagedResources()).
|
||||
WithDump(debugModeOpts.DumpPayload).
|
||||
WithTopLevelGVK(discovery).
|
||||
WithRoles(rbLister, crbLister).
|
||||
WithOperationFilter(admissionv1.Create, admissionv1.Update, admissionv1.Connect).
|
||||
WithMetrics(resourceLogger, metricsConfig.Config(), metrics.WebhookMutating).
|
||||
WithAdmission(resourceLogger.WithName("mutate"))
|
||||
},
|
||||
)
|
||||
registerWebhookHandlersWithAll(
|
||||
mux,
|
||||
"VALIDATE",
|
||||
|
@ -107,7 +124,7 @@ func NewServer(
|
|||
registerWebhookHandlers(
|
||||
mux,
|
||||
"VPOL",
|
||||
config.PolicyServicePath+config.ValidatingPolicyServicePath,
|
||||
config.PolicyServicePath+config.ValidatingPolicyServicePath+config.ValidatingWebhookServicePath,
|
||||
resourceHandlers.ValidatingPolicies,
|
||||
func(handler handlers.AdmissionHandler) handlers.HttpHandler {
|
||||
return handler.
|
||||
|
@ -122,8 +139,8 @@ func NewServer(
|
|||
)
|
||||
registerWebhookHandlers(
|
||||
mux,
|
||||
"IVPOL",
|
||||
config.PolicyServicePath+config.ImageVerificationPolicyServicePath,
|
||||
"IVPOL-VALIDATE",
|
||||
config.PolicyServicePath+config.ImageVerificationPolicyServicePath+config.ValidatingWebhookServicePath,
|
||||
resourceHandlers.ImageVerificationPolicies,
|
||||
func(handler handlers.AdmissionHandler) handlers.HttpHandler {
|
||||
return handler.
|
||||
|
|
|
@ -54,6 +54,8 @@ type ResourceHandlers struct {
|
|||
Validation Handler
|
||||
// ValidatingPolicies evaluates validating policies against kube resources
|
||||
ValidatingPolicies Handler
|
||||
// ImageVerificationPolicies evaluates imageverificationpolicies against kube resources
|
||||
// ImageVerificationPolicies evaluates imageverificationpolicies mutation phase against kube resources
|
||||
ImageVerificationPoliciesMutation Handler
|
||||
// ImageVerificationPolicies evaluates imageverificationpolicies validation phase against kube resources
|
||||
ImageVerificationPolicies Handler
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-pod-bad
|
||||
namespace: default
|
||||
labels:
|
||||
prod: "true"
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: 'ghcr.io/kyverno/test-verify-image:unsigned'
|
|
@ -0,0 +1,29 @@
|
|||
# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json
|
||||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||
kind: Test
|
||||
metadata:
|
||||
name: audit
|
||||
spec:
|
||||
steps:
|
||||
- name: create policy
|
||||
try:
|
||||
- create:
|
||||
file: policy.yaml
|
||||
- sleep:
|
||||
duration: 10s
|
||||
- name: create bad pod
|
||||
try:
|
||||
- create:
|
||||
file: bad-pod.yaml
|
||||
expect:
|
||||
- check:
|
||||
($error): >-
|
||||
admission webhook "ivpol.validate.kyverno.svc-ignore-finegrained-ivpol-sample" denied the request: Policy ivpol-sample failed: failed to verify image with notary cert
|
||||
- name: create good pod
|
||||
try:
|
||||
- create:
|
||||
file: good-pod.yaml
|
||||
- sleep:
|
||||
duration: 10s
|
||||
- assert:
|
||||
file: good-pod.yaml
|
|
@ -0,0 +1,11 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-pod-good
|
||||
namespace: default
|
||||
labels:
|
||||
prod: "true"
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: 'ghcr.io/kyverno/test-verify-image:signed'
|
|
@ -0,0 +1,60 @@
|
|||
apiVersion: policies.kyverno.io/v1alpha1
|
||||
kind: ImageVerificationPolicy
|
||||
metadata:
|
||||
name: ivpol-sample
|
||||
spec:
|
||||
webhookConfiguration:
|
||||
timeoutSeconds: 20
|
||||
failurePolicy: Ignore
|
||||
validationActions:
|
||||
- Deny
|
||||
matchConstraints:
|
||||
resourceRules:
|
||||
- apiGroups: [""]
|
||||
apiVersions: ["v1"]
|
||||
operations: ["CREATE"]
|
||||
resources: ["pods"]
|
||||
matchConditions:
|
||||
- name: "check-prod-label"
|
||||
expression: >-
|
||||
has(object.metadata.labels) && has(object.metadata.labels.prod) && object.metadata.labels.prod == 'true'
|
||||
imageRules:
|
||||
- glob: ghcr.io/*
|
||||
attestors:
|
||||
- name: notary
|
||||
notary:
|
||||
certs: |-
|
||||
-----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-----
|
||||
attestations:
|
||||
- name: sbom
|
||||
referrer:
|
||||
type: sbom/cyclone-dx
|
||||
verifications:
|
||||
- expression: >-
|
||||
images.containers.map(image, verifyImageSignatures(image, [attestors.notary])).all(e, e > 0)
|
||||
message: failed to verify image with notary cert
|
||||
- expression: >-
|
||||
images.containers.map(image, verifyAttestationSignatures(image, attestations.sbom ,[attestors.notary])).all(e, e > 0)
|
||||
message: failed to verify attestation with notary cer
|
||||
- expression: >-
|
||||
images.containers.map(image, payload(image, attestations.sbom).bomFormat == 'CycloneDX').all(e, e)
|
||||
message: sbom is not a cyclone dx sbom
|
|
@ -11,7 +11,7 @@ webhooks:
|
|||
service:
|
||||
name: kyverno-svc
|
||||
namespace: kyverno
|
||||
path: /policies/vpol/fail/finegrained/disallow-privilege-escalation
|
||||
path: /policies/vpol/validate/fail/finegrained/disallow-privilege-escalation
|
||||
port: 443
|
||||
failurePolicy: Fail
|
||||
matchConditions:
|
||||
|
|
|
@ -11,7 +11,7 @@ webhooks:
|
|||
service:
|
||||
name: kyverno-svc
|
||||
namespace: kyverno
|
||||
path: /policies/vpol/fail
|
||||
path: /policies/vpol/validate/fail
|
||||
port: 443
|
||||
failurePolicy: Fail
|
||||
matchPolicy: Equivalent
|
||||
|
|
|
@ -11,7 +11,7 @@ webhooks:
|
|||
service:
|
||||
name: kyverno-svc
|
||||
namespace: kyverno
|
||||
path: /policies/vpol/fail
|
||||
path: /policies/vpol/validate/fail
|
||||
port: 443
|
||||
failurePolicy: Fail
|
||||
matchPolicy: Equivalent
|
||||
|
|
Loading…
Add table
Reference in a new issue