Skip to content

Commit a99498c

Browse files
authored
feat(misconf): render causes for Terraform (#8360)
Signed-off-by: nikpivkin <[email protected]>
1 parent a994453 commit a99498c

29 files changed

+782
-259
lines changed

docs/docs/references/configuration/cli/trivy_config.md

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ trivy config [flags] DIR
4545
--redis-key string redis key file location, if using redis as cache backend
4646
--redis-tls enable redis TLS with public certificates, if using redis as cache backend
4747
--registry-token string registry token
48+
--render-cause strings specify configuration types for which the rendered causes will be shown in the table report (terraform)
4849
--report string specify a compliance report format for the output (all,summary) (default "all")
4950
-s, --severity strings severities of security issues to be displayed (UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL) (default [UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL])
5051
--skip-check-update skip fetching rego check updates

docs/docs/references/configuration/cli/trivy_filesystem.md

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ trivy filesystem [flags] PATH
7878
--redis-tls enable redis TLS with public certificates, if using redis as cache backend
7979
--registry-token string registry token
8080
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
81+
--render-cause strings specify configuration types for which the rendered causes will be shown in the table report (terraform)
8182
--report string specify a compliance report format for the output (all,summary) (default "all")
8283
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
8384
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])

docs/docs/references/configuration/cli/trivy_image.md

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ trivy image [flags] IMAGE_NAME
100100
--registry-token string registry token
101101
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
102102
--removed-pkgs detect vulnerabilities of removed packages (only for Alpine)
103+
--render-cause strings specify configuration types for which the rendered causes will be shown in the table report (terraform)
103104
--report string specify a format for the compliance report. (all,summary) (default "summary")
104105
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
105106
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])

docs/docs/references/configuration/cli/trivy_kubernetes.md

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ trivy kubernetes [flags] [CONTEXT]
9494
--redis-tls enable redis TLS with public certificates, if using redis as cache backend
9595
--registry-token string registry token
9696
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
97+
--render-cause strings specify configuration types for which the rendered causes will be shown in the table report (terraform)
9798
--report string specify a report format for the output (all,summary) (default "all")
9899
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
99100
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,rbac) (default [vuln,misconfig,secret,rbac])

docs/docs/references/configuration/cli/trivy_repository.md

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL)
7777
--redis-tls enable redis TLS with public certificates, if using redis as cache backend
7878
--registry-token string registry token
7979
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
80+
--render-cause strings specify configuration types for which the rendered causes will be shown in the table report (terraform)
8081
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
8182
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])
8283
--secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml")

docs/docs/references/configuration/cli/trivy_rootfs.md

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ trivy rootfs [flags] ROOTDIR
8080
--redis-tls enable redis TLS with public certificates, if using redis as cache backend
8181
--registry-token string registry token
8282
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
83+
--render-cause strings specify configuration types for which the rendered causes will be shown in the table report (terraform)
8384
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
8485
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])
8586
--secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml")

docs/docs/references/configuration/cli/trivy_vm.md

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ trivy vm [flags] VM_IMAGE
6969
--redis-key string redis key file location, if using redis as cache backend
7070
--redis-tls enable redis TLS with public certificates, if using redis as cache backend
7171
--rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev")
72+
--render-cause strings specify configuration types for which the rendered causes will be shown in the table report (terraform)
7273
--sbom-sources strings [EXPERIMENTAL] try to retrieve SBOM from the specified sources (oci,rekor)
7374
--scanners strings comma-separated list of what security issues to detect (vuln,misconfig,secret,license) (default [vuln,secret])
7475
--secret-config string specify a path to config file for secret scanning (default "trivy-secret.yaml")

docs/docs/references/configuration/config-file.md

+3
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@ misconfiguration:
409409
# Same as '--include-non-failures'
410410
include-non-failures: false
411411

412+
# Same as '--render-cause'
413+
render-cause: []
414+
412415
# Same as '--misconfig-scanners'
413416
scanners:
414417
- azure-arm

pkg/compliance/report/testdata/all.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"CauseMetadata": {
2424
"Code": {
2525
"Lines": null
26-
}
26+
},
27+
"RenderedCause": {}
2728
}
2829
}
2930
]
@@ -46,7 +47,8 @@
4647
"CauseMetadata": {
4748
"Code": {
4849
"Lines": null
49-
}
50+
},
51+
"RenderedCause": {}
5052
}
5153
}
5254
]

