Skip to content

Commit 6345f00

Browse files
committed
feat: allow to remove fields from vulnerability reports
1 parent 1caa4d4 commit 6345f00

File tree

7 files changed

+172
-43
lines changed

7 files changed

+172
-43
lines changed

deploy/helm/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ Keeps security report resources updated
129129
| targetNamespaces | string | `""` | targetNamespace defines where you want trivy-operator to operate. By default, it's a blank string to select all namespaces, but you can specify another namespace, or a comma separated list of namespaces. |
130130
| targetWorkloads | string | `"pod,replicaset,replicationcontroller,statefulset,daemonset,cronjob,job"` | targetWorkloads is a comma seperated list of Kubernetes workload resources to be included in the vulnerability and config-audit scans if left blank, all workload resources will be scanned |
131131
| tolerations | list | `[]` | tolerations set the operator tolerations |
132-
| trivy.additionalVulnerabilityReportFields | string | `""` | additionalVulnerabilityReportFields is a comma separated list of additional fields which can be added to the VulnerabilityReport. Supported parameters: Description, Links, CVSS, Target, Class, PackagePath and PackageType |
132+
| trivy.additionalVulnerabilityReportFields | string | `""` | additionalVulnerabilityReportFields is a comma separated list of additional fields which can be added to the VulnerabilityReport. Supported parameters: Description, Links, CVSS, Target, Class, PackagePath and PackageType. Fields can also be removed with a leading minus sign `-`. Supported parameters: -Resource, -InstalledVersion, -FixedVersion, -PublishedDate, -LastModifiedDate, -Severity, -Title, -PrimaryLink, -Score and -PkgPURL. |
133133
| trivy.clientServerSkipUpdate | bool | `false` | clientServerSkipUpdate is the flag to enable skip databases update for Trivy client. Only applicable in ClientServer mode. |
134134
| trivy.command | string | `"image"` | command. One of `image`, `filesystem` or `rootfs` scanning, depending on the target type required for the scan. For 'filesystem' and `rootfs` scanning, ensure that the `trivyOperator.scanJobPodTemplateContainerSecurityContext` is configured to run as the root user (runAsUser = 0). |
135135
| trivy.configFile | string | `nil` | configFile can be used to tell Trivy to use specific options available only in the config file (e.g. Mirror registries). |

deploy/helm/values.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,8 @@ trivy:
398398
priorityClassName: ""
399399

400400
# -- additionalVulnerabilityReportFields is a comma separated list of additional fields which
401-
# can be added to the VulnerabilityReport. Supported parameters: Description, Links, CVSS, Target, Class, PackagePath and PackageType
401+
# can be added to the VulnerabilityReport. Supported parameters: Description, Links, CVSS, Target, Class, PackagePath and PackageType.
402+
# Fields can also be removed with a leading minus sign `-`. Supported parameters: -Resource, -InstalledVersion, -FixedVersion, -PublishedDate, -LastModifiedDate, -Severity, -Title, -PrimaryLink, -Score and -PkgPURL.
402403
additionalVulnerabilityReportFields: ""
403404

404405
# -- httpProxy is the HTTP proxy used by Trivy to download the vulnerabilities database from GitHub.

docs/docs/vulnerability-scanning/trivy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ EOF
101101
| `trivy.javaDbRepository` | `mirror.gcr.io/aquasec/trivy-java-db` | External OCI Registry to download the vulnerability database for Java |
102102
| `trivy.dbRepositoryInsecure` | `false` | The Flag to enable insecure connection for downloading trivy-db via proxy (air-gaped env) |
103103
| `trivy.mode` | `Standalone` | Trivy client mode. Either `Standalone` or `ClientServer`. Depending on the active mode other settings might be applicable or required. |
104-
| `additionalVulnerabilityReportFields` | N/A | A comma separated list of additional fields which can be added to the VulnerabilityReport. Possible values: `Description,Links,CVSS,Target,Class,PackagePath,PackageType`. Description will add more data about vulnerability. Links - all the references to a specific vulnerability. CVSS - data about CVSSv2/CVSSv3 scoring and vectors. Target - vulnerable element. Class - OS or library vulnerability |
104+
| `additionalVulnerabilityReportFields` | N/A | A comma separated list of additional fields which can be added to the VulnerabilityReport. Possible values: `Description,Links,CVSS,Target,Class,PackagePath,PackageType`. Description will add more data about vulnerability. Links - all the references to a specific vulnerability. CVSS - data about CVSSv2/CVSSv3 scoring and vectors. Target - vulnerable element. Class - OS or library vulnerability. Fields can also be removed with a leading minus sign `-`. Possible values: `Resource,InstalledVersion,FixedVersion,PublishedDate,LastModifiedDate,Severity,Title,PrimaryLink,Score,PkgPURL` |
105105
| `trivy.command` | `image` | command. One of `image`, `filesystem` or `rootfs` scanning. Depending on the target type required for the scan. |
106106
| `trivy.slow` | `true` | This flag is to use less CPU/memory for scanning though it takes more time than normal scanning. It fits small-footprint |
107107
| `trivy.severity` | `UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL` | A comma separated list of severity levels reported by Trivy |

