Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kubernetes): Add report flag for summary #2112

Merged
merged 6 commits into from May 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 17 additions & 3 deletions docs/docs/kubernetes/scanning.md
Expand Up @@ -6,6 +6,8 @@ This feature might change without preserving backwards compatibility.

Scan your Kubernetes cluster for both Vulnerabilities and Misconfigurations.

Trivy uses your local kubectl configuration to access the API server to list artifacts.

Scan a full cluster:

```
Expand All @@ -24,13 +26,25 @@ Scan a namespace for only `CRITICAL` Vulnerabilities and Misconfigurations:
$ trivy k8s -n default -o results.json --severity CRITICAL
```

Trivy uses your local kubectl configuration to access the API server to list artifacts.
At this time, JSON is the only supported output and is intended to be used for automation, other reports will be implemented soon.
Scan a cluster and generate a simple summary report. The only outputs currently supported are `all` and `summary`. The default report format is `summary`

```
$ trivy k8s
```

![k8s Summary Report](../../imgs/k8s-summary.png)

To get all of the detail the output contains, use `--report all`, to get JSON output:

```
$ trivy k8s --report all
```


<details>
<summary>Result</summary>

```
```json
{
"ClusterName": "minikube",
"Vulnerabilities": [
Expand Down
Binary file added docs/imgs/k8s-summary.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 10 additions & 6 deletions go.mod
Expand Up @@ -7,13 +7,12 @@ require (
github.com/Masterminds/sprig/v3 v3.2.2
github.com/NYTimes/gziphandler v1.1.1
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
github.com/aquasecurity/fanal v0.0.0-20220513163515-33f2cd8392ee
github.com/aquasecurity/fanal v0.0.0-20220511115204-32614d79a234
github.com/aquasecurity/go-dep-parser v0.0.0-20220503151658-d316f5cc2cff
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492
github.com/aquasecurity/table v1.2.0
github.com/aquasecurity/trivy-db v0.0.0-20220327074450-74195d9604b2
github.com/caarlos0/env/v6 v6.9.1
github.com/cenkalti/backoff v2.2.1+incompatible
Expand Down Expand Up @@ -54,7 +53,7 @@ require (
require (
cloud.google.com/go v0.99.0 // indirect
cloud.google.com/go/storage v1.14.0 // indirect
github.com/Azure/azure-sdk-for-go v64.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go v63.0.0+incompatible // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.27 // indirect
Expand All @@ -77,10 +76,9 @@ require (
github.com/VividCortex/ewma v1.1.1 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/apparentlymart/go-cidr v1.1.0 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/aquasecurity/defsec v0.57.5
github.com/aquasecurity/defsec v0.57.3
github.com/aws/aws-sdk-go v1.44.5 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
Expand All @@ -93,7 +91,6 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/docker/cli v20.10.13+incompatible // indirect
github.com/docker/distribution v2.8.0+incompatible // indirect
github.com/docker/docker-credential-helpers v0.6.4 // indirect
Expand Down Expand Up @@ -242,6 +239,13 @@ require gopkg.in/yaml.v2 v2.4.0

require github.com/aquasecurity/trivy-kubernetes v0.1.0

require github.com/aquasecurity/table v1.5.1

require (
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
)

// To resolve CVE-2022-23648
replace github.com/containerd/containerd v1.5.9 => github.com/containerd/containerd v1.5.10

Expand Down
16 changes: 8 additions & 8 deletions go.sum
Expand Up @@ -56,8 +56,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg=
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v56.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v64.0.0+incompatible h1:WAA77WBDWYtNfCC95V70VvkdzHe+wM/r2MQ9mG7fnQs=
github.com/Azure/azure-sdk-for-go v64.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v63.0.0+incompatible h1:whPsa+jCHQSo5wGMPNLw4bz8q9Co2+vnXHzXGctoTaQ=
github.com/Azure/azure-sdk-for-go v63.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
Expand Down Expand Up @@ -180,10 +180,10 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30xLN2sUZcMXl50hg+PJCIDdJgIvIbVcKqLJ/ZrtM=
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8=
github.com/aquasecurity/defsec v0.57.5 h1:kOsRgMlQMxdOHYNEF0SCblZevrsdoz7c4fz5qYTTUFY=
github.com/aquasecurity/defsec v0.57.5/go.mod h1:42FxKif2itz+MHFlJ3TJjdroL9Jzj3THoexlueBTU5w=
github.com/aquasecurity/fanal v0.0.0-20220513163515-33f2cd8392ee h1:O7cN19V4W7u7s7M3kME21/IDUA4iQULDeo9g3DS4gdU=
github.com/aquasecurity/fanal v0.0.0-20220513163515-33f2cd8392ee/go.mod h1:1FqeeQo0AKRIgYgv60r0SOBNMBenxBQF3jAnnICEFIE=
github.com/aquasecurity/defsec v0.57.3 h1:oiATfUTxOAcxAuXSH31RdgjtXJdQznlVzMJWdVYGmXY=
github.com/aquasecurity/defsec v0.57.3/go.mod h1:42FxKif2itz+MHFlJ3TJjdroL9Jzj3THoexlueBTU5w=
github.com/aquasecurity/fanal v0.0.0-20220511115204-32614d79a234 h1:NG9Qs4hocUWcGytaA0yhArPRoPmo12EPAUERwYCgvLA=
github.com/aquasecurity/fanal v0.0.0-20220511115204-32614d79a234/go.mod h1:bqz0H4eqstkngJB0TJCk39GLXZcUtobMpuNr4ScC1vk=
github.com/aquasecurity/go-dep-parser v0.0.0-20220503151658-d316f5cc2cff h1:YNlzRYB0n4mZtfuWx6AWaGEjnLVNekchyoFDlYFZegs=
github.com/aquasecurity/go-dep-parser v0.0.0-20220503151658-d316f5cc2cff/go.mod h1:7EOQWQmyavVPY3fScbbPdd3dB/b0Q4ZbJ/NZCvNKrLs=
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM=
Expand All @@ -195,8 +195,8 @@ github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46/go.
github.com/aquasecurity/go-version v0.0.0-20201107203531-5e48ac5d022a/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU=
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 h1:rcEG5HI490FF0a7zuvxOxen52ddygCfNVjP0XOCMl+M=
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU=
github.com/aquasecurity/table v1.2.0 h1:26N9hFB5qttCjWoBgeKIlBtmlCpSwfL01BK7N+IOBN0=
github.com/aquasecurity/table v1.2.0/go.mod h1:1MFKrEPJ8NchM917BrVGvsqoXJo1OL1Ja7dF3PgUea4=
github.com/aquasecurity/table v1.5.1 h1:y05AuHM3p4BGybbGn/XbcTX3RxpyzeTXAXYMcJve4IE=
github.com/aquasecurity/table v1.5.1/go.mod h1:1MFKrEPJ8NchM917BrVGvsqoXJo1OL1Ja7dF3PgUea4=
github.com/aquasecurity/testdocker v0.0.0-20210911155206-e1e85f5a1516 h1:moQmzbpLo5dxHQCyEhqzizsDSNrNhn/7uRTCZzo4A1o=
github.com/aquasecurity/trivy-db v0.0.0-20220327074450-74195d9604b2 h1:q2Gza4V8uO5C1COzC2HeTbQgJIrmC6dTWaXZ8ujiWu0=
github.com/aquasecurity/trivy-db v0.0.0-20220327074450-74195d9604b2/go.mod h1:EwiQRdzVq6k7cKOMjkss8LjWMt2FUW7NaYwE7HfZZvk=
Expand Down
8 changes: 8 additions & 0 deletions pkg/commands/app.go
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/aquasecurity/trivy-db/pkg/metadata"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"

"github.com/aquasecurity/trivy/pkg/commands/artifact"
"github.com/aquasecurity/trivy/pkg/commands/option"
"github.com/aquasecurity/trivy/pkg/commands/plugin"
Expand Down Expand Up @@ -215,6 +216,12 @@ var (
EnvVars: []string{"TRIVY_K8S_NAMESPACE"},
}

reportFlag = cli.StringFlag{
Name: "report",
Value: "summary",
Usage: "specify a report format for the output. (all,summary default: all)",
}

// TODO: remove this flag after a sufficient deprecation period.
lightFlag = cli.BoolFlag{
Name: "light",
Expand Down Expand Up @@ -789,6 +796,7 @@ func NewK8sCommand() *cli.Command {
Action: artifact.K8sRun,
Flags: []cli.Flag{
&namespaceFlag,
&reportFlag,
&outputFlag,
&severityFlag,
&exitCodeFlag,
Expand Down
5 changes: 3 additions & 2 deletions pkg/commands/artifact/k8s.go
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy-db/pkg/db"

"github.com/aquasecurity/trivy/pkg/log"
pkgReport "github.com/aquasecurity/trivy/pkg/report"
k8sReport "github.com/aquasecurity/trivy/pkg/report/k8s"
Expand Down Expand Up @@ -76,9 +77,9 @@ func K8sRun(ctx *cli.Context) error {
report.ClusterName = cluster.GetCurrentContext()

if err = k8sReport.Write(report, pkgReport.Option{
Format: "json", // for now json is the default
Format: opt.KubernetesOption.ReportFormat, // for now json is the default
Output: opt.Output,
}); err != nil {
}, opt.Severities); err != nil {
return xerrors.Errorf("unable to write results: %w", err)
}

Expand Down
6 changes: 4 additions & 2 deletions pkg/commands/option/kubernetes.go
Expand Up @@ -6,12 +6,14 @@ import (

// KubernetesOption holds the options for Kubernetes scanning
type KubernetesOption struct {
Namespace string
Namespace string
ReportFormat string
}

// NewKubernetesOption is the factory method to return Kubernetes options
func NewKubernetesOption(c *cli.Context) KubernetesOption {
return KubernetesOption{
Namespace: c.String("namespace"),
Namespace: c.String("namespace"),
ReportFormat: c.String("report"),
}
}
53 changes: 46 additions & 7 deletions pkg/report/k8s/k8s.go
Expand Up @@ -3,6 +3,8 @@ package k8s
import (
"golang.org/x/xerrors"

dbTypes "github.com/aquasecurity/trivy-db/pkg/types"

"github.com/aquasecurity/trivy/pkg/report"
"github.com/aquasecurity/trivy/pkg/types"
)
Expand All @@ -15,26 +17,33 @@ type Report struct {
Misconfigurations []Resource `json:",omitempty"`
}

// ConsolidatedReport represents a kubernetes scan report with consolidated findings
type ConsolidatedReport struct {
SchemaVersion int `json:",omitempty"`
ClusterName string
Findings []Resource `json:",omitempty"`
}

// Resource represents a kubernetes resource report
type Resource struct {
Namespace string `json:",omitempty"`
Kind string
Name string
//TODO(josedonizetti): should add metadata? per report? per Result?
//Metadata Metadata `json:",omitempty"`
// TODO(josedonizetti): should add metadata? per report? per Result?
// Metadata Metadata `json:",omitempty"`
Results types.Results `json:",omitempty"`
Error string `json:",omitempty"`
}

// Failed returns whether the k8s report includes any vulnerabilities or misconfigurations
func (report Report) Failed() bool {
for _, r := range report.Vulnerabilities {
func (r Report) Failed() bool {
for _, r := range r.Vulnerabilities {
if r.Results.Failed() {
return true
}
}

for _, r := range report.Misconfigurations {
for _, r := range r.Misconfigurations {
if r.Results.Failed() {
return true
}
Expand All @@ -43,17 +52,47 @@ func (report Report) Failed() bool {
return false
}

func (r Report) consolidate() ConsolidatedReport {
consolidated := ConsolidatedReport{
SchemaVersion: r.SchemaVersion,
ClusterName: r.ClusterName,
}

for _, m := range r.Misconfigurations {
found := false
for _, v := range r.Vulnerabilities {
if v.Kind == m.Kind && v.Name == m.Name && v.Namespace == m.Namespace {
consolidated.Findings = append(consolidated.Findings, Resource{
Namespace: v.Namespace,
Kind: v.Kind,
Name: v.Name,
Results: append(v.Results, m.Results...),
Error: v.Error,
})
found = true
continue
}
}
if !found {
consolidated.Findings = append(consolidated.Findings, m)
}
}
return consolidated
}

// Writer defines the result write operation
type Writer interface {
Write(Report) error
}

// Write writes the results in the give format
func Write(report Report, option report.Option) error {
func Write(report Report, option report.Option, severities []dbTypes.Severity) error {
var writer Writer
switch option.Format {
case "json":
case "all":
writer = &JSONWriter{Output: option.Output}
case "summary":
writer = NewSummaryWriter(option.Output, severities)
default:
return xerrors.Errorf("unknown format: %v", option.Format)
}
Expand Down