mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-20 22:33:53 -08:00
Co-authored-by: afdesk <work@afdesk.com> Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
257 lines
7.3 KiB
Go
257 lines
7.3 KiB
Go
package report
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/aquasecurity/trivy/pkg/flag"
|
|
"github.com/aquasecurity/trivy/pkg/types"
|
|
)
|
|
|
|
var (
|
|
deployOrionWithMisconfigs = Resource{
|
|
Namespace: "default",
|
|
Kind: "Deploy",
|
|
Name: "orion",
|
|
Results: types.Results{
|
|
{Misconfigurations: []types.DetectedMisconfiguration{{ID: "ID100", Status: types.StatusFailure}}},
|
|
},
|
|
}
|
|
|
|
deployOrionWithVulns = Resource{
|
|
Namespace: "default",
|
|
Kind: "Deploy",
|
|
Name: "orion",
|
|
Results: types.Results{
|
|
{Vulnerabilities: []types.DetectedVulnerability{{VulnerabilityID: "CVE-2020-8888"}}},
|
|
},
|
|
}
|
|
|
|
deployOrionWithBothVulnsAndMisconfigs = Resource{
|
|
Namespace: "default",
|
|
Kind: "Deploy",
|
|
Name: "orion",
|
|
Results: types.Results{
|
|
{Misconfigurations: []types.DetectedMisconfiguration{{ID: "ID100", Status: types.StatusFailure}}},
|
|
{Vulnerabilities: []types.DetectedVulnerability{{VulnerabilityID: "CVE-2020-8888"}}},
|
|
},
|
|
}
|
|
|
|
cronjobHelloWithVulns = Resource{
|
|
Namespace: "default",
|
|
Kind: "Cronjob",
|
|
Name: "hello",
|
|
Results: types.Results{
|
|
{Vulnerabilities: []types.DetectedVulnerability{{VulnerabilityID: "CVE-2020-9999"}}},
|
|
},
|
|
}
|
|
|
|
podPrometheusWithMisconfigs = Resource{
|
|
Namespace: "default",
|
|
Kind: "Pod",
|
|
Name: "prometheus",
|
|
Results: types.Results{
|
|
{Misconfigurations: []types.DetectedMisconfiguration{{ID: "ID100"}}},
|
|
},
|
|
}
|
|
)
|
|
|
|
func TestReport_consolidate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
report Report
|
|
expectedFindings map[string]Resource
|
|
}{
|
|
{
|
|
name: "report with both misconfigs and vulnerabilities",
|
|
report: Report{
|
|
Vulnerabilities: []Resource{deployOrionWithVulns, cronjobHelloWithVulns},
|
|
Misconfigurations: []Resource{deployOrionWithMisconfigs, podPrometheusWithMisconfigs},
|
|
},
|
|
expectedFindings: map[string]Resource{
|
|
"default/deploy/orion": deployOrionWithBothVulnsAndMisconfigs,
|
|
"default/cronjob/hello": cronjobHelloWithVulns,
|
|
"default/pod/prometheus": podPrometheusWithMisconfigs,
|
|
},
|
|
},
|
|
{
|
|
name: "report with only misconfigurations",
|
|
report: Report{
|
|
Misconfigurations: []Resource{deployOrionWithMisconfigs, podPrometheusWithMisconfigs},
|
|
},
|
|
expectedFindings: map[string]Resource{
|
|
"default/deploy/orion": deployOrionWithMisconfigs,
|
|
"default/pod/prometheus": podPrometheusWithMisconfigs,
|
|
},
|
|
},
|
|
{
|
|
name: "report with only vulnerabilities",
|
|
report: Report{
|
|
Vulnerabilities: []Resource{deployOrionWithVulns, cronjobHelloWithVulns},
|
|
},
|
|
expectedFindings: map[string]Resource{
|
|
"default/deploy/orion": deployOrionWithVulns,
|
|
"default/cronjob/hello": cronjobHelloWithVulns,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
consolidateReport := tt.report.consolidate()
|
|
for _, f := range consolidateReport.Findings {
|
|
key := f.fullname()
|
|
|
|
expected, found := tt.expectedFindings[key]
|
|
if !found {
|
|
t.Errorf("key not found: %s", key)
|
|
}
|
|
|
|
assert.Equal(t, expected, f)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestResource_fullname(t *testing.T) {
|
|
tests := []struct {
|
|
expected string
|
|
resource Resource
|
|
}{
|
|
{"default/deploy/orion", deployOrionWithBothVulnsAndMisconfigs},
|
|
{"default/deploy/orion", deployOrionWithMisconfigs},
|
|
{"default/cronjob/hello", cronjobHelloWithVulns},
|
|
{"default/pod/prometheus", podPrometheusWithMisconfigs},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.expected, func(t *testing.T) {
|
|
assert.Equal(t, tt.expected, tt.resource.fullname())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestResourceFailed(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
report Report
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "report with both misconfigs and vulnerabilities",
|
|
report: Report{
|
|
Vulnerabilities: []Resource{deployOrionWithVulns, cronjobHelloWithVulns},
|
|
Misconfigurations: []Resource{deployOrionWithMisconfigs, podPrometheusWithMisconfigs},
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "report with only misconfigurations",
|
|
report: Report{
|
|
Misconfigurations: []Resource{deployOrionWithMisconfigs, podPrometheusWithMisconfigs},
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "report with only vulnerabilities",
|
|
report: Report{
|
|
Vulnerabilities: []Resource{deployOrionWithVulns, cronjobHelloWithVulns},
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "report without vulnerabilities and misconfigurations",
|
|
report: Report{},
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert.Equal(t, tt.expected, tt.report.Failed())
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_rbacResource(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
misConfig Resource
|
|
want bool
|
|
}{
|
|
{
|
|
name: "rbac Role resources",
|
|
misConfig: Resource{Kind: "Role"},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "rbac ClusterRole resources",
|
|
misConfig: Resource{Kind: "ClusterRole"},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "rbac RoleBinding resources",
|
|
misConfig: Resource{Kind: "RoleBinding"},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "rbac ClusterRoleBinding resources",
|
|
misConfig: Resource{Kind: "ClusterRoleBinding"},
|
|
want: true,
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
got := rbacResource(test.misConfig)
|
|
assert.Equal(t, test.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_separateMisConfigRoleAssessment(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
k8sReport Report
|
|
opts flag.ScanOptions
|
|
wantRbacReport Report
|
|
wantMisConfigReport Report
|
|
}{
|
|
{
|
|
name: "Role and Deployment Reports",
|
|
k8sReport: Report{Misconfigurations: []Resource{{Kind: "Role"}, {Kind: "Deployment"}}},
|
|
opts: flag.ScanOptions{SecurityChecks: []string{"config", "rbac"}},
|
|
wantRbacReport: Report{Misconfigurations: []Resource{{Kind: "Role"}}},
|
|
wantMisConfigReport: Report{Misconfigurations: []Resource{{Kind: "Deployment"}}},
|
|
},
|
|
{
|
|
name: "Role Report Only",
|
|
k8sReport: Report{Misconfigurations: []Resource{{Kind: "Role"}, {Kind: "Deployment"}}},
|
|
opts: flag.ScanOptions{SecurityChecks: []string{"rbac"}},
|
|
wantRbacReport: Report{Misconfigurations: []Resource{{Kind: "Role"}}},
|
|
wantMisConfigReport: Report{Misconfigurations: []Resource{}},
|
|
},
|
|
{
|
|
name: "Deployment Report Only",
|
|
k8sReport: Report{Misconfigurations: []Resource{{Kind: "Role"}, {Kind: "Deployment"}}},
|
|
opts: flag.ScanOptions{SecurityChecks: []string{"config"}},
|
|
wantRbacReport: Report{Misconfigurations: []Resource{}},
|
|
wantMisConfigReport: Report{Misconfigurations: []Resource{{Kind: "Deployment"}}},
|
|
},
|
|
{
|
|
name: "No Deployment & No Role Reports",
|
|
k8sReport: Report{Misconfigurations: []Resource{{Kind: "Role"}, {Kind: "Deployment"}}},
|
|
opts: flag.ScanOptions{SecurityChecks: []string{"vuln"}},
|
|
wantRbacReport: Report{Misconfigurations: []Resource{}},
|
|
wantMisConfigReport: Report{Misconfigurations: []Resource{}},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
misConfig, rbac := separateMisConfigRoleAssessment(tt.k8sReport, tt.opts.SecurityChecks)
|
|
assert.Equal(t, len(tt.wantMisConfigReport.Misconfigurations), len(misConfig.Misconfigurations))
|
|
assert.Equal(t, len(tt.wantRbacReport.Misconfigurations), len(rbac.Misconfigurations))
|
|
})
|
|
}
|
|
}
|