1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

Add image data to validate image configs (#2946)

* Add image data to validate image configs

Signed-off-by: Sambhav Kothari <sambhavs.email@gmail.com>

* Add tests for image context

Signed-off-by: Sambhav Kothari <sambhavs.email@gmail.com>

* Add e2e test cases for image size policy

Signed-off-by: Sambhav Kothari <sambhavs.email@gmail.com>
This commit is contained in:
Sambhav Kothari 2022-01-17 04:06:44 +00:00 committed by GitHub
parent f42092208f
commit 1af9e48b0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1021 additions and 222 deletions

View file

@ -145,7 +145,7 @@ docker-build-kyverno: docker-buildx-builder
docker-build-kyverno-local:
CGO_ENABLED=0 GOOS=linux go build -o $(PWD)/$(KYVERNO_PATH)/kyverno -tags $(TAGS) -ldflags=$(LD_FLAGS_DEV) $(PWD)/$(KYVERNO_PATH)/main.go
@docker build -f $(PWD)/$(KYVERNO_PATH)/localDockerfile -t $(REPO)/$(KYVERNO_IMAGE):$(IMAGE_TAG_DEV) $(PWD)/$(KYVERNO_PATH)
@docker build -f $(PWD)/$(KYVERNO_PATH)/localDockerfile -t $(REPO)/$(KYVERNO_IMAGE):$(IMAGE_TAG_DEV) -t $(REPO)/$(KYVERNO_IMAGE):latest $(PWD)/$(KYVERNO_PATH)
@docker tag $(REPO)/$(KYVERNO_IMAGE):$(IMAGE_TAG_DEV) $(REPO)/$(KYVERNO_IMAGE):$(IMAGE_TAG_LATEST_DEV)-latest
docker-build-kyverno-amd64:

View file

@ -168,6 +168,24 @@ type ContextEntry struct {
// APICall defines an HTTP request to the Kubernetes API server. The JSON
// data retrieved is stored in the context.
APICall *APICall `json:"apiCall,omitempty" yaml:"apiCall,omitempty"`
// ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image
// details.
ImageRegistry *ImageRegistry `json:"imageRegistry,omitempty" yaml:"imageRegistry,omitempty"`
}
// ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image
// details.
type ImageRegistry struct {
// Reference is image reference to a container image in the registry.
// Example: ghcr.io/kyverno/kyverno:latest
Reference string `json:"reference" yaml:"reference"`
// JMESPath is an optional JSON Match Expression that can be used to
// transform the ImageData struct returned as a result of processing
// the image reference.
// +optional
JMESPath string `json:"jmesPath,omitempty" yaml:"jmesPath,omitempty"`
}
// ConfigMapReference refers to a ConfigMap

View file

@ -2,8 +2,6 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@ -17,20 +15,19 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
// Code generated by controller-gen. DO NOT EDIT.
package v1
import (
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *APICall) DeepCopyInto(out *APICall) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APICall.
@ -46,7 +43,6 @@ func (in *APICall) DeepCopy() *APICall {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AdmissionRequestInfoObject) DeepCopyInto(out *AdmissionRequestInfoObject) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdmissionRequestInfoObject.
@ -76,7 +72,6 @@ func (in *AnyAllConditions) DeepCopyInto(out *AnyAllConditions) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnyAllConditions.
@ -103,7 +98,6 @@ func (in *Attestation) DeepCopyInto(out *Attestation) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Attestation.
@ -119,7 +113,6 @@ func (in *Attestation) DeepCopy() *Attestation {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CloneFrom) DeepCopyInto(out *CloneFrom) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloneFrom.
@ -139,7 +132,6 @@ func (in *ClusterPolicy) DeepCopyInto(out *ClusterPolicy) {
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
out.Status = in.Status
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPolicy.
@ -172,7 +164,6 @@ func (in *ClusterPolicyList) DeepCopyInto(out *ClusterPolicyList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPolicyList.
@ -206,7 +197,6 @@ func (in *Condition) DeepCopy() *Condition {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConfigMapReference) DeepCopyInto(out *ConfigMapReference) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapReference.
@ -232,7 +222,11 @@ func (in *ContextEntry) DeepCopyInto(out *ContextEntry) {
*out = new(APICall)
**out = **in
}
return
if in.ImageRegistry != nil {
in, out := &in.ImageRegistry, &out.ImageRegistry
*out = new(ImageRegistry)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContextEntry.
@ -274,7 +268,6 @@ func (in *ExcludeResources) DeepCopyInto(out *ExcludeResources) {
}
in.UserInfo.DeepCopyInto(&out.UserInfo)
in.ResourceDescription.DeepCopyInto(&out.ResourceDescription)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExcludeResources.
@ -287,16 +280,6 @@ func (in *ExcludeResources) DeepCopy() *ExcludeResources {
return out
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ForEachValidation.
func (in *ForEachValidation) DeepCopy() *ForEachValidation {
if in == nil {
return nil
}
out := new(ForEachValidation)
in.DeepCopyInto(out)
return out
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ForEachMutation.
func (in *ForEachMutation) DeepCopy() *ForEachMutation {
if in == nil {
@ -307,6 +290,16 @@ func (in *ForEachMutation) DeepCopy() *ForEachMutation {
return out
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ForEachValidation.
func (in *ForEachValidation) DeepCopy() *ForEachValidation {
if in == nil {
return nil
}
out := new(ForEachValidation)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GenerateRequest) DeepCopyInto(out *GenerateRequest) {
*out = *in
@ -314,7 +307,6 @@ func (in *GenerateRequest) DeepCopyInto(out *GenerateRequest) {
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerateRequest.
@ -340,7 +332,6 @@ func (in *GenerateRequestContext) DeepCopyInto(out *GenerateRequestContext) {
*out = *in
in.UserRequestInfo.DeepCopyInto(&out.UserRequestInfo)
out.AdmissionRequestInfo = in.AdmissionRequestInfo
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerateRequestContext.
@ -365,7 +356,6 @@ func (in *GenerateRequestList) DeepCopyInto(out *GenerateRequestList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerateRequestList.
@ -391,7 +381,6 @@ func (in *GenerateRequestSpec) DeepCopyInto(out *GenerateRequestSpec) {
*out = *in
out.Resource = in.Resource
in.Context.DeepCopyInto(&out.Context)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerateRequestSpec.
@ -412,7 +401,6 @@ func (in *GenerateRequestStatus) DeepCopyInto(out *GenerateRequestStatus) {
*out = make([]ResourceSpec, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerateRequestStatus.
@ -435,9 +423,31 @@ func (in *Generation) DeepCopy() *Generation {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageRegistry) DeepCopyInto(out *ImageRegistry) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageRegistry.
func (in *ImageRegistry) DeepCopy() *ImageRegistry {
if in == nil {
return nil
}
out := new(ImageRegistry)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageVerification) DeepCopyInto(out *ImageVerification) {
*out = *in
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Attestations != nil {
in, out := &in.Attestations, &out.Attestations
*out = make([]*Attestation, len(*in))
@ -449,7 +459,6 @@ func (in *ImageVerification) DeepCopyInto(out *ImageVerification) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageVerification.
@ -481,7 +490,6 @@ func (in *MatchResources) DeepCopyInto(out *MatchResources) {
}
in.UserInfo.DeepCopyInto(&out.UserInfo)
in.ResourceDescription.DeepCopyInto(&out.ResourceDescription)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MatchResources.
@ -511,7 +519,6 @@ func (in *Policy) DeepCopyInto(out *Policy) {
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
out.Status = in.Status
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Policy.
@ -544,7 +551,6 @@ func (in *PolicyList) DeepCopyInto(out *PolicyList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyList.
@ -568,7 +574,6 @@ func (in *PolicyList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyStatus) DeepCopyInto(out *PolicyStatus) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyStatus.
@ -595,7 +600,6 @@ func (in *RequestInfo) DeepCopyInto(out *RequestInfo) {
copy(*out, *in)
}
in.AdmissionUserInfo.DeepCopyInto(&out.AdmissionUserInfo)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestInfo.
@ -643,7 +647,6 @@ func (in *ResourceDescription) DeepCopyInto(out *ResourceDescription) {
*out = new(metav1.LabelSelector)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceDescription.
@ -661,7 +664,6 @@ func (in *ResourceFilter) DeepCopyInto(out *ResourceFilter) {
*out = *in
in.UserInfo.DeepCopyInto(&out.UserInfo)
in.ResourceDescription.DeepCopyInto(&out.ResourceDescription)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceFilter.
@ -682,7 +684,6 @@ func (in ResourceFilters) DeepCopyInto(out *ResourceFilters) {
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
return
}
}
@ -699,7 +700,6 @@ func (in ResourceFilters) DeepCopy() ResourceFilters {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourceSpec) DeepCopyInto(out *ResourceSpec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceSpec.
@ -752,7 +752,6 @@ func (in *Spec) DeepCopyInto(out *Spec) {
*out = new(int32)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec.
@ -783,7 +782,6 @@ func (in *UserInfo) DeepCopyInto(out *UserInfo) {
*out = make([]rbacv1.Subject, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserInfo.
@ -809,7 +807,6 @@ func (in *Validation) DeepCopy() *Validation {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ViolatedRule) DeepCopyInto(out *ViolatedRule) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ViolatedRule.

View file

@ -2,8 +2,6 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@ -17,13 +15,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha1
import (
policyreportv1alpha1 "github.com/kyverno/kyverno/api/policyreport/v1alpha1"
v1 "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@ -55,7 +53,6 @@ func (in *ClusterReportChangeRequest) DeepCopyInto(out *ClusterReportChangeReque
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterReportChangeRequest.
@ -88,7 +85,6 @@ func (in *ClusterReportChangeRequestList) DeepCopyInto(out *ClusterReportChangeR
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterReportChangeRequestList.
@ -136,7 +132,6 @@ func (in *ReportChangeRequest) DeepCopyInto(out *ReportChangeRequest) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportChangeRequest.
@ -169,7 +164,6 @@ func (in *ReportChangeRequestList) DeepCopyInto(out *ReportChangeRequestList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportChangeRequestList.

View file

@ -2,8 +2,6 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@ -17,13 +15,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha2
import (
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
v1 "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@ -55,7 +53,6 @@ func (in *ClusterReportChangeRequest) DeepCopyInto(out *ClusterReportChangeReque
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterReportChangeRequest.
@ -88,7 +85,6 @@ func (in *ClusterReportChangeRequestList) DeepCopyInto(out *ClusterReportChangeR
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterReportChangeRequestList.
@ -136,7 +132,6 @@ func (in *ReportChangeRequest) DeepCopyInto(out *ReportChangeRequest) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportChangeRequest.
@ -169,7 +164,6 @@ func (in *ReportChangeRequestList) DeepCopyInto(out *ReportChangeRequestList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportChangeRequestList.

View file

@ -2,8 +2,6 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@ -17,12 +15,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha1
import (
v1 "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@ -54,7 +52,6 @@ func (in *ClusterPolicyReport) DeepCopyInto(out *ClusterPolicyReport) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPolicyReport.
@ -87,7 +84,6 @@ func (in *ClusterPolicyReportList) DeepCopyInto(out *ClusterPolicyReportList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPolicyReportList.
@ -135,7 +131,6 @@ func (in *PolicyReport) DeepCopyInto(out *PolicyReport) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReport.
@ -168,7 +163,6 @@ func (in *PolicyReportList) DeepCopyInto(out *PolicyReportList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReportList.
@ -215,7 +209,6 @@ func (in *PolicyReportResult) DeepCopyInto(out *PolicyReportResult) {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReportResult.
@ -231,7 +224,6 @@ func (in *PolicyReportResult) DeepCopy() *PolicyReportResult {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyReportSummary) DeepCopyInto(out *PolicyReportSummary) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReportSummary.

View file

@ -2,8 +2,6 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@ -17,12 +15,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha2
import (
v1 "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@ -54,7 +52,6 @@ func (in *ClusterPolicyReport) DeepCopyInto(out *ClusterPolicyReport) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPolicyReport.
@ -87,7 +84,6 @@ func (in *ClusterPolicyReportList) DeepCopyInto(out *ClusterPolicyReportList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPolicyReportList.
@ -135,7 +131,6 @@ func (in *PolicyReport) DeepCopyInto(out *PolicyReport) {
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReport.
@ -168,7 +163,6 @@ func (in *PolicyReportList) DeepCopyInto(out *PolicyReportList) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReportList.
@ -216,7 +210,6 @@ func (in *PolicyReportResult) DeepCopyInto(out *PolicyReportResult) {
}
}
out.Timestamp = in.Timestamp
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReportResult.
@ -232,7 +225,6 @@ func (in *PolicyReportResult) DeepCopy() *PolicyReportResult {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyReportSummary) DeepCopyInto(out *PolicyReportSummary) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyReportSummary.

View file

@ -98,6 +98,18 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression that can be used to transform the ImageData struct returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -922,6 +934,18 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression that can be used to transform the ImageData struct returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1073,6 +1097,18 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression that can be used to transform the ImageData struct returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1086,7 +1122,7 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
elementScope:
description: Use the list element as the scope for validation. Defaults to "true" if not specified. When set to "false", "request.object" is used as the validation scope within the foreach block to allow referencing other elements in the subtree.
description: ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. When set to "false", "request.object" is used as the validation scope within the foreach block to allow referencing other elements in the subtree.
type: boolean
list:
description: List specifies a JMESPath expression that results in one or more elements to which the validation logic is applied.
@ -1420,7 +1456,7 @@ spec:
description: key is the label key that the selector applies to.
type: string
operator:
description: operator represents a key's relationship to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
@ -1529,7 +1565,7 @@ spec:
description: key is the label key that the selector applies to.
type: string
operator:
description: operator represents a key's relationship to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
@ -1641,7 +1677,7 @@ spec:
description: key is the label key that the selector applies to.
type: string
operator:
description: operator represents a key's relationship to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
@ -1768,7 +1804,7 @@ spec:
description: key is the label key that the selector applies to.
type: string
operator:
description: operator represents a key's relationship to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
@ -2590,6 +2626,18 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression that can be used to transform the ImageData struct returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -3414,6 +3462,18 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression that can be used to transform the ImageData struct returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -3565,6 +3625,18 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression that can be used to transform the ImageData struct returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -3578,7 +3650,7 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
elementScope:
description: Use the list element as the scope for validation. Defaults to "true" if not specified. When set to "false", "request.object" is used as the validation scope within the foreach block to allow referencing other elements in the subtree.
description: ElementScope specifies whether to use the current list element as the scope for validation. Defaults to "true" if not specified. When set to "false", "request.object" is used as the validation scope within the foreach block to allow referencing other elements in the subtree.
type: boolean
list:
description: List specifies a JMESPath expression that results in one or more elements to which the validation logic is applied.
@ -3912,7 +3984,7 @@ spec:
description: key is the label key that the selector applies to.
type: string
operator:
description: operator represents a key's relationship to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
@ -4021,7 +4093,7 @@ spec:
description: key is the label key that the selector applies to.
type: string
operator:
description: operator represents a key's relationship to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
@ -4133,7 +4205,7 @@ spec:
description: key is the label key that the selector applies to.
type: string
operator:
description: operator represents a key's relationship to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
@ -4260,7 +4332,7 @@ spec:
description: key is the label key that the selector applies to.
type: string
operator:
description: operator represents a key's relationship to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.

View file

@ -34,6 +34,7 @@ import (
"github.com/kyverno/kyverno/pkg/policy"
"github.com/kyverno/kyverno/pkg/policycache"
"github.com/kyverno/kyverno/pkg/policyreport"
"github.com/kyverno/kyverno/pkg/registryclient"
"github.com/kyverno/kyverno/pkg/resourcecache"
"github.com/kyverno/kyverno/pkg/signal"
ktls "github.com/kyverno/kyverno/pkg/tls"
@ -176,7 +177,7 @@ func main() {
secrets := strings.Split(imagePullSecrets, ",")
if imagePullSecrets != "" && len(secrets) > 0 {
setupLog.Info("initializing registry credentials", "secrets", secrets)
if err := cosign.Initialize(kubeClient, config.KyvernoNamespace, "", secrets); err != nil {
if err := registryclient.Initialize(kubeClient, config.KyvernoNamespace, "", secrets); err != nil {
setupLog.Error(err, "failed to initialize image pull secrets")
os.Exit(1)
}

View file

@ -122,6 +122,22 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker
V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression
that can be used to transform the ImageData struct
returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container
image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1491,6 +1507,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1722,6 +1757,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1741,11 +1795,12 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
elementScope:
description: Use the list element as the scope for
validation. Defaults to "true" if not specified.
When set to "false", "request.object" is used as
the validation scope within the foreach block to
allow referencing other elements in the subtree.
description: ElementScope specifies whether to use
the current list element as the scope for validation.
Defaults to "true" if not specified. When set to
"false", "request.object" is used as the validation
scope within the foreach block to allow referencing
other elements in the subtree.
type: boolean
list:
description: List specifies a JMESPath expression

View file

@ -123,6 +123,22 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker
V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression
that can be used to transform the ImageData struct
returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container
image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1492,6 +1508,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1723,6 +1758,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1742,11 +1796,12 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
elementScope:
description: Use the list element as the scope for
validation. Defaults to "true" if not specified.
When set to "false", "request.object" is used as
the validation scope within the foreach block to
allow referencing other elements in the subtree.
description: ElementScope specifies whether to use
the current list element as the scope for validation.
Defaults to "true" if not specified. When set to
"false", "request.object" is used as the validation
scope within the foreach block to allow referencing
other elements in the subtree.
type: boolean
list:
description: List specifies a JMESPath expression

View file

@ -106,7 +106,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
@ -277,7 +277,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
@ -418,7 +418,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
@ -614,7 +614,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator

View file

@ -105,7 +105,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
@ -276,7 +276,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
@ -416,7 +416,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
@ -612,7 +612,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator

View file

@ -138,6 +138,22 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker
V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression
that can be used to transform the ImageData struct
returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container
image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1507,6 +1523,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1738,6 +1773,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1757,11 +1811,12 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
elementScope:
description: Use the list element as the scope for
validation. Defaults to "true" if not specified.
When set to "false", "request.object" is used as
the validation scope within the foreach block to
allow referencing other elements in the subtree.
description: ElementScope specifies whether to use
the current list element as the scope for validation.
Defaults to "true" if not specified. When set to
"false", "request.object" is used as the validation
scope within the foreach block to allow referencing
other elements in the subtree.
type: boolean
list:
description: List specifies a JMESPath expression
@ -2228,8 +2283,8 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
@ -2399,8 +2454,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn,
AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
@ -2541,8 +2595,8 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
@ -2737,8 +2791,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn,
AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
@ -3804,6 +3857,22 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker
V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression
that can be used to transform the ImageData struct
returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container
image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -5173,6 +5242,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -5404,6 +5492,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -5423,11 +5530,12 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
elementScope:
description: Use the list element as the scope for
validation. Defaults to "true" if not specified.
When set to "false", "request.object" is used as
the validation scope within the foreach block to
allow referencing other elements in the subtree.
description: ElementScope specifies whether to use
the current list element as the scope for validation.
Defaults to "true" if not specified. When set to
"false", "request.object" is used as the validation
scope within the foreach block to allow referencing
other elements in the subtree.
type: boolean
list:
description: List specifies a JMESPath expression
@ -5894,8 +6002,8 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
@ -6065,8 +6173,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn,
AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
@ -6206,8 +6313,8 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
@ -6402,8 +6509,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn,
AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator

View file

@ -127,6 +127,22 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker
V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression
that can be used to transform the ImageData struct
returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container
image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1496,6 +1512,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1727,6 +1762,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -1746,11 +1800,12 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
elementScope:
description: Use the list element as the scope for
validation. Defaults to "true" if not specified.
When set to "false", "request.object" is used as
the validation scope within the foreach block to
allow referencing other elements in the subtree.
description: ElementScope specifies whether to use
the current list element as the scope for validation.
Defaults to "true" if not specified. When set to
"false", "request.object" is used as the validation
scope within the foreach block to allow referencing
other elements in the subtree.
type: boolean
list:
description: List specifies a JMESPath expression
@ -2211,8 +2266,8 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
@ -2382,8 +2437,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn,
AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
@ -2524,8 +2578,8 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
@ -2720,8 +2774,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn,
AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
@ -3769,6 +3822,22 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests to an OCI/Docker
V2 registry to fetch image details.
properties:
jmesPath:
description: JMESPath is an optional JSON Match Expression
that can be used to transform the ImageData struct
returned as a result of processing the image reference.
type: string
reference:
description: 'Reference is image reference to a container
image in the registry. Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -5138,6 +5207,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -5369,6 +5457,25 @@ spec:
required:
- name
type: object
imageRegistry:
description: ImageRegistry defines requests
to an OCI/Docker V2 registry to fetch image
details.
properties:
jmesPath:
description: JMESPath is an optional JSON
Match Expression that can be used to transform
the ImageData struct returned as a result
of processing the image reference.
type: string
reference:
description: 'Reference is image reference
to a container image in the registry.
Example: ghcr.io/kyverno/kyverno:latest'
type: string
required:
- reference
type: object
name:
description: Name is the variable name.
type: string
@ -5388,11 +5495,12 @@ spec:
x-kubernetes-preserve-unknown-fields: true
type: object
elementScope:
description: Use the list element as the scope for
validation. Defaults to "true" if not specified.
When set to "false", "request.object" is used as
the validation scope within the foreach block to
allow referencing other elements in the subtree.
description: ElementScope specifies whether to use
the current list element as the scope for validation.
Defaults to "true" if not specified. When set to
"false", "request.object" is used as the validation
scope within the foreach block to allow referencing
other elements in the subtree.
type: boolean
list:
description: List specifies a JMESPath expression
@ -5853,8 +5961,8 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
@ -6024,8 +6132,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn,
AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator
@ -6165,8 +6272,8 @@ spec:
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn Exists and DoesNotExist.
to a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
@ -6361,8 +6468,7 @@ spec:
type: string
operator:
description: operator represents a key's relationship to a set
of values. Valid operators are In, AnyIn, AllIn, NotIn, AnyNotIn,
AllNotIn Exists and DoesNotExist.
of values. Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values. If the operator

View file

@ -13,8 +13,6 @@ import (
"github.com/sigstore/cosign/pkg/oci/remote"
"github.com/go-logr/logr"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/authn/k8schain"
"github.com/google/go-containerregistry/pkg/name"
"github.com/in-toto/in-toto-golang/in_toto"
"github.com/kyverno/kyverno/pkg/engine/common"
@ -27,50 +25,10 @@ import (
sigs "github.com/sigstore/cosign/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature/payload"
"k8s.io/client-go/kubernetes"
)
var (
// ImageSignatureRepository is an alternate signature repository
ImageSignatureRepository string
Secrets []string
kubeClient kubernetes.Interface
kyvernoNamespace string
kyvernoServiceAccount string
)
// Initialize loads the image pull secrets and initializes the default auth method for container registry API calls
func Initialize(client kubernetes.Interface, namespace, serviceAccount string, imagePullSecrets []string) error {
kubeClient = client
kyvernoNamespace = namespace
kyvernoServiceAccount = serviceAccount
Secrets = imagePullSecrets
var kc authn.Keychain
kcOpts := &k8schain.Options{
Namespace: namespace,
ServiceAccountName: serviceAccount,
ImagePullSecrets: imagePullSecrets,
}
kc, err := k8schain.New(context.Background(), client, *kcOpts)
if err != nil {
return errors.Wrap(err, "failed to initialize registry keychain")
}
authn.DefaultKeychain = kc
return nil
}
// UpdateKeychain reinitializes the image pull secrets and default auth method for container registry API calls
func UpdateKeychain() error {
var err = Initialize(kubeClient, kyvernoNamespace, kyvernoServiceAccount, Secrets)
if err != nil {
return err
}
return nil
}
// ImageSignatureRepository is an alternate signature repository
var ImageSignatureRepository string
type Options struct {
ImageRef string

View file

@ -7,6 +7,7 @@ import (
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/registryclient"
"github.com/pkg/errors"
"github.com/go-logr/logr"
@ -40,9 +41,9 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (resp *response.EngineRe
defer policyContext.JSONContext.Restore()
// update image registry secrets
if len(cosign.Secrets) > 0 {
logger.V(4).Info("updating registry credentials", "secrets", cosign.Secrets)
if err := cosign.UpdateKeychain(); err != nil {
if len(registryclient.Secrets) > 0 {
logger.V(4).Info("updating registry credentials", "secrets", registryclient.Secrets)
if err := registryclient.UpdateKeychain(); err != nil {
logger.Error(err, "failed to update image pull secrets")
}
}

View file

@ -7,12 +7,15 @@ import (
"strings"
"github.com/go-logr/logr"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
pkgcommon "github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/engine/context"
jmespath "github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/kyverno/store"
"github.com/kyverno/kyverno/pkg/registryclient"
"github.com/kyverno/kyverno/pkg/resourcecache"
"k8s.io/client-go/dynamic/dynamiclister"
)
@ -26,7 +29,7 @@ func LoadContext(logger logr.Logger, contextEntries []kyverno.ContextEntry, resC
policyName := ctx.Policy.Name
if store.GetMock() {
rule := store.GetPolicyRuleFromContext(policyName, ruleName)
if len(rule.Values) == 0 {
if rule == nil || len(rule.Values) == 0 {
return fmt.Errorf("No values found for policy %s rule %s", policyName, ruleName)
}
variables := rule.Values
@ -45,7 +48,6 @@ func LoadContext(logger logr.Logger, contextEntries []kyverno.ContextEntry, resC
return err
}
}
} else {
// get GVR Cache for "configmaps"
// can get cache for other resources if the informers are enabled in resource cache
@ -65,12 +67,107 @@ func LoadContext(logger logr.Logger, contextEntries []kyverno.ContextEntry, resC
if err := loadAPIData(logger, entry, ctx); err != nil {
return err
}
} else if entry.ImageRegistry != nil {
if err := loadImageData(logger, entry, ctx); err != nil {
return err
}
}
}
}
return nil
}
func loadImageData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyContext) error {
if len(registryclient.Secrets) > 0 {
if err := registryclient.UpdateKeychain(); err != nil {
return fmt.Errorf("unable to load image registry credentials, %w", err)
}
}
imageData, err := fetchImageData(logger, entry, ctx)
if err != nil {
return err
}
if err := ctx.JSONContext.AddJSONObject(imageData); err != nil {
return fmt.Errorf("failed to add resource data to context: contextEntry: %v, error: %v", entry, err)
}
return nil
}
func fetchImageData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyContext) (interface{}, error) {
ref, err := variables.SubstituteAll(logger, ctx.JSONContext, entry.ImageRegistry.Reference)
if err != nil {
return nil, fmt.Errorf("ailed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.Reference, err)
}
refString, ok := ref.(string)
if !ok {
return nil, fmt.Errorf("invalid image reference %s, image reference must be a string", ref)
}
path, err := variables.SubstituteAll(logger, ctx.JSONContext, entry.ImageRegistry.JMESPath)
if err != nil {
return nil, fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.JMESPath, err)
}
imageData, err := fetchImageDataMap(refString)
if err != nil {
return nil, err
}
if path != "" {
imageData, err = applyJMESPath(path.(string), imageData)
if err != nil {
return nil, fmt.Errorf("failed to apply JMESPath (%s) results to context entry %s, error: %v", entry.ImageRegistry.JMESPath, entry.Name, err)
}
}
return map[string]interface{}{
entry.Name: imageData,
}, nil
}
func fetchImageDataMap(ref string) (interface{}, error) {
parsedRef, err := name.ParseReference(ref)
if err != nil {
return nil, fmt.Errorf("failed to parse image reference: %s, error: %v", ref, err)
}
desc, err := remote.Get(parsedRef)
if err != nil {
return nil, fmt.Errorf("failed to fetch image reference: %s, error: %v", ref, err)
}
image, err := desc.Image()
if err != nil {
return nil, fmt.Errorf("failed to resolve image reference: %s, error: %v", ref, err)
}
manifest, err := image.Manifest()
if err != nil {
return nil, fmt.Errorf("failed to fetch manifest for image reference: %s, error: %v", ref, err)
}
config, err := image.ConfigFile()
if err != nil {
return nil, fmt.Errorf("failed to fetch config for image reference: %s, error: %v", ref, err)
}
data := map[string]interface{}{
"image": ref,
"resolvedImage": fmt.Sprintf("%s@%s", parsedRef.Context().Name(), desc.Digest.String()),
"registry": parsedRef.Context().RegistryStr(),
"repository": parsedRef.Context().RepositoryStr(),
"identifier": parsedRef.Identifier(),
"manifest": manifest,
"configData": config,
}
// we need to do the conversion from struct types to an interface type so that jmespath
// evaluation works correctly. go-jmespath cannot handle function calls like max/sum
// for types like integers for eg. the conversion to untyped allows the stdlib json
// to convert all the types to types that are compatible with jmespath.
jsonDoc, err := json.Marshal(data)
if err != nil {
return nil, err
}
var untyped interface{}
err = json.Unmarshal(jsonDoc, &untyped)
if err != nil {
return nil, err
}
return untyped, nil
}
func loadAPIData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyContext) error {
jsonData, err := fetchAPIData(logger, entry, ctx)
if err != nil {
@ -91,7 +188,7 @@ func loadAPIData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyCont
return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.APICall.JMESPath, err)
}
results, err := applyJMESPath(path.(string), jsonData)
results, err := applyJMESPathJSON(path.(string), jsonData)
if err != nil {
return err
}
@ -112,19 +209,22 @@ func loadAPIData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyCont
return nil
}
func applyJMESPath(jmesPath string, jsonData []byte) (interface{}, error) {
func applyJMESPath(jmesPath string, data interface{}) (interface{}, error) {
jp, err := jmespath.New(jmesPath)
if err != nil {
return nil, fmt.Errorf("failed to compile JMESPath: %s, error: %v", jmesPath, err)
}
return jp.Search(data)
}
func applyJMESPathJSON(jmesPath string, jsonData []byte) (interface{}, error) {
var data interface{}
err = json.Unmarshal(jsonData, &data)
err := json.Unmarshal(jsonData, &data)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal JSON: %s, error: %v", string(jsonData), err)
}
return jp.Search(data)
return applyJMESPath(jmesPath, data)
}
func fetchAPIData(log logr.Logger, entry kyverno.ContextEntry, ctx *PolicyContext) ([]byte, error) {

View file

@ -7,6 +7,7 @@ import (
"regexp"
"strings"
"github.com/distribution/distribution/reference"
"github.com/kyverno/kyverno/pkg/engine/context"
jsonpatch "github.com/evanphx/json-patch/v5"
@ -479,7 +480,7 @@ func getAllowedVariables(background bool) *regexp.Regexp {
func addContextVariables(entries []kyverno.ContextEntry, ctx *context.MockContext) {
for _, contextEntry := range entries {
if contextEntry.APICall != nil {
if contextEntry.APICall != nil || contextEntry.ImageRegistry != nil {
ctx.AddVariable(contextEntry.Name + "*")
}
@ -1094,8 +1095,10 @@ func validateRuleContext(rule kyverno.Rule) error {
err = validateConfigMap(entry)
} else if entry.APICall != nil {
err = validateAPICall(entry)
} else if entry.ImageRegistry != nil {
err = validateImageRegistry(entry)
} else {
return fmt.Errorf("a configMap or apiCall is required for context entries")
return fmt.Errorf("a configMap or apiCall or imageRegistry is required for context entries")
}
if err != nil {
@ -1123,6 +1126,10 @@ func validateConfigMap(entry kyverno.ContextEntry) error {
return fmt.Errorf("both configMap and apiCall are not allowed in a context entry")
}
if entry.ImageRegistry != nil {
return fmt.Errorf("both imageRegistry and configMap are not allowed in a context entry")
}
if entry.ConfigMap.Name == "" {
return fmt.Errorf("a name is required for configMap context entry")
}
@ -1143,6 +1150,10 @@ func validateAPICall(entry kyverno.ContextEntry) error {
return fmt.Errorf("both configMap and apiCall are not allowed in a context entry")
}
if entry.ImageRegistry != nil {
return fmt.Errorf("both imageRegistry and apiCall are not allowed in a context entry")
}
// Replace all variables to prevent validation failing on variable keys.
urlPath := variables.ReplaceAllVars(entry.APICall.URLPath, func(s string) string { return "kyvernoapicallvariable" })
@ -1165,6 +1176,47 @@ func validateAPICall(entry kyverno.ContextEntry) error {
return nil
}
func validateImageRegistry(entry kyverno.ContextEntry) error {
if entry.ImageRegistry == nil {
return fmt.Errorf("imageRegistry is empty")
}
if entry.ConfigMap != nil {
return fmt.Errorf("both configMap and imageRegistry are not allowed in a context entry")
}
if entry.APICall != nil {
return fmt.Errorf("both configMap and apiCall are not allowed in a context entry")
}
if entry.ImageRegistry.Reference == "" {
return fmt.Errorf("a ref is required for imageRegistry context entry")
}
// Replace all variables to prevent validation failing on variable keys.
ref := variables.ReplaceAllVars(entry.ImageRegistry.Reference, func(s string) string { return "kyvernoimageref" })
// it's no use validating a refernce that contains a variable
if !strings.Contains(ref, "kyvernoimageref") {
_, err := reference.Parse(ref)
if err != nil {
return errors.Wrapf(err, "bad image: %s", ref)
}
}
// If JMESPath contains variables, the validation will fail because it's not possible to infer which value
// will be inserted by the variable
// Skip validation if a variable is detected
jmesPath := variables.ReplaceAllVars(entry.ImageRegistry.JMESPath, func(s string) string { return "kyvernojmespathvariable" })
if !strings.Contains(jmesPath, "kyvernojmespathvariable") && entry.ImageRegistry.JMESPath != "" {
if _, err := jmespath.NewParser().Parse(entry.ImageRegistry.JMESPath); err != nil {
return fmt.Errorf("failed to parse JMESPath %s: %v", entry.ImageRegistry.JMESPath, err)
}
}
return nil
}
// validateResourceDescription checks if all necessary fields are present and have values. Also checks a Selector.
// field type is checked through openapi
// Returns error if

View file

@ -0,0 +1,50 @@
package registryclient
import (
"context"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/authn/k8schain"
"github.com/pkg/errors"
"k8s.io/client-go/kubernetes"
)
var (
Secrets []string
kubeClient kubernetes.Interface
kyvernoNamespace string
kyvernoServiceAccount string
)
// Initialize loads the image pull secrets and initializes the default auth method for container registry API calls
func Initialize(client kubernetes.Interface, namespace, serviceAccount string, imagePullSecrets []string) error {
kubeClient = client
kyvernoNamespace = namespace
kyvernoServiceAccount = serviceAccount
Secrets = imagePullSecrets
var kc authn.Keychain
kcOpts := &k8schain.Options{
Namespace: namespace,
ServiceAccountName: serviceAccount,
ImagePullSecrets: imagePullSecrets,
}
kc, err := k8schain.New(context.Background(), client, *kcOpts)
if err != nil {
return errors.Wrap(err, "failed to initialize registry keychain")
}
authn.DefaultKeychain = kc
return nil
}
// UpdateKeychain reinitializes the image pull secrets and default auth method for container registry API calls
func UpdateKeychain() error {
var err = Initialize(kubeClient, kyvernoNamespace, kyvernoServiceAccount, Secrets)
if err != nil {
return err
}
return nil
}

View file

@ -3,6 +3,7 @@ policies:
- policies.yaml
resources:
- resources.yaml
variables: variables.yaml
results:
- policy: validate-empty-dir-mountpath
rule: check-mount-paths
@ -38,4 +39,4 @@ results:
rule: check-resources
resource: test-pod-with-resources-multiple-ctnrs
kind: Pod
status: pass
status: pass

View file

@ -125,4 +125,4 @@ spec:
- name: cache-volume
emptyDir: {}
- name: gce
gcePersistentDisk: {}
gcePersistentDisk: {}

View file

@ -69,8 +69,6 @@ spec:
containers:
- name: nginx
image: nginx:1.12
---
apiVersion: v1
kind: Pod

View file

@ -0,0 +1,33 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: images
spec:
validationFailureAction: enforce
rules:
- name: only-allow-trusted-images
match:
resources:
kinds:
- Pod
preconditions:
- key: "{{request.operation}}"
operator: NotEquals
value: DELETE
validate:
message: "images with root user are not allowed"
foreach:
- list: "request.object.spec.containers"
context:
- name: imageData
imageRegistry:
reference: "{{ element.image }}"
deny:
conditions:
all:
- key: "{{ imageData.configData.config.User || ''}}"
operator: Equals
value: ""
- key: "{{ imageData.registry }}"
operator: NotEquals
value: "ghcr.io"

View file

@ -4,6 +4,7 @@ policies:
- cm-array-example.yaml
- cm-blk-scalar-example.yaml
- cm-globalval-example.yaml
- image-example.yaml
resources:
- resources.yaml
variables: variables.yaml
@ -48,3 +49,18 @@ results:
resource: test-global-prod
kind: Pod
result: fail
- policy: images
rule: only-allow-trusted-images
resource: test-pod-with-non-root-user-image
kind: Pod
status: pass
- policy: images
rule: only-allow-trusted-images
resource: test-pod-with-trusted-registry
kind: Pod
status: pass
- policy: images
rule: only-allow-trusted-images
resource: test-pod-with-non-trusted-registry
kind: Pod
status: fail

View file

@ -81,3 +81,30 @@ spec:
containers:
- name: nginx
image: nginx:1.12
---
apiVersion: v1
kind: Pod
metadata:
name: test-pod-with-non-root-user-image
spec:
containers:
- name: nginx
image: nginx:1.14.2
---
apiVersion: v1
kind: Pod
metadata:
name: test-pod-with-trusted-registry
spec:
containers:
- name: kyverno
image: ghcr.io/kyverno/kyverno
---
apiVersion: v1
kind: Pod
metadata:
name: test-pod-with-non-trusted-registry
spec:
containers:
- name: not-kyverno
image: gcr.io/not-kyverno/kyverno

View file

@ -42,5 +42,26 @@ policies:
- name: test-global-prod
values:
request.mode: prod
- name: images
rules:
- name: only-allow-trusted-images
values:
request.operation: CREATE
resources:
- name: test-pod-with-non-root-user-image
values:
imageData.registry: "index.docker.io"
imageData.configData.config.User: "nginx"
element.name: "nginx"
- name: test-pod-with-trusted-registry
values:
element.name: "kyverno"
imageData.registry: "ghcr.io"
imageData.configData.config.User: ""
- name: test-pod-with-non-trusted-registry
values:
element.name: "not-kyverno"
imageData.registry: "gcr.io"
imageData.configData.config.User: ""
globalValues:
request.mode: dev

View file

@ -71,7 +71,7 @@ var ValidateTests = []struct {
PolicyName: "check-image-pull-secret",
PolicyRaw: kyverno_global_anchor_validate_policy,
ResourceName: "pod-with-nginx-allowed-registory",
ResourceNamespace: "",
ResourceNamespace: "test-validate",
ResourceGVR: podGVR,
ResourceRaw: kyverno_global_anchor_validate_resource_1,
MustSucceed: true,
@ -82,9 +82,53 @@ var ValidateTests = []struct {
PolicyName: "check-image-pull-secret",
PolicyRaw: kyverno_global_anchor_validate_policy,
ResourceName: "pod-with-nginx-disallowed-registory",
ResourceNamespace: "",
ResourceNamespace: "test-validate",
ResourceGVR: podGVR,
ResourceRaw: kyverno_global_anchor_validate_resource_2,
MustSucceed: false,
},
{
// Case for image validation
TestDescription: "checks that images are trustable",
PolicyName: "check-trustable-images",
PolicyRaw: kyverno_trustable_image_policy,
ResourceName: "pod-with-trusted-registry",
ResourceNamespace: "test-validate",
ResourceGVR: podGVR,
ResourceRaw: kyverno_trusted_image_pod,
MustSucceed: true,
},
{
// Case for image validation
TestDescription: "checks that images are trustable",
PolicyName: "check-trustable-images",
PolicyRaw: kyverno_trustable_image_policy,
ResourceName: "pod-with-root-user",
ResourceNamespace: "test-validate",
ResourceGVR: podGVR,
ResourceRaw: kyverno_pod_with_root_user,
MustSucceed: false,
},
{
// Case for small image validation
TestDescription: "checks that images are small",
PolicyName: "check-small-images",
PolicyRaw: kyverno_small_image_policy,
ResourceName: "pod-with-small-image",
ResourceNamespace: "test-validate",
ResourceGVR: podGVR,
ResourceRaw: kyverno_pod_with_small_image,
MustSucceed: true,
},
{
// Case for small image validation
TestDescription: "checks that images are small",
PolicyName: "check-large-images",
PolicyRaw: kyverno_small_image_policy,
ResourceName: "pod-with-large-image",
ResourceNamespace: "test-validate",
ResourceGVR: podGVR,
ResourceRaw: kyverno_pod_with_large_image,
MustSucceed: false,
},
}

View file

@ -632,6 +632,43 @@ spec:
- CAP_SOMETHING
`)
var kyverno_trustable_image_policy = []byte(`
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: check-trustable-images
spec:
validationFailureAction: enforce
rules:
- name: only-allow-trusted-images
match:
resources:
kinds:
- Pod
preconditions:
- key: "{{request.operation}}"
operator: NotEquals
value: DELETE
validate:
message: "images with root user are not allowed"
foreach:
- list: "request.object.spec.containers"
context:
- name: imageData
imageRegistry:
reference: "{{ element.image }}"
jmesPath: "{user: configData.config.User || '', registry: registry}"
deny:
conditions:
all:
- key: "{{ imageData.user }}"
operator: Equals
value: ""
- key: "{{ imageData.registry }}"
operator: NotEquals
value: "ghcr.io"
`)
var kyverno_global_anchor_validate_policy = []byte(`
apiVersion: kyverno.io/v1
kind: ClusterPolicy
@ -680,3 +717,82 @@ spec:
imagePullSecrets:
- name: other-registory-secret
`)
var kyverno_trusted_image_pod = []byte(`
apiVersion: v1
kind: Pod
metadata:
name: pod-with-trusted-registry
spec:
containers:
- name: kyverno
image: ghcr.io/kyverno/kyverno:latest
`)
var kyverno_pod_with_root_user = []byte(`
apiVersion: v1
kind: Pod
metadata:
name: pod-with-root-user
spec:
containers:
- name: ubuntu
image: ubuntu:bionic
`)
var kyverno_small_image_policy = []byte(`
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: images
spec:
validationFailureAction: enforce
rules:
- name: only-allow-small-images
match:
resources:
kinds:
- Pod
preconditions:
- key: "{{request.operation}}"
operator: NotEquals
value: DELETE
validate:
message: "images with size greater than 2Gi not allowed"
foreach:
- list: "request.object.spec.containers"
context:
- name: imageSize
imageRegistry:
reference: "{{ element.image }}"
# Note that we need to use "to_string" here to allow kyverno to treat it like a resource quantity of type memory
# the total size of an image as calculated by docker is the total sum of its layer sizes
jmesPath: "to_string(sum(manifest.layers[*].size))"
deny:
conditions:
- key: "2Gi"
operator: LessThan
value: "{{imageSize}}"
`)
var kyverno_pod_with_small_image = []byte(`
apiVersion: v1
kind: Pod
metadata:
name: small-image
spec:
containers:
- name: small-image
image: busybox:latest
`)
var kyverno_pod_with_large_image = []byte(`
apiVersion: v1
kind: Pod
metadata:
name: large-image
spec:
containers:
- name: large-image
image: nvidia/cuda:11.6.0-devel-ubi8
`)