mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
fix ns selector (#6887)
* fix ns selector Signed-off-by: Jim Bugwadia <jim@nirmata.com> * remove debug Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add kuttl tests Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix tests Signed-off-by: Jim Bugwadia <jim@nirmata.com> --------- Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
2948adba57
commit
a054f7c957
14 changed files with 140 additions and 8 deletions
|
@ -122,7 +122,7 @@ func doesResourceMatchConditionBlock(
|
||||||
errs = append(errs, fmt.Errorf("failed to parse namespace selector: %v", err))
|
errs = append(errs, fmt.Errorf("failed to parse namespace selector: %v", err))
|
||||||
} else {
|
} else {
|
||||||
if !hasPassed {
|
if !hasPassed {
|
||||||
errs = append(errs, fmt.Errorf("namespace selector does not match"))
|
errs = append(errs, fmt.Errorf("namespace selector does not match labels"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,7 @@ func (gen *generator) syncHandler(key Info) error {
|
||||||
eventType = corev1.EventTypeNormal
|
eventType = corev1.EventTypeNormal
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.V(2).Info("creating the event", "source", key.Source, "type", eventType, "resource", key.Resource())
|
logger.V(3).Info("creating the event", "source", key.Source, "type", eventType, "resource", key.Resource())
|
||||||
// based on the source of event generation, use different event recorders
|
// based on the source of event generation, use different event recorders
|
||||||
switch key.Source {
|
switch key.Source {
|
||||||
case AdmissionController:
|
case AdmissionController:
|
||||||
|
|
|
@ -51,8 +51,8 @@ func (i *ImageInfo) ReferenceWithTag() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetImageInfo(image string, cfg config.Configuration) (*ImageInfo, error) {
|
func GetImageInfo(image string, cfg config.Configuration) (*ImageInfo, error) {
|
||||||
logger.V(2).Info(
|
logger.V(3).Info(
|
||||||
"Getting the image info",
|
"getting the image info",
|
||||||
"image", image,
|
"image", image,
|
||||||
"defaultRegistry", config.Configuration.GetDefaultRegistry(cfg),
|
"defaultRegistry", config.Configuration.GetDefaultRegistry(cfg),
|
||||||
"enableDefaultRegistryMutation", config.Configuration.GetEnableDefaultRegistryMutation(cfg),
|
"enableDefaultRegistryMutation", config.Configuration.GetEnableDefaultRegistryMutation(cfg),
|
||||||
|
@ -86,8 +86,8 @@ func GetImageInfo(image string, cfg config.Configuration) (*ImageInfo, error) {
|
||||||
registry = ""
|
registry = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.V(2).Info(
|
logger.V(3).Info(
|
||||||
"Getting the image info",
|
"getting the image info",
|
||||||
"image", image,
|
"image", image,
|
||||||
"registry", registry,
|
"registry", registry,
|
||||||
"name", name,
|
"name", name,
|
||||||
|
|
|
@ -176,7 +176,7 @@ func (h *resourceHandlers) Mutate(ctx context.Context, logger logr.Logger, reque
|
||||||
logger.Error(err, "failed to build policy context")
|
logger.Error(err, "failed to build policy context")
|
||||||
return admissionutils.Response(request.UID, err)
|
return admissionutils.Response(request.UID, err)
|
||||||
}
|
}
|
||||||
ivh := imageverification.NewImageVerificationHandler(logger, h.kyvernoClient, h.engine, h.eventGen, h.admissionReports, h.configuration)
|
ivh := imageverification.NewImageVerificationHandler(logger, h.kyvernoClient, h.engine, h.eventGen, h.admissionReports, h.configuration, h.nsLister)
|
||||||
imagePatches, imageVerifyWarnings, err := ivh.Handle(ctx, newRequest, verifyImagesPolicies, policyContext)
|
imagePatches, imageVerifyWarnings, err := ivh.Handle(ctx, newRequest, verifyImagesPolicies, policyContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "image verification failed")
|
logger.Error(err, "image verification failed")
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/kyverno/kyverno/pkg/event"
|
"github.com/kyverno/kyverno/pkg/event"
|
||||||
"github.com/kyverno/kyverno/pkg/tracing"
|
"github.com/kyverno/kyverno/pkg/tracing"
|
||||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||||
|
engineutils "github.com/kyverno/kyverno/pkg/utils/engine"
|
||||||
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
||||||
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
||||||
webhookutils "github.com/kyverno/kyverno/pkg/webhooks/utils"
|
webhookutils "github.com/kyverno/kyverno/pkg/webhooks/utils"
|
||||||
|
@ -21,6 +22,7 @@ import (
|
||||||
admissionv1 "k8s.io/api/admission/v1"
|
admissionv1 "k8s.io/api/admission/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ImageVerificationHandler interface {
|
type ImageVerificationHandler interface {
|
||||||
|
@ -34,6 +36,7 @@ type imageVerificationHandler struct {
|
||||||
eventGen event.Interface
|
eventGen event.Interface
|
||||||
admissionReports bool
|
admissionReports bool
|
||||||
cfg config.Configuration
|
cfg config.Configuration
|
||||||
|
nsLister corev1listers.NamespaceLister
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewImageVerificationHandler(
|
func NewImageVerificationHandler(
|
||||||
|
@ -43,6 +46,7 @@ func NewImageVerificationHandler(
|
||||||
eventGen event.Interface,
|
eventGen event.Interface,
|
||||||
admissionReports bool,
|
admissionReports bool,
|
||||||
cfg config.Configuration,
|
cfg config.Configuration,
|
||||||
|
nsLister corev1listers.NamespaceLister,
|
||||||
) ImageVerificationHandler {
|
) ImageVerificationHandler {
|
||||||
return &imageVerificationHandler{
|
return &imageVerificationHandler{
|
||||||
kyvernoClient: kyvernoClient,
|
kyvernoClient: kyvernoClient,
|
||||||
|
@ -51,6 +55,7 @@ func NewImageVerificationHandler(
|
||||||
eventGen: eventGen,
|
eventGen: eventGen,
|
||||||
admissionReports: admissionReports,
|
admissionReports: admissionReports,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
|
nsLister: nsLister,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,24 +86,34 @@ func (h *imageVerificationHandler) handleVerifyImages(
|
||||||
var engineResponses []engineapi.EngineResponse
|
var engineResponses []engineapi.EngineResponse
|
||||||
var patches [][]byte
|
var patches [][]byte
|
||||||
verifiedImageData := engineapi.ImageVerificationMetadata{}
|
verifiedImageData := engineapi.ImageVerificationMetadata{}
|
||||||
|
failurePolicy := kyvernov1.Ignore
|
||||||
|
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
tracing.ChildSpan(
|
tracing.ChildSpan(
|
||||||
ctx,
|
ctx,
|
||||||
"",
|
"",
|
||||||
fmt.Sprintf("POLICY %s/%s", policy.GetNamespace(), policy.GetName()),
|
fmt.Sprintf("POLICY %s/%s", policy.GetNamespace(), policy.GetName()),
|
||||||
func(ctx context.Context, span trace.Span) {
|
func(ctx context.Context, span trace.Span) {
|
||||||
|
if policy.GetSpec().GetFailurePolicy() == kyvernov1.Fail {
|
||||||
|
failurePolicy = kyvernov1.Fail
|
||||||
|
}
|
||||||
|
|
||||||
policyContext := policyContext.WithPolicy(policy)
|
policyContext := policyContext.WithPolicy(policy)
|
||||||
|
if request.Kind.Kind != "Namespace" && request.Namespace != "" {
|
||||||
|
policyContext = policyContext.WithNamespaceLabels(engineutils.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, h.log))
|
||||||
|
}
|
||||||
|
|
||||||
resp, ivm := h.engine.VerifyAndPatchImages(ctx, policyContext)
|
resp, ivm := h.engine.VerifyAndPatchImages(ctx, policyContext)
|
||||||
if !resp.IsEmpty() {
|
if !resp.IsEmpty() {
|
||||||
engineResponses = append(engineResponses, resp)
|
engineResponses = append(engineResponses, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
patches = append(patches, resp.GetPatches()...)
|
patches = append(patches, resp.GetPatches()...)
|
||||||
verifiedImageData.Merge(ivm)
|
verifiedImageData.Merge(ivm)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
failurePolicy := policies[0].GetSpec().GetFailurePolicy()
|
|
||||||
blocked := webhookutils.BlockRequest(engineResponses, failurePolicy, logger)
|
blocked := webhookutils.BlockRequest(engineResponses, failurePolicy, logger)
|
||||||
events := webhookutils.GenerateEvents(engineResponses, blocked)
|
events := webhookutils.GenerateEvents(engineResponses, blocked)
|
||||||
h.eventGen.Add(events...)
|
h.eventGen.Add(events...)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: keyed-basic-ns-selector-policy
|
||||||
|
status:
|
||||||
|
conditions:
|
||||||
|
- reason: Succeeded
|
||||||
|
status: "True"
|
||||||
|
type: Ready
|
|
@ -0,0 +1,47 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: test-verify-images
|
||||||
|
labels:
|
||||||
|
signed: "true"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: test-verify-images-unprotected
|
||||||
|
labels:
|
||||||
|
signed: "false"
|
||||||
|
---
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: keyed-basic-ns-selector-policy
|
||||||
|
spec:
|
||||||
|
validationFailureAction: Enforce
|
||||||
|
background: false
|
||||||
|
webhookTimeoutSeconds: 30
|
||||||
|
failurePolicy: Fail
|
||||||
|
rules:
|
||||||
|
- name: keyed-basic-rule
|
||||||
|
match:
|
||||||
|
all:
|
||||||
|
- resources:
|
||||||
|
kinds:
|
||||||
|
- Pod
|
||||||
|
namespaceSelector:
|
||||||
|
matchExpressions:
|
||||||
|
- key: signed
|
||||||
|
operator: In
|
||||||
|
values:
|
||||||
|
- "true"
|
||||||
|
verifyImages:
|
||||||
|
- imageReferences:
|
||||||
|
- "ghcr.io/kyverno/test-verify-image:*"
|
||||||
|
attestors:
|
||||||
|
- entries:
|
||||||
|
- keys:
|
||||||
|
publicKeys: |-
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM
|
||||||
|
5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==
|
||||||
|
-----END PUBLIC KEY-----
|
|
@ -0,0 +1,5 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test-signed-pod
|
||||||
|
namespace: test-verify-images
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test-signed-pod
|
||||||
|
namespace: test-verify-images
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: ghcr.io/kyverno/test-verify-image:signed
|
||||||
|
name: test-secret
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: kuttl.dev/v1beta1
|
||||||
|
kind: TestStep
|
||||||
|
apply:
|
||||||
|
- file: pod-unsigned.yaml
|
||||||
|
shouldFail: true
|
||||||
|
- file: pod-signed.yaml
|
||||||
|
shouldFail: false
|
||||||
|
- file: pod-unprotected-ns.yaml
|
||||||
|
shouldFail: false
|
|
@ -0,0 +1,11 @@
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This test performs a simple verification of an image using a public key specified directly in the policy.
|
||||||
|
|
||||||
|
## Expected Behavior
|
||||||
|
|
||||||
|
Pod creation should pass as the image has been signed by the public key specified in the policy.
|
||||||
|
|
||||||
|
## Reference Issue(s)
|
||||||
|
|
||||||
|
N/A
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test-signed-pod2
|
||||||
|
namespace: test-verify-images
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: ghcr.io/kyverno/test-verify-image:signed
|
||||||
|
name: test-signed2
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test-unsigned-pod
|
||||||
|
namespace: test-verify-images-unprotected
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: ghcr.io/kyverno/test-verify-image:unsigned
|
||||||
|
name: test-unsigned
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: test-unsigned-pod
|
||||||
|
namespace: test-verify-images
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: ghcr.io/kyverno/test-verify-image:unsigned
|
||||||
|
name: test-unsigned
|
Loading…
Add table
Reference in a new issue