pkg/plugins/trivy/config.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,28 +80,49 @@ type Config struct {
8080
}
8181

8282
func (c Config) GetAdditionalVulnerabilityReportFields() vulnerabilityreport.AdditionalFields {
83-
addFields := vulnerabilityreport.AdditionalFields{}
83+
addFields := vulnerabilityreport.NewDefaultAdditionalFields()
8484

8585
fields, ok := c.Data[keyTrivyAdditionalVulnerabilityReportFields]
8686
if !ok {
8787
return addFields
8888
}
8989
for _, field := range strings.Split(fields, ",") {
90+
trimmed_field := strings.TrimSpace(field)
91+
value := !strings.HasPrefix(trimmed_field, "-")
92+
field = strings.TrimPrefix(trimmed_field, "-")
9093
switch strings.TrimSpace(field) {
94+
case "Resource":
95+
addFields.Resource = value
96+
case "InstalledVersion":
97+
addFields.InstalledVersion = value
98+
case "FixedVersion":
99+
addFields.FixedVersion = value
100+
case "PublishedDate":
101+
addFields.PublishedDate = value
102+
case "LastModifiedDate":
103+
addFields.LastModifiedDate = value
104+
case "Title":
105+
addFields.Title = value
106+
case "PrimaryLink":
107+
addFields.PrimaryLink = value
108+
case "Score":
109+
addFields.Score = value
110+
case "PkgPURL":
111+
addFields.PkgPURL = value
91112
case "Description":
92-
addFields.Description = true
113+
addFields.Description = value
93114
case "Links":
94-
addFields.Links = true
115+
addFields.Links = value
95116
case "CVSS":
96-
addFields.CVSS = true
117+
addFields.CVSS = value
97118
case "Target":
98-
addFields.Target = true
119+
addFields.Target = value
99120
case "Class":
100-
addFields.Class = true
121+
addFields.Class = value
101122
case "PackageType":
102-
addFields.PackageType = true
123+
addFields.PackageType = value
103124
case "PackagePath":
104-
addFields.PkgPath = true
125+
addFields.PkgPath = value
105126
}
106127
}
107128
return addFields

pkg/plugins/trivy/config_test.go

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func TestConfig_GetAdditionalVulnerabilityReportFields(t *testing.T) {
8888
{
8989
name: "no additional fields are set",
9090
configData: Config{PluginConfig: trivyoperator.PluginConfig{}},
91-
additionalFields: vulnerabilityreport.AdditionalFields{},
91+
additionalFields: vulnerabilityreport.NewDefaultAdditionalFields(),
9292
},
9393
{
9494
name: "all additional fields are set",
@@ -97,7 +97,25 @@ func TestConfig_GetAdditionalVulnerabilityReportFields(t *testing.T) {
9797
"trivy.additionalVulnerabilityReportFields": "PackageType,PkgPath,Class,Target,Links,Description,CVSS",
9898
},
9999
}},
100-
additionalFields: vulnerabilityreport.AdditionalFields{Description: true, Links: true, CVSS: true, Class: true, PackageType: true, PkgPath: true, Target: true},
100+
additionalFields: vulnerabilityreport.AdditionalFields{
101+
// default
102+
Resource: true,
103+
InstalledVersion: true,
104+
FixedVersion: true,
105+
PublishedDate: true,
106+
LastModifiedDate: true,
107+
Title: true,
108+
PrimaryLink: true,
109+
Score: true,
110+
PkgPURL: true,
111+
// added
112+
Description: true,
113+
Links: true,
114+
CVSS: true,
115+
Class: true,
116+
PackageType: true,
117+
Target: true,
118+
},
101119
},
102120
{
103121
name: "some additional fields are set",
@@ -106,19 +124,77 @@ func TestConfig_GetAdditionalVulnerabilityReportFields(t *testing.T) {
106124
"trivy.additionalVulnerabilityReportFields": "PackageType,Target,Links,CVSS",
107125
},
108126
}},
109-
additionalFields: vulnerabilityreport.AdditionalFields{Links: true, CVSS: true, PackageType: true, Target: true},
127+
additionalFields: vulnerabilityreport.AdditionalFields{
128+
// default
129+
Resource: true,
130+
InstalledVersion: true,
131+
FixedVersion: true,
132+
PublishedDate: true,
133+
LastModifiedDate: true,
134+
Title: true,
135+
PrimaryLink: true,
136+
Score: true,
137+
PkgPURL: true,
138+
// added
139+
Links: true,
140+
CVSS: true,
141+
PackageType: true,
142+
Target: true,
143+
},
144+
},
145+
{
146+
name: "all fields are removed",
147+
configData: Config{PluginConfig: trivyoperator.PluginConfig{
148+
Data: map[string]string{
149+
"trivy.additionalVulnerabilityReportFields": " -Resource,- InstalledVersion, - FixedVersion, - PublishedDate,-LastModifiedDate,-Title,-PrimaryLink,-Score,-PkgPURL",
150+
},
151+
}},
152+
additionalFields: vulnerabilityreport.AdditionalFields{},
153+
},
154+
{
155+
name: "some fields are added and some are removed",
156+
configData: Config{PluginConfig: trivyoperator.PluginConfig{
157+
Data: map[string]string{
158+
"trivy.additionalVulnerabilityReportFields": "CVSS,PackageType,-PublishedDate,-LastModifiedDate",
159+
},
160+
}},
161+
additionalFields: vulnerabilityreport.AdditionalFields{
162+
// default
163+
Resource: true,
164+
InstalledVersion: true,
165+
FixedVersion: true,
166+
PublishedDate: false, // removed
167+
LastModifiedDate: false, // removed
168+
Title: true,
169+
PrimaryLink: true,
170+
Score: true,
171+
PkgPURL: true,
172+
// added
173+
CVSS: true,
174+
PackageType: true,
175+
},
110176
},
111177
}
112178

