mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-22 23:26:39 -08:00
* feat: cyclonedx kbom support Signed-off-by: chenk <hen.keinan@gmail.com> * feat: cyclonedx kbom support Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> * chore: update sum db Signed-off-by: chenk <hen.keinan@gmail.com> * chore: update sum db Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> * chore: update sumdb Signed-off-by: chenk <hen.keinan@gmail.com> * chore: update sumdb Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> * feat: kubernetes bill of materials Signed-off-by: chenk <hen.keinan@gmail.com> --------- Signed-off-by: chenk <hen.keinan@gmail.com>
410 lines
16 KiB
Go
410 lines
16 KiB
Go
package k8s
|
|
|
|
import (
|
|
"bytes"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
|
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
|
"github.com/aquasecurity/trivy/pkg/k8s/report"
|
|
"github.com/aquasecurity/trivy/pkg/types"
|
|
)
|
|
|
|
const (
|
|
AllReport = "all"
|
|
SummaryReport = "summary"
|
|
|
|
tableFormat = "table"
|
|
jsonFormat = "json"
|
|
cycloneDXFormat = "cyclonedx"
|
|
|
|
workloadComponent = "workload"
|
|
infraComponent = "infra"
|
|
)
|
|
|
|
var (
|
|
roleWithMisconfig = report.Resource{
|
|
Namespace: "default",
|
|
Kind: "Role",
|
|
Name: "system::leader-locking-kube-controller-manager",
|
|
Results: types.Results{
|
|
{
|
|
Misconfigurations: []types.DetectedMisconfiguration{
|
|
{
|
|
ID: "ID100",
|
|
Status: types.StatusFailure,
|
|
Severity: "MEDIUM",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
apiseverPodWithMisconfigAndInfra = report.Resource{
|
|
Namespace: "kube-system",
|
|
Kind: "Pod",
|
|
Name: "kube-apiserver",
|
|
Results: types.Results{
|
|
{
|
|
Misconfigurations: []types.DetectedMisconfiguration{
|
|
{
|
|
ID: "KSV-ID100",
|
|
Status: types.StatusFailure,
|
|
Severity: "LOW",
|
|
},
|
|
{
|
|
ID: "KSV-ID101",
|
|
Status: types.StatusFailure,
|
|
Severity: "MEDIUM",
|
|
},
|
|
{
|
|
ID: "KSV-ID102",
|
|
Status: types.StatusFailure,
|
|
Severity: "HIGH",
|
|
},
|
|
|
|
{
|
|
ID: "KCV-ID100",
|
|
Status: types.StatusFailure,
|
|
Severity: "LOW",
|
|
},
|
|
{
|
|
ID: "KCV-ID101",
|
|
Status: types.StatusFailure,
|
|
Severity: "MEDIUM",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
deployLuaWithSecrets = report.Resource{
|
|
Namespace: "default",
|
|
Kind: "Deploy",
|
|
Name: "lua",
|
|
Results: types.Results{
|
|
{
|
|
Secrets: []ftypes.SecretFinding{
|
|
{
|
|
RuleID: "secret1",
|
|
Severity: "CRITICAL",
|
|
},
|
|
{
|
|
RuleID: "secret2",
|
|
Severity: "MEDIUM",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
deployOrionWithMisconfigs = report.Resource{
|
|
Namespace: "default",
|
|
Kind: "Deploy",
|
|
Name: "orion",
|
|
Results: types.Results{
|
|
{
|
|
Misconfigurations: []types.DetectedMisconfiguration{
|
|
{
|
|
ID: "ID100",
|
|
Status: types.StatusFailure,
|
|
Severity: "LOW",
|
|
},
|
|
{
|
|
ID: "ID101",
|
|
Status: types.StatusFailure,
|
|
Severity: "MEDIUM",
|
|
},
|
|
{
|
|
ID: "ID102",
|
|
Status: types.StatusFailure,
|
|
Severity: "HIGH",
|
|
},
|
|
{
|
|
ID: "ID103",
|
|
Status: types.StatusFailure,
|
|
Severity: "CRITICAL",
|
|
},
|
|
{
|
|
ID: "ID104",
|
|
Status: types.StatusFailure,
|
|
Severity: "UNKNOWN",
|
|
},
|
|
{
|
|
ID: "ID105",
|
|
Status: types.StatusFailure,
|
|
Severity: "LOW",
|
|
},
|
|
{
|
|
ID: "ID106",
|
|
Status: types.StatusFailure,
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
deployOrionWithVulns = report.Resource{
|
|
Namespace: "default",
|
|
Kind: "Deploy",
|
|
Name: "orion",
|
|
Results: types.Results{
|
|
{
|
|
Vulnerabilities: []types.DetectedVulnerability{
|
|
{
|
|
VulnerabilityID: "CVE-2022-1111",
|
|
Vulnerability: dbTypes.Vulnerability{Severity: "LOW"},
|
|
},
|
|
{
|
|
VulnerabilityID: "CVE-2022-2222",
|
|
Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"},
|
|
},
|
|
{
|
|
VulnerabilityID: "CVE-2022-3333",
|
|
Vulnerability: dbTypes.Vulnerability{Severity: "HIGH"},
|
|
},
|
|
{
|
|
VulnerabilityID: "CVE-2022-4444",
|
|
Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"},
|
|
},
|
|
{
|
|
VulnerabilityID: "CVE-2022-5555",
|
|
Vulnerability: dbTypes.Vulnerability{Severity: "UNKNOWN"},
|
|
},
|
|
{
|
|
VulnerabilityID: "CVE-2022-6666",
|
|
Vulnerability: dbTypes.Vulnerability{Severity: "CRITICAL"},
|
|
},
|
|
{
|
|
VulnerabilityID: "CVE-2022-7777",
|
|
Vulnerability: dbTypes.Vulnerability{Severity: "MEDIUM"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
func TestReportWrite_Summary(t *testing.T) {
|
|
allSeverities := []dbTypes.Severity{
|
|
dbTypes.SeverityUnknown,
|
|
dbTypes.SeverityLow,
|
|
dbTypes.SeverityMedium,
|
|
dbTypes.SeverityHigh,
|
|
dbTypes.SeverityCritical,
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
report report.Report
|
|
opt report.Option
|
|
scanners types.Scanners
|
|
components []string
|
|
severities []dbTypes.Severity
|
|
expectedOutput string
|
|
}{
|
|
{
|
|
name: "Only config, all serverities",
|
|
report: report.Report{
|
|
ClusterName: "test",
|
|
Resources: []report.Resource{deployOrionWithMisconfigs},
|
|
},
|
|
scanners: types.Scanners{types.MisconfigScanner},
|
|
components: []string{workloadComponent},
|
|
severities: allSeverities,
|
|
expectedOutput: `Summary Report for test
|
|
=======================
|
|
|
|
Workload Assessment
|
|
┌───────────┬──────────────┬───────────────────┐
|
|
│ Namespace │ Resource │ Misconfigurations │
|
|
│ │ ├───┬───┬───┬───┬───┤
|
|
│ │ │ C │ H │ M │ L │ U │
|
|
├───────────┼──────────────┼───┼───┼───┼───┼───┤
|
|
│ default │ Deploy/orion │ 1 │ 2 │ 1 │ 2 │ 1 │
|
|
└───────────┴──────────────┴───┴───┴───┴───┴───┘
|
|
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
|
|
},
|
|
{
|
|
name: "Only vuln, all serverities",
|
|
report: report.Report{
|
|
ClusterName: "test",
|
|
Resources: []report.Resource{deployOrionWithVulns},
|
|
},
|
|
scanners: types.Scanners{types.VulnerabilityScanner},
|
|
severities: allSeverities,
|
|
expectedOutput: `Summary Report for test
|
|
=======================
|
|
|
|
Workload Assessment
|
|
┌───────────┬──────────────┬───────────────────┐
|
|
│ Namespace │ Resource │ Vulnerabilities │
|
|
│ │ ├───┬───┬───┬───┬───┤
|
|
│ │ │ C │ H │ M │ L │ U │
|
|
├───────────┼──────────────┼───┼───┼───┼───┼───┤
|
|
│ default │ Deploy/orion │ 2 │ 1 │ 2 │ 1 │ 1 │
|
|
└───────────┴──────────────┴───┴───┴───┴───┴───┘
|
|
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
|
|
},
|
|
{
|
|
name: "Only rbac, all serverities",
|
|
report: report.Report{
|
|
ClusterName: "test",
|
|
Resources: []report.Resource{roleWithMisconfig},
|
|
},
|
|
scanners: types.Scanners{types.RBACScanner},
|
|
severities: allSeverities,
|
|
expectedOutput: `Summary Report for test
|
|
=======================
|
|
|
|
RBAC Assessment
|
|
┌───────────┬─────────────────────────────────────────────────────┬───────────────────┐
|
|
│ Namespace │ Resource │ RBAC Assessment │
|
|
│ │ ├───┬───┬───┬───┬───┤
|
|
│ │ │ C │ H │ M │ L │ U │
|
|
├───────────┼─────────────────────────────────────────────────────┼───┼───┼───┼───┼───┤
|
|
│ default │ Role/system::leader-locking-kube-controller-manager │ │ │ 1 │ │ │
|
|
└───────────┴─────────────────────────────────────────────────────┴───┴───┴───┴───┴───┘
|
|
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
|
|
},
|
|
{
|
|
name: "Only secret, all serverities",
|
|
report: report.Report{
|
|
ClusterName: "test",
|
|
Resources: []report.Resource{deployLuaWithSecrets},
|
|
},
|
|
scanners: types.Scanners{types.SecretScanner},
|
|
severities: allSeverities,
|
|
expectedOutput: `Summary Report for test
|
|
=======================
|
|
|
|
Workload Assessment
|
|
┌───────────┬────────────┬───────────────────┐
|
|
│ Namespace │ Resource │ Secrets │
|
|
│ │ ├───┬───┬───┬───┬───┤
|
|
│ │ │ C │ H │ M │ L │ U │
|
|
├───────────┼────────────┼───┼───┼───┼───┼───┤
|
|
│ default │ Deploy/lua │ 1 │ │ 1 │ │ │
|
|
└───────────┴────────────┴───┴───┴───┴───┴───┘
|
|
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
|
|
},
|
|
{
|
|
name: "apiserver, only infra and serverities",
|
|
report: report.Report{
|
|
ClusterName: "test",
|
|
Resources: []report.Resource{apiseverPodWithMisconfigAndInfra},
|
|
},
|
|
scanners: types.Scanners{types.MisconfigScanner},
|
|
components: []string{infraComponent},
|
|
severities: allSeverities,
|
|
expectedOutput: `Summary Report for test
|
|
=======================
|
|
|
|
Infra Assessment
|
|
┌─────────────┬────────────────────┬─────────────────────────────┐
|
|
│ Namespace │ Resource │ Kubernetes Infra Assessment │
|
|
│ │ ├─────┬─────┬─────┬─────┬─────┤
|
|
│ │ │ C │ H │ M │ L │ U │
|
|
├─────────────┼────────────────────┼─────┼─────┼─────┼─────┼─────┤
|
|
│ kube-system │ Pod/kube-apiserver │ │ │ 1 │ 1 │ │
|
|
└─────────────┴────────────────────┴─────┴─────┴─────┴─────┴─────┘
|
|
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
|
|
},
|
|
{
|
|
name: "apiserver, vuln,config,secret and serverities",
|
|
report: report.Report{
|
|
ClusterName: "test",
|
|
Resources: []report.Resource{apiseverPodWithMisconfigAndInfra},
|
|
},
|
|
scanners: types.Scanners{
|
|
types.VulnerabilityScanner,
|
|
types.MisconfigScanner,
|
|
types.SecretScanner,
|
|
},
|
|
components: []string{workloadComponent},
|
|
severities: allSeverities,
|
|
expectedOutput: `Summary Report for test
|
|
=======================
|
|
|
|
Workload Assessment
|
|
┌─────────────┬────────────────────┬───────────────────┬───────────────────┬───────────────────┐
|
|
│ Namespace │ Resource │ Vulnerabilities │ Misconfigurations │ Secrets │
|
|
│ │ ├───┬───┬───┬───┬───┼───┬───┬───┬───┬───┼───┬───┬───┬───┬───┤
|
|
│ │ │ C │ H │ M │ L │ U │ C │ H │ M │ L │ U │ C │ H │ M │ L │ U │
|
|
├─────────────┼────────────────────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
|
|
│ kube-system │ Pod/kube-apiserver │ │ │ │ │ │ │ 1 │ 1 │ 1 │ │ │ │ │ │ │
|
|
└─────────────┴────────────────────┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
|
|
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
|
|
},
|
|
{
|
|
name: "apiserver, all scanners and serverities",
|
|
report: report.Report{
|
|
ClusterName: "test",
|
|
Resources: []report.Resource{apiseverPodWithMisconfigAndInfra},
|
|
},
|
|
scanners: types.Scanners{
|
|
types.MisconfigScanner,
|
|
types.VulnerabilityScanner,
|
|
types.RBACScanner,
|
|
types.SecretScanner,
|
|
},
|
|
components: []string{
|
|
workloadComponent,
|
|
infraComponent,
|
|
},
|
|
severities: allSeverities,
|
|
expectedOutput: `Summary Report for test
|
|
=======================
|
|
|
|
Workload Assessment
|
|
┌─────────────┬────────────────────┬───────────────────┬───────────────────┬───────────────────┐
|
|
│ Namespace │ Resource │ Vulnerabilities │ Misconfigurations │ Secrets │
|
|
│ │ ├───┬───┬───┬───┬───┼───┬───┬───┬───┬───┼───┬───┬───┬───┬───┤
|
|
│ │ │ C │ H │ M │ L │ U │ C │ H │ M │ L │ U │ C │ H │ M │ L │ U │
|
|
├─────────────┼────────────────────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
|
|
│ kube-system │ Pod/kube-apiserver │ │ │ │ │ │ │ 1 │ 1 │ 1 │ │ │ │ │ │ │
|
|
└─────────────┴────────────────────┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
|
|
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN
|
|
|
|
|
|
Infra Assessment
|
|
┌─────────────┬────────────────────┬─────────────────────────────┐
|
|
│ Namespace │ Resource │ Kubernetes Infra Assessment │
|
|
│ │ ├─────┬─────┬─────┬─────┬─────┤
|
|
│ │ │ C │ H │ M │ L │ U │
|
|
├─────────────┼────────────────────┼─────┼─────┼─────┼─────┼─────┤
|
|
│ kube-system │ Pod/kube-apiserver │ │ │ 1 │ 1 │ │
|
|
└─────────────┴────────────────────┴─────┴─────┴─────┴─────┴─────┘
|
|
Severities: C=CRITICAL H=HIGH M=MEDIUM L=LOW U=UNKNOWN`,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
output := bytes.Buffer{}
|
|
|
|
opt := report.Option{
|
|
Format: "table",
|
|
Report: "summary",
|
|
Output: &output,
|
|
Scanners: tc.scanners,
|
|
Severities: tc.severities,
|
|
Components: tc.components,
|
|
}
|
|
|
|
Write(tc.report, opt)
|
|
|
|
assert.Equal(t, tc.expectedOutput, stripAnsi(output.String()), tc.name)
|
|
})
|
|
}
|
|
}
|
|
|
|
const ansi = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"
|
|
|
|
var ansiRegexp = regexp.MustCompile(ansi)
|
|
|
|
func stripAnsi(str string) string {
|
|
return strings.TrimSpace(ansiRegexp.ReplaceAllString(str, ""))
|
|
}
|