pkg/fanal/types/misconf.go

+13-7
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,14 @@ type MisconfResult struct {
3030
type MisconfResults []MisconfResult
3131

3232
type CauseMetadata struct {
33-
Resource string `json:",omitempty"`
34-
Provider string `json:",omitempty"`
35-
Service string `json:",omitempty"`
36-
StartLine int `json:",omitempty"`
37-
EndLine int `json:",omitempty"`
38-
Code Code `json:",omitempty"`
39-
Occurrences []Occurrence `json:",omitempty"`
33+
Resource string `json:",omitempty"`
34+
Provider string `json:",omitempty"`
35+
Service string `json:",omitempty"`
36+
StartLine int `json:",omitempty"`
37+
EndLine int `json:",omitempty"`
38+
Code Code `json:",omitempty"`
39+
Occurrences []Occurrence `json:",omitempty"`
40+
RenderedCause RenderedCause `json:",omitempty"`
4041
}
4142

4243
type Occurrence struct {
@@ -45,6 +46,11 @@ type Occurrence struct {
4546
Location Location
4647
}
4748

49+
type RenderedCause struct {
50+
Raw string `json:",omitempty"`
51+
Highlighted string `json:",omitempty"`
52+
}
53+
4854
type Code struct {
4955
Lines []Line
5056
}

pkg/flag/misconf_flags.go

+13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/samber/lo"
77

88
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
9+
"github.com/aquasecurity/trivy/pkg/fanal/types"
910
"github.com/aquasecurity/trivy/pkg/policy"
1011
xstrings "github.com/aquasecurity/trivy/pkg/x/strings"
1112
)
@@ -108,6 +109,13 @@ var (
108109
ConfigName: "misconfiguration.config-file-schemas",
109110
Usage: "specify paths to JSON configuration file schemas to determine that a file matches some configuration and pass the schema to Rego checks for type checking",
110111
}
112+
RenderCauseFlag = Flag[[]string]{
113+
Name: "render-cause",
114+
ConfigName: "misconfiguration.render-cause",
115+
Usage: "specify configuration types for which the rendered causes will be shown in the table report",
116+
Values: xstrings.ToStringSlice([]types.ConfigType{types.Terraform}), // TODO: add Plan and JSON?
117+
Default: []string{},
118+
}
111119
)
112120

113121
// MisconfFlagGroup composes common printer flag structs used for commands providing misconfiguration scanning.
@@ -128,6 +136,7 @@ type MisconfFlagGroup struct {
128136
TerraformExcludeDownloaded *Flag[bool]
129137
MisconfigScanners *Flag[[]string]
130138
ConfigFileSchemas *Flag[[]string]
139+
RenderCause *Flag[[]string]
131140
}
132141

133142
type MisconfOptions struct {
@@ -147,6 +156,7 @@ type MisconfOptions struct {
147156
TfExcludeDownloaded bool
148157
MisconfigScanners []analyzer.Type
149158
ConfigFileSchemas []string
159+
RenderCause []types.ConfigType
150160
}
151161

152162
func NewMisconfFlagGroup() *MisconfFlagGroup {
@@ -166,6 +176,7 @@ func NewMisconfFlagGroup() *MisconfFlagGroup {
166176
TerraformExcludeDownloaded: TerraformExcludeDownloaded.Clone(),
167177
MisconfigScanners: MisconfigScannersFlag.Clone(),
168178
ConfigFileSchemas: ConfigFileSchemasFlag.Clone(),
179+
RenderCause: RenderCauseFlag.Clone(),
169180
}
170181
}
171182

@@ -189,6 +200,7 @@ func (f *MisconfFlagGroup) Flags() []Flagger {
189200
f.CloudformationParamVars,
190201
f.MisconfigScanners,
191202
f.ConfigFileSchemas,
203+
f.RenderCause,
192204
}
193205
}
194206

@@ -212,5 +224,6 @@ func (f *MisconfFlagGroup) ToOptions() (MisconfOptions, error) {
212224
TfExcludeDownloaded: f.TerraformExcludeDownloaded.Value(),
213225
MisconfigScanners: xstrings.ToTSlice[analyzer.Type](f.MisconfigScanners.Value()),
214226
ConfigFileSchemas: f.ConfigFileSchemas.Value(),
227+
RenderCause: xstrings.ToTSlice[types.ConfigType](f.RenderCause.Value()),
215228
}, nil
216229
}

