1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

adds ephemeralContainers to the image variable (#2662)

* adds ephemeralContainers to the image variable

Signed-off-by: Mritunjay Sharma <mritunjaysharma394@gmail.com>

* fixes unit tests

Signed-off-by: Mritunjay Sharma <mritunjaysharma394@gmail.com>

Co-authored-by: shuting <shutting06@gmail.com>
This commit is contained in:
Mritunjay Kumar Sharma 2022-01-07 14:25:52 +05:30 committed by GitHub
parent 68c8790139
commit 15495a472e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 26 deletions

View file

@ -277,12 +277,12 @@ func (ctx *Context) AddNamespace(namespace string) error {
}
func (ctx *Context) AddImageInfo(resource *unstructured.Unstructured) error {
initContainersImgs, containersImgs := extractImageInfo(resource, ctx.log)
if len(initContainersImgs) == 0 && len(containersImgs) == 0 {
initContainersImgs, containersImgs, ephemeralContainersImgs := extractImageInfo(resource, ctx.log)
if len(initContainersImgs) == 0 && len(containersImgs) == 0 && len(ephemeralContainersImgs) == 0 {
return nil
}
images := newImages(initContainersImgs, containersImgs)
images := newImages(initContainersImgs, containersImgs, ephemeralContainersImgs)
if images == nil {
return nil
}

View file

@ -48,11 +48,12 @@ type ContainerImage struct {
}
type Images struct {
InitContainers map[string]*ImageInfo `json:"initContainers,omitempty"`
Containers map[string]*ImageInfo `json:"containers"`
InitContainers map[string]*ImageInfo `json:"initContainers,omitempty"`
Containers map[string]*ImageInfo `json:"containers"`
EphemeralContainers map[string]*ImageInfo `json:"ephemeralContainers"`
}
func newImages(initContainersImgs, containersImgs []*ContainerImage) *Images {
func newImages(initContainersImgs, containersImgs, ephemeralContainersImgs []*ContainerImage) *Images {
initContainers := make(map[string]*ImageInfo)
for _, resource := range initContainersImgs {
initContainers[resource.Name] = resource.Image
@ -63,23 +64,31 @@ func newImages(initContainersImgs, containersImgs []*ContainerImage) *Images {
containers[resource.Name] = resource.Image
}
ephemeralContainers := make(map[string]*ImageInfo)
for _, resource := range ephemeralContainersImgs {
ephemeralContainers[resource.Name] = resource.Image
}
return &Images{
InitContainers: initContainers,
Containers: containers,
InitContainers: initContainers,
Containers: containers,
EphemeralContainers: ephemeralContainers,
}
}
func extractImageInfo(resource *unstructured.Unstructured, log logr.Logger) (initContainersImgs, containersImgs []*ContainerImage) {
func extractImageInfo(resource *unstructured.Unstructured, log logr.Logger) (initContainersImgs, containersImgs, ephemeralContainersImgs []*ContainerImage) {
logger := log.WithName("extractImageInfo").WithValues("kind", resource.GetKind(), "ns", resource.GetNamespace(), "name", resource.GetName())
for _, tag := range []string{"initContainers", "containers"} {
for _, tag := range []string{"initContainers", "containers", "ephemeralContainers"} {
switch resource.GetKind() {
case "Pod":
if containers, ok, _ := unstructured.NestedSlice(resource.UnstructuredContent(), "spec", tag); ok {
if tag == "initContainers" {
initContainersImgs = extractImageInfos(containers, initContainersImgs, "/spec/initContainers", logger)
} else {
} else if tag == "containers" {
containersImgs = extractImageInfos(containers, containersImgs, "/spec/containers", logger)
} else {
ephemeralContainersImgs = extractImageInfos(containers, ephemeralContainersImgs, "/spec/ephemeralContainers", logger)
}
}
@ -87,8 +96,10 @@ func extractImageInfo(resource *unstructured.Unstructured, log logr.Logger) (ini
if containers, ok, _ := unstructured.NestedSlice(resource.UnstructuredContent(), "spec", "jobTemplate", "spec", "template", "spec", tag); ok {
if tag == "initContainers" {
initContainersImgs = extractImageInfos(containers, initContainersImgs, "/spec/jobTemplate/spec/template/spec/initContainers", logger)
} else {
} else if tag == "containers" {
containersImgs = extractImageInfos(containers, containersImgs, "/spec/jobTemplate/spec/template/spec/containers", logger)
} else {
ephemeralContainersImgs = extractImageInfos(containers, ephemeralContainersImgs, "/spec/jobTemplate/spec/template/spec/ephemeralContainers", logger)
}
}
@ -97,8 +108,10 @@ func extractImageInfo(resource *unstructured.Unstructured, log logr.Logger) (ini
if containers, ok, _ := unstructured.NestedSlice(resource.UnstructuredContent(), "spec", "template", "spec", tag); ok {
if tag == "initContainers" {
initContainersImgs = extractImageInfos(containers, initContainersImgs, "/spec/template/spec/initContainers", logger)
} else {
} else if tag == "containers" {
containersImgs = extractImageInfos(containers, containersImgs, "/spec/template/spec/containers", logger)
} else {
ephemeralContainersImgs = extractImageInfos(containers, ephemeralContainersImgs, "/spec/template/spec/ephemeralContainers", logger)
}
}
}
@ -215,6 +228,10 @@ func MutateResourceWithImageInfo(raw []byte, ctx *Context) error {
patches = append(patches, buildJSONPatch("replace", info.JSONPointer, info.String()))
}
for _, info := range images.EphemeralContainers {
patches = append(patches, buildJSONPatch("replace", info.JSONPointer, info.String()))
}
patchedResource, err := engineutils.ApplyPatches(raw, patches)
if err != nil {
return err

View file

@ -10,24 +10,29 @@ import (
func Test_extractImageInfo(t *testing.T) {
tests := []struct {
raw []byte
containers []*ContainerImage
initContainers []*ContainerImage
raw []byte
containers []*ContainerImage
initContainers []*ContainerImage
ephemeralContainers []*ContainerImage
}{
{
raw: []byte(`{"apiVersion": "v1","kind": "Pod","metadata": {"name": "myapp"},"spec": {"initContainers": [{"name": "init","image": "index.docker.io/busybox:v1.2.3"}],"containers": [{"name": "nginx","image": "nginx:latest"}]}}`),
initContainers: []*ContainerImage{{Name: "init", Image: &ImageInfo{Registry: "index.docker.io", Name: "busybox", Path: "busybox", Tag: "v1.2.3", JSONPointer: "/spec/initContainers/0/image"}}},
containers: []*ContainerImage{{Name: "nginx", Image: &ImageInfo{Registry: "docker.io", Name: "nginx", Path: "nginx", Tag: "latest", JSONPointer: "/spec/containers/0/image"}}},
raw: []byte(`{"apiVersion": "v1","kind": "Pod","metadata": {"name": "myapp"},"spec": {"initContainers": [{"name": "init","image": "index.docker.io/busybox:v1.2.3"}],"containers": [{"name": "nginx","image": "nginx:latest"}], "ephemeralContainers": [{"name": "ephemeral", "image":"test/nginx:latest"}]}}`),
initContainers: []*ContainerImage{{Name: "init", Image: &ImageInfo{Registry: "index.docker.io", Name: "busybox", Path: "busybox", Tag: "v1.2.3", JSONPointer: "/spec/initContainers/0/image"}}},
containers: []*ContainerImage{{Name: "nginx", Image: &ImageInfo{Registry: "docker.io", Name: "nginx", Path: "nginx", Tag: "latest", JSONPointer: "/spec/containers/0/image"}}},
ephemeralContainers: []*ContainerImage{{Name: "ephemeral", Image: &ImageInfo{Registry: "docker.io", Name: "nginx", Path: "test/nginx", Tag: "latest", JSONPointer: "/spec/ephemeralContainers/0/image"}}},
},
{
raw: []byte(`{"apiVersion": "v1","kind": "Pod","metadata": {"name": "myapp"},"spec": {"containers": [{"name": "nginx","image": "test/nginx:latest"}]}}`),
initContainers: []*ContainerImage{},
containers: []*ContainerImage{{Name: "nginx", Image: &ImageInfo{Registry: "docker.io", Name: "nginx", Path: "test/nginx", Tag: "latest", JSONPointer: "/spec/containers/0/image"}}},
raw: []byte(`{"apiVersion": "v1","kind": "Pod","metadata": {"name": "myapp"},"spec": {"containers": [{"name": "nginx","image": "test/nginx:latest"}]}}`),
initContainers: []*ContainerImage{},
containers: []*ContainerImage{{Name: "nginx", Image: &ImageInfo{Registry: "docker.io", Name: "nginx", Path: "test/nginx", Tag: "latest", JSONPointer: "/spec/containers/0/image"}}},
ephemeralContainers: []*ContainerImage{},
},
{
raw: []byte(`{"apiVersion": "apps/v1","kind": "Deployment","metadata": {"name": "myapp"},"spec": {"selector": {"matchLabels": {"app": "myapp"}},"template": {"metadata": {"labels": {"app": "myapp"}},"spec": {"initContainers": [{"name": "init","image": "fictional.registry.example:10443/imagename:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}],"containers": [{"name": "myapp","image": "fictional.registry.example:10443/imagename"}]}}}}`),
initContainers: []*ContainerImage{{Name: "init", Image: &ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "tag", JSONPointer: "/spec/template/spec/initContainers/0/image", Digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}}},
containers: []*ContainerImage{{Name: "myapp", Image: &ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "latest", JSONPointer: "/spec/template/spec/containers/0/image"}}}},
raw: []byte(`{"apiVersion": "apps/v1","kind": "Deployment","metadata": {"name": "myapp"},"spec": {"selector": {"matchLabels": {"app": "myapp"}},"template": {"metadata": {"labels": {"app": "myapp"}},"spec": {"initContainers": [{"name": "init","image": "fictional.registry.example:10443/imagename:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}],"containers": [{"name": "myapp","image": "fictional.registry.example:10443/imagename"}],"ephemeralContainers": [{"name": "ephemeral","image": "fictional.registry.example:10443/imagename:tag@sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}] }}}}`),
initContainers: []*ContainerImage{{Name: "init", Image: &ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "tag", JSONPointer: "/spec/template/spec/initContainers/0/image", Digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}}},
containers: []*ContainerImage{{Name: "myapp", Image: &ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "latest", JSONPointer: "/spec/template/spec/containers/0/image"}}},
ephemeralContainers: []*ContainerImage{{Name: "ephemeral", Image: &ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "tag", JSONPointer: "/spec/template/spec/ephemeralContainers/0/image", Digest: "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}}},
},
{
raw: []byte(`{"apiVersion": "batch/v1beta1","kind": "CronJob","metadata": {"name": "hello"},"spec": {"schedule": "*/1 * * * *","jobTemplate": {"spec": {"template": {"spec": {"containers": [{"name": "hello","image": "test.example.com/test/my-app:v2"}]}}}}}}`),
containers: []*ContainerImage{{Name: "hello", Image: &ImageInfo{Registry: "test.example.com", Name: "my-app", Path: "test/my-app", Tag: "v2", JSONPointer: "/spec/jobTemplate/spec/template/spec/containers/0/image"}}},
@ -38,7 +43,7 @@ func Test_extractImageInfo(t *testing.T) {
resource, err := utils.ConvertToUnstructured(test.raw)
assert.Nil(t, err)
init, container := extractImageInfo(resource, log.Log.WithName("TestExtractImageInfo"))
init, container, ephemeral := extractImageInfo(resource, log.Log.WithName("TestExtractImageInfo"))
if len(test.initContainers) > 0 {
assert.Equal(t, test.initContainers, init, "unexpected initContainers %s", resource.GetName())
}
@ -46,6 +51,10 @@ func Test_extractImageInfo(t *testing.T) {
if len(test.containers) > 0 {
assert.Equal(t, test.containers, container, "unexpected containers %s", resource.GetName())
}
if len(test.ephemeralContainers) > 0 {
assert.Equal(t, test.ephemeralContainers, ephemeral, "unexpected ephemeralContainers %s", resource.GetName())
}
}
}

View file

@ -80,6 +80,7 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (resp *response.EngineRe
for _, imageVerify := range ruleCopy.VerifyImages {
iv.verify(imageVerify, images.Containers)
iv.verify(imageVerify, images.InitContainers)
iv.verify(imageVerify, images.EphemeralContainers)
}
}