From 4970ef8908b0527945812660214ae0cbe7b1ef3a Mon Sep 17 00:00:00 2001 From: takutaka Date: Tue, 27 Aug 2024 20:40:54 +0900 Subject: [PATCH 1/3] fix: use index instead of `container`. --- pkg/vulnerabilityreport/builder.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/vulnerabilityreport/builder.go b/pkg/vulnerabilityreport/builder.go index 9913d229a..bb9da2ec3 100644 --- a/pkg/vulnerabilityreport/builder.go +++ b/pkg/vulnerabilityreport/builder.go @@ -166,11 +166,11 @@ func (s *ScanJobBuilder) Get() (*batchv1.Job, []*corev1.Secret, error) { templateSpec.Volumes = append(templateSpec.Volumes, s.customVolumes...) } if len(s.customVolumesMount) > 0 { - for _, container := range templateSpec.Containers { - container.VolumeMounts = append(container.VolumeMounts, s.customVolumesMount...) + for i := range templateSpec.Containers { + templateSpec.Containers[i].VolumeMounts = append(templateSpec.Containers[i].VolumeMounts, s.customVolumesMount...) } - for _, initContainer := range templateSpec.InitContainers { - initContainer.VolumeMounts = append(initContainer.VolumeMounts, s.customVolumesMount...) + for i := range templateSpec.InitContainers { + templateSpec.InitContainers[i].VolumeMounts = append(templateSpec.InitContainers[i].VolumeMounts, s.customVolumesMount...) } } templateSpec.PriorityClassName = s.podPriorityClassName From 37143dcb4b956f6f8d69957222b2b17ad3dde090 Mon Sep 17 00:00:00 2001 From: takutaka Date: Tue, 27 Aug 2024 20:48:21 +0900 Subject: [PATCH 2/3] add test for builder using custom volumes and mounts --- pkg/vulnerabilityreport/builder_test.go | 91 +++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/pkg/vulnerabilityreport/builder_test.go b/pkg/vulnerabilityreport/builder_test.go index d7968ba6a..05303c6ab 100644 --- a/pkg/vulnerabilityreport/builder_test.go +++ b/pkg/vulnerabilityreport/builder_test.go @@ -294,6 +294,97 @@ func TestScanJobBuilder(t *testing.T) { }, })) }) + + t.Run("Shoud set scan job with custom volume and volume mount", func(t *testing.T) { + g := gomega.NewGomegaWithT(t) + job, _, err := vulnerabilityreport.NewScanJobBuilder(). + WithPlugin(&testPlugin{}). + WithPluginContext(trivyoperator.NewPluginContext(). + WithName("test-plugin"). + WithNamespace("trivy-operator-ns"). + WithServiceAccountName("trivy-operator-sa"). + Get()). + WithTimeout(3 * time.Second). + WithObject(&appsv1.ReplicaSet{ + TypeMeta: metav1.TypeMeta{ + Kind: "ReplicaSet", + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "nginx-6799fc88d8", + Namespace: "prod-ns", + }, + Spec: appsv1.ReplicaSetSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "nginx", + Image: "nginx:1.16", + }, + }, + }, + }, + Selector: &metav1.LabelSelector{}, + }, + }). + WithCustomVolumes([]corev1.Volume{ + { + Name: "test-volume", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + }). + WithCustomVolumesMount([]corev1.VolumeMount{ + { + Name: "test-volume", + MountPath: "/test-mount-path", + }, + }). + Get() + g.Expect(err).ToNot(gomega.HaveOccurred()) + g.Expect(job).ToNot(gomega.BeNil()) + g.Expect(job).To(gomega.Equal(&batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: "scan-vulnerabilityreport-64d65c457", + Namespace: "trivy-operator-ns", + Labels: map[string]string{ + trivyoperator.LabelK8SAppManagedBy: "trivy-operator", + trivyoperator.LabelVulnerabilityReportScanner: "test-plugin", + trivyoperator.LabelResourceKind: "ReplicaSet", + trivyoperator.LabelResourceName: "nginx-6799fc88d8", + trivyoperator.LabelResourceNamespace: "prod-ns", + trivyoperator.LabelResourceSpecHash: "788f48d57f", + }, + Annotations: map[string]string{ + "test-annotation": "test-value", + trivyoperator.AnnotationContainerImages: `{"nginx":"nginx:1.16"}`, + }, + }, + Spec: batchv1.JobSpec{ + BackoffLimit: ptr.To[int32](0), + Completions: ptr.To[int32](1), + ActiveDeadlineSeconds: ptr.To[int64](3), + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + trivyoperator.LabelK8SAppManagedBy: "trivy-operator", + trivyoperator.LabelVulnerabilityReportScanner: "test-plugin", + trivyoperator.LabelResourceKind: "ReplicaSet", + trivyoperator.LabelResourceName: "nginx-6799fc88d8", + trivyoperator.LabelResourceNamespace: "prod-ns", + trivyoperator.LabelResourceSpecHash: "788f48d57f", + }, + Annotations: map[string]string{ + "test-annotation": "test-value", + }, + }, + Spec: corev1.PodSpec{}, + }, + }, + })) + }) } type testPlugin struct { From d69536e7695c238802265e1ffefca1142c1b4c8e Mon Sep 17 00:00:00 2001 From: takutaka Date: Tue, 27 Aug 2024 23:35:51 +0900 Subject: [PATCH 3/3] add container definition included plugin and use it --- pkg/vulnerabilityreport/builder_test.go | 104 +++++++++++++++++++----- 1 file changed, 84 insertions(+), 20 deletions(-) diff --git a/pkg/vulnerabilityreport/builder_test.go b/pkg/vulnerabilityreport/builder_test.go index 05303c6ab..677e6234c 100644 --- a/pkg/vulnerabilityreport/builder_test.go +++ b/pkg/vulnerabilityreport/builder_test.go @@ -298,7 +298,7 @@ func TestScanJobBuilder(t *testing.T) { t.Run("Shoud set scan job with custom volume and volume mount", func(t *testing.T) { g := gomega.NewGomegaWithT(t) job, _, err := vulnerabilityreport.NewScanJobBuilder(). - WithPlugin(&testPlugin{}). + WithPlugin(&testContainersPlugin{}). WithPluginContext(trivyoperator.NewPluginContext(). WithName("test-plugin"). WithNamespace("trivy-operator-ns"). @@ -317,10 +317,17 @@ func TestScanJobBuilder(t *testing.T) { Spec: appsv1.ReplicaSetSpec{ Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "test-init-container", + Image: "test-init-image", + }, + }, + Containers: []corev1.Container{ { - Name: "nginx", - Image: "nginx:1.16", + Name: "test-container", + Image: "test-image", }, }, }, @@ -350,16 +357,15 @@ func TestScanJobBuilder(t *testing.T) { Name: "scan-vulnerabilityreport-64d65c457", Namespace: "trivy-operator-ns", Labels: map[string]string{ - trivyoperator.LabelK8SAppManagedBy: "trivy-operator", - trivyoperator.LabelVulnerabilityReportScanner: "test-plugin", - trivyoperator.LabelResourceKind: "ReplicaSet", - trivyoperator.LabelResourceName: "nginx-6799fc88d8", - trivyoperator.LabelResourceNamespace: "prod-ns", - trivyoperator.LabelResourceSpecHash: "788f48d57f", + "app.kubernetes.io/managed-by": "trivy-operator", + "resource-spec-hash": "7dcdf9f488", + "trivy-operator.resource.kind": "ReplicaSet", + "trivy-operator.resource.name": "nginx-6799fc88d8", + "trivy-operator.resource.namespace": "prod-ns", + "vulnerabilityReport.scanner": "test-plugin", }, Annotations: map[string]string{ - "test-annotation": "test-value", - trivyoperator.AnnotationContainerImages: `{"nginx":"nginx:1.16"}`, + "trivy-operator.container-images": `{"test-container":"test-image","test-init-container":"test-init-image"}`, }, }, Spec: batchv1.JobSpec{ @@ -369,18 +375,48 @@ func TestScanJobBuilder(t *testing.T) { Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ - trivyoperator.LabelK8SAppManagedBy: "trivy-operator", - trivyoperator.LabelVulnerabilityReportScanner: "test-plugin", - trivyoperator.LabelResourceKind: "ReplicaSet", - trivyoperator.LabelResourceName: "nginx-6799fc88d8", - trivyoperator.LabelResourceNamespace: "prod-ns", - trivyoperator.LabelResourceSpecHash: "788f48d57f", + "app.kubernetes.io/managed-by": "trivy-operator", + "resource-spec-hash": "7dcdf9f488", + "trivy-operator.resource.kind": "ReplicaSet", + "trivy-operator.resource.name": "nginx-6799fc88d8", + "trivy-operator.resource.namespace": "prod-ns", + "vulnerabilityReport.scanner": "test-plugin", }, - Annotations: map[string]string{ - "test-annotation": "test-value", + }, + Spec: corev1.PodSpec{ + Volumes: []corev1.Volume{ + { + Name: "test-volume", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + }, + InitContainers: []corev1.Container{ + { + Name: "test-init-container", + Image: "test-init-image", + VolumeMounts: []corev1.VolumeMount{ + { + Name: "test-volume", + MountPath: "/test-mount-path", + }, + }, + }, + }, + Containers: []corev1.Container{ + { + Name: "test-container", + Image: "test-image", + VolumeMounts: []corev1.VolumeMount{ + { + Name: "test-volume", + MountPath: "/test-mount-path", + }, + }, + }, }, }, - Spec: corev1.PodSpec{}, }, }, })) @@ -401,3 +437,31 @@ func (p *testPlugin) GetScanJobSpec(_ trivyoperator.PluginContext, _ client.Obje func (p *testPlugin) ParseReportData(_ trivyoperator.PluginContext, _ string, _ io.ReadCloser) (v1alpha1.VulnerabilityReportData, v1alpha1.ExposedSecretReportData, *v1alpha1.SbomReportData, error) { return v1alpha1.VulnerabilityReportData{}, v1alpha1.ExposedSecretReportData{}, &v1alpha1.SbomReportData{}, nil } + +type testContainersPlugin struct { +} + +func (p *testContainersPlugin) Init(_ trivyoperator.PluginContext) error { + return nil +} + +func (p *testContainersPlugin) GetScanJobSpec(_ trivyoperator.PluginContext, _ client.Object, _ map[string]docker.Auth, _ *corev1.SecurityContext, _ map[string]v1alpha1.SbomReportData) (corev1.PodSpec, []*corev1.Secret, error) { + return corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "test-init-container", + Image: "test-init-image", + }, + }, + Containers: []corev1.Container{ + { + Name: "test-container", + Image: "test-image", + }, + }, + }, nil, nil +} + +func (p *testContainersPlugin) ParseReportData(_ trivyoperator.PluginContext, _ string, _ io.ReadCloser) (v1alpha1.VulnerabilityReportData, v1alpha1.ExposedSecretReportData, *v1alpha1.SbomReportData, error) { + return v1alpha1.VulnerabilityReportData{}, v1alpha1.ExposedSecretReportData{}, &v1alpha1.SbomReportData{}, nil +}