From 7dcc5210ff204a027d1e04dcec9ff13c54fcbe86 Mon Sep 17 00:00:00 2001 From: Vladimir DOMBROVSKI Date: Fri, 18 Oct 2024 16:04:04 +0200 Subject: [PATCH] feat: Add accept-images parameter to whitelist images --- api/core/v1/pod_webhook.go | 10 +++++ api/core/v1/pod_webhook_test.go | 39 +++++++++++++++++++ cmd/cache/main.go | 3 ++ .../templates/controller-deployment.yaml | 3 ++ helm/kube-image-keeper/values.yaml | 2 + 5 files changed, 57 insertions(+) diff --git a/api/core/v1/pod_webhook.go b/api/core/v1/pod_webhook.go index 4a861f6f..71bb68b3 100644 --- a/api/core/v1/pod_webhook.go +++ b/api/core/v1/pod_webhook.go @@ -35,6 +35,7 @@ var ( type ImageRewriter struct { Client client.Client IgnoreImages []*regexp.Regexp + AcceptImages []*regexp.Regexp IgnorePullPolicyAlways bool ProxyPort int Decoder *admission.Decoder @@ -169,6 +170,15 @@ func (a *ImageRewriter) isImageRewritable(container *corev1.Container) error { } } + if len(a.AcceptImages) > 0 { + for _, r := range a.AcceptImages { + if r.MatchString(container.Image) { + return nil + } + } + return fmt.Errorf("image does not match any existing rules (--accept-images not empty)") + } + return nil } diff --git a/api/core/v1/pod_webhook_test.go b/api/core/v1/pod_webhook_test.go index a058d18b..7509487c 100644 --- a/api/core/v1/pod_webhook_test.go +++ b/api/core/v1/pod_webhook_test.go @@ -115,6 +115,45 @@ func TestRewriteImagesWithIgnore(t *testing.T) { }) } +func TestRewriteImagesWithAccept(t *testing.T) { + podStub := *podStub.DeepCopy() + + g := NewWithT(t) + t.Run("Rewrite image", func(t *testing.T) { + ir := ImageRewriter{ + ProxyPort: 4242, + AcceptImages: []*regexp.Regexp{ + regexp.MustCompile("185.145.250.247\\:30042"), + }, + } + ir.RewriteImages(&podStub, true) + + rewrittenInitContainers := []corev1.Container{ + {Name: "a", Image: "original-init"}, + } + + rewrittenContainers := []corev1.Container{ + {Name: "b", Image: "original"}, + {Name: "c", Image: "localhost:1313/original-2"}, + {Name: "d", Image: "localhost:4242/185.145.250.247-30042/alpine"}, + {Name: "e", Image: "localhost:4242/185.145.250.247-30042/alpine:latest"}, + {Name: "f", Image: "invalid:image:8080"}, + } + + g.Expect(podStub.Spec.InitContainers).To(Equal(rewrittenInitContainers)) + g.Expect(podStub.Spec.Containers).To(Equal(rewrittenContainers)) + + g.Expect(podStub.Labels[core.LabelManagedName]).To(Equal("true")) + + g.Expect(podStub.Annotations[registry.ContainerAnnotationKey("a", true)]).To(Equal("")) + g.Expect(podStub.Annotations[registry.ContainerAnnotationKey("b", false)]).To(Equal("")) + g.Expect(podStub.Annotations[registry.ContainerAnnotationKey("c", false)]).To(Equal("")) + g.Expect(podStub.Annotations[registry.ContainerAnnotationKey("d", false)]).To(Equal("185.145.250.247:30042/alpine")) + g.Expect(podStub.Annotations[registry.ContainerAnnotationKey("e", false)]).To(Equal("185.145.250.247:30042/alpine:latest")) + g.Expect(podStub.Annotations[registry.ContainerAnnotationKey("f", false)]).To(Equal("")) + }) +} + func Test_isImageRewritable(t *testing.T) { emptyRegexps := []*regexp.Regexp{} someRegexps := []*regexp.Regexp{ diff --git a/cmd/cache/main.go b/cmd/cache/main.go index 2140bef6..2798398b 100644 --- a/cmd/cache/main.go +++ b/cmd/cache/main.go @@ -39,6 +39,7 @@ func main() { var expiryDelay uint var proxyPort int var ignoreImages internal.RegexpArrayFlags + var acceptImages internal.RegexpArrayFlags var ignorePullPolicyAlways bool var architectures internal.ArrayFlags var maxConcurrentCachedImageReconciles int @@ -52,6 +53,7 @@ func main() { flag.UintVar(&expiryDelay, "expiry-delay", 30, "The delay in days before deleting an unused CachedImage.") flag.IntVar(&proxyPort, "proxy-port", 8082, "The port on which the registry proxy accepts connections on each host.") flag.Var(&ignoreImages, "ignore-images", "Regex that represents images to be excluded (this flag can be used multiple times).") + flag.Var(&acceptImages, "accept-images", "Regex that represents images to be whitelisted (this flag can be used multiple times).") flag.BoolVar(&ignorePullPolicyAlways, "ignore-pull-policy-always", true, "Ignore containers that are configured with imagePullPolicy: Always") flag.Var(&architectures, "arch", "Architecture of image to put in cache (this flag can be used multiple times).") flag.StringVar(®istry.Endpoint, "registry-endpoint", "kube-image-keeper-registry:5000", "The address of the registry where cached images are stored.") @@ -111,6 +113,7 @@ func main() { imageRewriter := kuikenixiov1.ImageRewriter{ Client: mgr.GetClient(), IgnoreImages: ignoreImages, + AcceptImages: acceptImages, IgnorePullPolicyAlways: ignorePullPolicyAlways, ProxyPort: proxyPort, Decoder: admission.NewDecoder(mgr.GetScheme()), diff --git a/helm/kube-image-keeper/templates/controller-deployment.yaml b/helm/kube-image-keeper/templates/controller-deployment.yaml index 7df329e2..9c2358ca 100644 --- a/helm/kube-image-keeper/templates/controller-deployment.yaml +++ b/helm/kube-image-keeper/templates/controller-deployment.yaml @@ -48,6 +48,9 @@ spec: {{- range .Values.controllers.webhook.ignoredImages }} - -ignore-images={{- . }} {{- end }} + {{- range .Values.controllers.webhook.acceptedImages }} + - -accept-images={{- . }} + {{- end }} {{- range .Values.architectures }} - -arch={{- . }} {{- end }} diff --git a/helm/kube-image-keeper/values.yaml b/helm/kube-image-keeper/values.yaml index a3da0ed6..e24ad544 100644 --- a/helm/kube-image-keeper/values.yaml +++ b/helm/kube-image-keeper/values.yaml @@ -78,6 +78,8 @@ controllers: ignoredNamespaces: [] # -- Don't enable image caching if the image match the following regexes ignoredImages: [] + # -- Enable image caching only if the image matches the following regexes (only applies when not empty) + acceptedImages: [] # -- Don't enable image caching if the image is configured with imagePullPolicy: Always ignorePullPolicyAlways: true # -- If true, create the issuer used to issue the webhook certificate