113179
for _, tc := range testCases {
114180
t.Run(tc.name, func(t *testing.T) {
115181
addFields := tc.configData.GetAdditionalVulnerabilityReportFields()
182+
assert.Equal(t, tc.additionalFields.Resource, addFields.Resource)
183+
assert.Equal(t, tc.additionalFields.InstalledVersion, addFields.InstalledVersion)
184+
assert.Equal(t, tc.additionalFields.FixedVersion, addFields.FixedVersion)
185+
assert.Equal(t, tc.additionalFields.PublishedDate, addFields.PublishedDate)
186+
assert.Equal(t, tc.additionalFields.LastModifiedDate, addFields.LastModifiedDate)
187+
assert.Equal(t, tc.additionalFields.Title, addFields.Title)
188+
assert.Equal(t, tc.additionalFields.PrimaryLink, addFields.PrimaryLink)
189+
assert.Equal(t, tc.additionalFields.Score, addFields.Score)
190+
assert.Equal(t, tc.additionalFields.PkgPURL, addFields.PkgPURL)
116191
assert.Equal(t, tc.additionalFields.Description, addFields.Description)
192+
assert.Equal(t, tc.additionalFields.Links, addFields.Links)
117193
assert.Equal(t, tc.additionalFields.CVSS, addFields.CVSS)
118194
assert.Equal(t, tc.additionalFields.Target, addFields.Target)
119-
assert.Equal(t, tc.additionalFields.PackageType, addFields.PackageType)
120195
assert.Equal(t, tc.additionalFields.Class, addFields.Class)
121-
assert.Equal(t, tc.additionalFields.Links, addFields.Links)
196+
assert.Equal(t, tc.additionalFields.PackageType, addFields.PackageType)
197+
assert.Equal(t, tc.additionalFields.PkgPath, addFields.PkgPath)
122198
})
123199
}
124200
}

