Skip to content

Commit

Permalink
feat: filter container by regex (#2080)
Browse files Browse the repository at this point in the history
* feat: filter container by regex

Signed-off-by: chenk <hen.keinan@gmail.com>

* feat: filter container by regex

Signed-off-by: chenk <hen.keinan@gmail.com>

* feat: filter container by regex

Signed-off-by: chenk <hen.keinan@gmail.com>

* feat: filter container by regex

Signed-off-by: chenk <hen.keinan@gmail.com>

* feat: filter container by regex

Signed-off-by: chenk <hen.keinan@gmail.com>

---------

Signed-off-by: chenk <hen.keinan@gmail.com>
  • Loading branch information
chen-keinan committed May 20, 2024
1 parent 727b9ab commit 289f303
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 0 deletions.
1 change: 1 addition & 0 deletions deploy/helm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ Keeps security report resources updated
| trivy.vulnType | string | `nil` | vulnType can be used to tell Trivy to filter vulnerabilities by a pkg-type (library, os) |
| trivyOperator.additionalReportLabels | string | `""` | additionalReportLabels comma-separated representation of the labels which the user wants the scanner pods to be labeled with. Example: `foo=bar,env=stage` will labeled the reports with the labels `foo: bar` and `env: stage` |
| trivyOperator.configAuditReportsPlugin | string | `"Trivy"` | configAuditReportsPlugin the name of the plugin that generates config audit reports. |
| trivyOperator.excludeImages | string | `""` | excludeImages is comma separated glob patterns for excluding images from scanning. Example: pattern: `k8s.gcr.io/*/*` will exclude image: `k8s.gcr.io/coredns/coredns:v1.8.0`. |
| trivyOperator.metricsResourceLabelsPrefix | string | `"k8s_label_"` | metricsResourceLabelsPrefix Prefix that will be prepended to the labels names indicated in `reportResourceLabels` when including them in the Prometheus metrics |
| trivyOperator.policiesConfig | string | `""` | policiesConfig Custom Rego Policies to be used by the config audit scanner See https://github.com/aquasecurity/trivy-operator/blob/main/docs/tutorials/writing-custom-configuration-audit-policies.md for more details. |
| trivyOperator.reportRecordFailedChecksOnly | bool | `true` | reportRecordFailedChecksOnly flag is to record only failed checks on misconfiguration reports (config-audit and rbac assessment) |
Expand Down
3 changes: 3 additions & 0 deletions deploy/helm/templates/configmaps/operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ data:
{{- with .Values.trivyOperator.skipInitContainers }}
scanJob.skipInitContainers: {{ . | quote }}
{{- end }}
{{- with .Values.trivyOperator.excludeImages }}
scanJob.excludeImages: {{ . | quote }}
{{- end }}
{{- with .Values.nodeCollector.excludeNodes }}
nodeCollector.excludeNodes: {{ . | quote }}
{{- end }}
Expand Down
4 changes: 4 additions & 0 deletions deploy/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ trivyOperator:
# See https://github.com/aquasecurity/trivy-operator/blob/main/docs/tutorials/writing-custom-configuration-audit-policies.md for more details.
policiesConfig: ""

# -- excludeImages is comma separated glob patterns for excluding images from scanning.
# Example: pattern: `k8s.gcr.io/*/*` will exclude image: `k8s.gcr.io/coredns/coredns:v1.8.0`.
excludeImages: ""

trivy:
# -- createConfig indicates whether to create config objects
createConfig: true
Expand Down
3 changes: 3 additions & 0 deletions pkg/plugins/trivy/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,9 @@ func GetPodSpecForClientServerFSMode(ctx trivyoperator.PluginContext, config Con
}

for _, c := range getContainers(spec) {
if ExcludeImage(ctx.GetTrivyOperatorConfig().ExcludeImages(), c.Image) {
continue
}
env := []corev1.EnvVar{
constructEnvVarSourceFromConfigMap("TRIVY_SEVERITY", trivyConfigName, KeyTrivySeverity),
ConfigWorkloadAnnotationEnvVars(workload, SkipFilesAnnotation, "TRIVY_SKIP_FILES", trivyConfigName, keyTrivySkipFiles),
Expand Down
3 changes: 3 additions & 0 deletions pkg/plugins/trivy/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ func GetPodSpecForStandaloneMode(ctx trivyoperator.PluginContext,
}

for _, c := range containersSpec {
if ExcludeImage(ctx.GetTrivyOperatorConfig().ExcludeImages(), c.Image) {
continue
}
env := []corev1.EnvVar{
constructEnvVarSourceFromConfigMap("TRIVY_SEVERITY", trivyConfigName, KeyTrivySeverity),
constructEnvVarSourceFromConfigMap("TRIVY_IGNORE_UNFIXED", trivyConfigName, keyTrivyIgnoreUnfixed),
Expand Down
14 changes: 14 additions & 0 deletions pkg/plugins/trivy/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package trivy
import (
"encoding/json"
"io"
"path/filepath"

"github.com/aquasecurity/trivy-operator/pkg/exposedsecretreport"
"github.com/aquasecurity/trivy-operator/pkg/sbomreport"
Expand Down Expand Up @@ -247,3 +248,16 @@ func (p *plugin) parseOSRef(reports ty.Report) v1alpha1.OS {

return os
}

// ExcludeImage checks if the image should be excluded from scanning based on the excludeImagePattern (glob pattern)
func ExcludeImage(excludeImagePattern []string, imageName string) bool {
if len(excludeImagePattern) == 0 {
return false
}
for _, pattern := range excludeImagePattern {
if matched, err := filepath.Match(pattern, imageName); err == nil && matched {
return true
}
}
return false
}
40 changes: 40 additions & 0 deletions pkg/plugins/trivy/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7458,3 +7458,43 @@ func TestGetFilesystemScanCacheDir(t *testing.T) {
})
}
}

func TestExcludeImages(t *testing.T) {
testCases := []struct {
name string
excludePattern []string
imageName string
want bool
}{
{
name: "exclude images single pattern match",
excludePattern: []string{"docker.io/*/*"},
imageName: "docker.io/library/alpine:3.10.2",
want: true,
},
{
name: "exclude images multi pattern match",
excludePattern: []string{"docker.io/*/*", "k8s.gcr.io/*/*"},
imageName: "k8s.gcr.io/coredns/coredns:v1.8.0",
want: true,
},
{
name: "exclude images multi pattern no match",
excludePattern: []string{"docker.io/*", "ecr.io/*/*"},
imageName: "docker.io/library/alpine:3.10.2",
want: false,
},
{
name: "exclude images no pattern",
excludePattern: []string{},
imageName: "docker.io/library/alpine:3.10.2",
want: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := trivy.ExcludeImage(tc.excludePattern, tc.imageName)
assert.Equal(t, got, tc.want)
})
}
}
15 changes: 15 additions & 0 deletions pkg/trivyoperator/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const (
KeyScanJobContainerSecurityContext = "scanJob.podTemplateContainerSecurityContext"
keyScanJobPodSecurityContext = "scanJob.podTemplatePodSecurityContext"
keyScanJobPodTemplateLabels = "scanJob.podTemplateLabels"
keyScanJobExcludeImags = "scanJob.excludeImages"
KeyScanJobPodPriorityClassName = "scanJob.podPriorityClassName"
keyComplianceFailEntriesLimit = "compliance.failEntriesLimit"
keySkipResourceByLabels = "skipResourceByLabels"
Expand Down Expand Up @@ -197,6 +198,20 @@ func (c ConfigData) GetScanJobTolerations() ([]corev1.Toleration, error) {
return scanJobTolerations, err
}

func (c ConfigData) ExcludeImages() []string {
patterns := make([]string, 0)
if excludeImagesPattern, ok := c[keyScanJobExcludeImags]; ok {
for _, s := range strings.Split(excludeImagesPattern, ",") {
if len(strings.TrimSpace(s)) == 0 {
continue
}
patterns = append(patterns, strings.TrimSpace(s))
}
return patterns
}
return []string{}
}

func (c ConfigData) GetNodeCollectorTolerations() ([]corev1.Toleration, error) {
var nodeCollectorTolerations []corev1.Toleration
if c[keyNodeCollectorTolerations] == "" {
Expand Down
36 changes: 36 additions & 0 deletions pkg/trivyoperator/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1108,3 +1108,39 @@ func TestConfigData_ExposedSecretsScannerEnabled(t *testing.T) {
})
}
}

func TestConfigData_GetExcludeImages(t *testing.T) {
testCases := []struct {
name string
key string
value string
expected []string
}{
{
name: "multi pattern",
key: "scanJob.excludeImages",
value: "docker.io/*, ecr.io/*/*",
expected: []string{"docker.io/*", "ecr.io/*/*"},
},
{
name: "single pattern",
key: "scanJob.excludeImages",
value: "docker.io/*",
expected: []string{"docker.io/*"},
},
{
name: "no pattern",
key: "scanJob.excludeImages",
value: "",
expected: []string{},
},
}
for _, tc := range testCases {
configData := trivyoperator.ConfigData{}
t.Run(tc.name, func(t *testing.T) {
configData.Set(tc.key, tc.value)
got := configData.ExcludeImages()
assert.Equal(t, tc.expected, got)
})
}
}
5 changes: 5 additions & 0 deletions pkg/vulnerabilityreport/controller/workload.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,11 @@ func (r *WorkloadController) SubmitScanJob(ctx context.Context, owner client.Obj
}
return fmt.Errorf("constructing scan job: %w", err)
}
// If there are no containers in the pod spec, we don't need to create a scan job.
if len(scanJob.Spec.Template.Spec.Containers) == 0 {
log.V(1).Info("ignoring vulnerability scan", "no containers in the pod spec for resource", owner.GetName())
return nil
}

for _, secret := range secrets {
err = r.Client.Create(ctx, secret)
Expand Down

0 comments on commit 289f303

Please sign in to comment.