pkg/iac/scan/code.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ func (c *Code) IsCauseMultiline() bool {
7878
}
7979

8080
const (
81-
darkTheme = "solarized-dark256"
82-
lightTheme = "github"
81+
DarkTheme = "solarized-dark256"
82+
LightTheme = "github"
8383
)
8484

8585
type codeSettings struct {
@@ -90,7 +90,7 @@ type codeSettings struct {
9090
}
9191

9292
var defaultCodeSettings = codeSettings{
93-
theme: darkTheme,
93+
theme: DarkTheme,
9494
allowTruncation: true,
9595
maxLines: 10,
9696
includeHighlighted: true,
@@ -106,13 +106,13 @@ func OptionCodeWithTheme(theme string) CodeOption {
106106

107107
func OptionCodeWithDarkTheme() CodeOption {
108108
return func(s *codeSettings) {
109-
s.theme = darkTheme
109+
s.theme = DarkTheme
110110
}
111111
}
112112

113113
func OptionCodeWithLightTheme() CodeOption {
114114
return func(s *codeSettings) {
115-
s.theme = lightTheme
115+
s.theme = LightTheme
116116
}
117117
}
118118

pkg/iac/scan/flat.go

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type FlatResult struct {
2222
Resource string `json:"resource"`
2323
Occurrences []Occurrence `json:"occurrences,omitempty"`
2424
Location FlatRange `json:"location"`
25+
RenderedCause RenderedCause `json:"rendered_cause"`
2526
}
2627

2728
type FlatRange struct {
@@ -68,5 +69,6 @@ func (r *Result) Flatten() FlatResult {
6869
StartLine: rng.GetStartLine(),
6970
EndLine: rng.GetEndLine(),
7071
},
72+
RenderedCause: r.renderedCause,
7173
}
7274
}

pkg/iac/scan/highlighting.go

+18-10
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,17 @@ func highlight(fsKey, filename string, startLine, endLine int, input, theme stri
4141
return lines
4242
}
4343

44-
lexer := lexers.Match(filename)
45-
if lexer == nil {
46-
lexer = lexers.Fallback
44+
highlighted, ok := Highlight(filename, input, theme)
45+
if !ok {
46+
return nil
4747
}
48-
lexer = chroma.Coalesce(lexer)
4948

49+
lines := strings.Split(highlighted, "\n")
50+
globalCache.Set(key, lines)
51+
return lines
52+
}
53+
54+
func Highlight(filename, input, theme string) (string, bool) {
5055
style := styles.Get(theme)
5156
if style == nil {
5257
style = styles.Fallback
@@ -56,20 +61,23 @@ func highlight(fsKey, filename string, startLine, endLine int, input, theme stri
5661
formatter = formatters.Fallback
5762
}
5863

64+
lexer := lexers.Match(filename)
65+
if lexer == nil {
66+
lexer = lexers.Fallback
67+
}
68+
lexer = chroma.Coalesce(lexer)
69+
5970
iterator, err := lexer.Tokenise(nil, input)
6071
if err != nil {
61-
return nil
72+
return "", false
6273
}
6374

6475
var buffer bytes.Buffer
6576
if err := formatter.Format(&buffer, style, iterator); err != nil {
66-
return nil
77+
return "", false
6778
}
6879

69-
raw := shiftANSIOverLineEndings(buffer.Bytes())
70-
lines := strings.Split(string(raw), "\n")
71-
globalCache.Set(key, lines)
72-
return lines
80+
return string(shiftANSIOverLineEndings(buffer.Bytes())), true
7381
}
7482

7583
func shiftANSIOverLineEndings(input []byte) []byte {

pkg/iac/scan/result.go

+9
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type Result struct {
3232
regoRule string
3333
traces []string
3434
fsPath string
35+
renderedCause RenderedCause
3536
}
3637

3738
func (r Result) RegoNamespace() string {
@@ -101,6 +102,14 @@ func (r Result) Traces() []string {
101102
return r.traces
102103
}
103104

105+
type RenderedCause struct {
106+
Raw string
107+
}
108+
109+
func (r *Result) WithRenderedCause(cause RenderedCause) {
110+
r.renderedCause = cause
111+
}
112+
104113
func (r *Result) AbsolutePath(fsRoot string, metadata iacTypes.Metadata) string {
105114
if strings.HasSuffix(fsRoot, ":") {
106115
fsRoot += "/"

0 commit comments

Comments
 (0)