pkg/plugins/trivy/plugin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ func (p *plugin) ParseReportData(ctx trivyoperator.PluginContext, imageRef strin
182182
}
183183
vulnerabilities := make([]v1alpha1.Vulnerability, 0)
184184
secrets := make([]v1alpha1.ExposedSecret, 0)
185+
addFields := config.GetAdditionalVulnerabilityReportFields()
185186
for _, report := range reports.Results {
186-
addFields := config.GetAdditionalVulnerabilityReportFields()
187187
vulnerabilities = append(vulnerabilities, vulnerabilityreport.GetVulnerabilitiesFromScanResult(report, addFields)...)
188188
secrets = append(secrets, getExposedSecretsFromScanResult(report)...)
189189
}

pkg/vulnerabilityreport/io.go

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -129,41 +129,72 @@ func (r *readWriter) FindByOwner(ctx context.Context, owner kube.ObjectRef) ([]v
129129
}
130130

131131
type AdditionalFields struct {
132-
Description bool
133-
Links bool
134-
CVSS bool
135-
Target bool
136-
Class bool
137-
PackageType bool
138-
PkgPath bool
132+
Resource bool
133+
InstalledVersion bool
134+
FixedVersion bool
135+
PublishedDate bool
136+
LastModifiedDate bool
137+
Title bool
138+
PrimaryLink bool
139+
Score bool
140+
PkgPURL bool
141+
Description bool
142+
Links bool
143+
CVSS bool
144+
Target bool
145+
Class bool
146+
PackageType bool
147+
PkgPath bool
148+
}
149+
150+
func NewDefaultAdditionalFields() AdditionalFields {
151+
return AdditionalFields{
152+
Resource: true,
153+
InstalledVersion: true,
154+
FixedVersion: true,
155+
PublishedDate: true,
156+
LastModifiedDate: true,
157+
Title: true,
158+
PrimaryLink: true,
159+
Score: true,
160+
PkgPURL: true,
161+
}
139162
}
140163

141164
func GetVulnerabilitiesFromScanResult(report ty.Result, addFields AdditionalFields) []v1alpha1.Vulnerability {
142165
vulnerabilities := make([]v1alpha1.Vulnerability, 0)
143166

144167
for _, sr := range report.Vulnerabilities {
145-
var pd, lmd string
146-
if sr.PublishedDate != nil {
147-
pd = sr.PublishedDate.Format(time.RFC3339)
148-
}
149-
if sr.LastModifiedDate != nil {
150-
lmd = sr.LastModifiedDate.Format(time.RFC3339)
151-
}
152168
vulnerability := v1alpha1.Vulnerability{
153-
VulnerabilityID: sr.VulnerabilityID,
154-
Resource: sr.PkgName,
155-
InstalledVersion: sr.InstalledVersion,
156-
FixedVersion: sr.FixedVersion,
157-
PublishedDate: pd,
158-
LastModifiedDate: lmd,
159-
Severity: v1alpha1.Severity(sr.Severity),
160-
Title: sr.Title,
161-
PrimaryLink: sr.PrimaryURL,
162-
Links: []string{},
163-
Score: GetScoreFromCVSS(GetCvssV3(sr.CVSS)),
169+
VulnerabilityID: sr.VulnerabilityID,
170+
Severity: v1alpha1.Severity(sr.Severity),
164171
}
165172

166-
if sr.PkgIdentifier.PURL != nil {
173+
if addFields.Resource {
174+
vulnerability.Resource = sr.PkgName
175+
}
176+
if addFields.InstalledVersion {
177+
vulnerability.InstalledVersion = sr.InstalledVersion
178+
}
179+
if addFields.FixedVersion {
180+
vulnerability.FixedVersion = sr.FixedVersion
181+
}
182+
if addFields.PublishedDate && sr.PublishedDate != nil {
183+
vulnerability.PublishedDate = sr.PublishedDate.Format(time.RFC3339)
184+
}
185+
if addFields.LastModifiedDate && sr.LastModifiedDate != nil {
186+
vulnerability.LastModifiedDate = sr.LastModifiedDate.Format(time.RFC3339)
187+
}
188+
if addFields.Title {
189+
vulnerability.Title = sr.Title
190+
}
191+
if addFields.PrimaryLink {
192+
vulnerability.PrimaryLink = sr.PrimaryURL
193+
}
194+
if addFields.Score {
195+
vulnerability.Score = GetScoreFromCVSS(GetCvssV3(sr.CVSS))
196+
}
197+
if addFields.PkgPURL && sr.PkgIdentifier.PURL != nil {
167198
vulnerability.PkgPURL = sr.PkgIdentifier.PURL.String()
168199
}
169200

0 commit comments

Comments
 (0)