Skip to content
This repository was archived by the owner on Oct 30, 2024. It is now read-only.

refactors sarif test #469

Merged
merged 5 commits into from
Aug 24, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions internal/sarif/fixtures/apparmor-invalid.yaml

This file was deleted.

11 changes: 0 additions & 11 deletions internal/sarif/fixtures/apparmor-valid.yaml

This file was deleted.

21 changes: 0 additions & 21 deletions internal/sarif/fixtures/capabilities-added.yaml

This file was deleted.

16 changes: 0 additions & 16 deletions internal/sarif/fixtures/image-tag-present.yaml

This file was deleted.

8 changes: 0 additions & 8 deletions internal/sarif/fixtures/limits-nil.yaml

This file was deleted.

94 changes: 46 additions & 48 deletions internal/sarif/sarif_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package sarif

import (
"os"
"path/filepath"
"testing"

"github.com/Shopify/kubeaudit"
Expand All @@ -15,66 +13,82 @@ import (
)

func TestCreateWithResults(t *testing.T) {
capabilitiesAuditable := capabilities.New(capabilities.Config{})
apparmorAuditable := apparmor.New()
imageAuditable := image.New(image.Config{Image: "scratch:1.5"})
limitsAuditable, _ := limits.New(limits.Config{})

cases := []struct {
file string
auditors []kubeaudit.Auditable
description string
auditResults []*kubeaudit.AuditResult
expectedRule string
expectedErrorLevel string
expectedMessage string
expectedURI string
expectedFilePath string
}{
{
"apparmor-invalid.yaml",
[]kubeaudit.Auditable{apparmorAuditable},
"apparmor invalid",
[]*kubeaudit.AuditResult{{
Auditor: apparmor.Name,
Rule: apparmor.AppArmorInvalidAnnotation,
Severity: kubeaudit.Error,
Message: "AppArmor annotation key refers to a container that doesn't exist",
FilePath: "apparmorPath",
}},
apparmor.AppArmorInvalidAnnotation,
"error",
"AppArmor annotation key refers to a container that doesn't exist",
"https://github.com/Shopify/kubeaudit/blob/main/docs/auditors/apparmor.md",
"apparmorPath",
},
{
"capabilities-added.yaml",
[]kubeaudit.Auditable{capabilitiesAuditable},
"capabilities added",
[]*kubeaudit.AuditResult{{
Auditor: capabilities.Name,
Rule: capabilities.CapabilityAdded,
Severity: kubeaudit.Error,
Message: "It should be removed from the capability add list",
FilePath: "capsPath",
}},
capabilities.CapabilityAdded,
"error",
"It should be removed from the capability add list",
"https://github.com/Shopify/kubeaudit/blob/main/docs/auditors/capabilities.md",
"capsPath",
},
{
"image-tag-present.yaml",
[]kubeaudit.Auditable{imageAuditable},
"image tag is present",
[]*kubeaudit.AuditResult{{
Auditor: image.Name,
Rule: image.ImageCorrect,
Severity: kubeaudit.Info,
Message: "Image tag is correct",
FilePath: "imagePath",
}},
image.ImageCorrect,
"note",
"Image tag is correct",
"https://github.com/Shopify/kubeaudit/blob/main/docs/auditors/image.md",
"imagePath",
},
{
"limits-nil.yaml",
[]kubeaudit.Auditable{limitsAuditable},
"limits is nil",
[]*kubeaudit.AuditResult{{
Auditor: limits.Name,
Rule: limits.LimitsNotSet,
Severity: kubeaudit.Warn,
Message: "Resource limits not set",
FilePath: "limitsPath",
}},
limits.LimitsNotSet,
"warning",
"Resource limits not set",
"https://github.com/Shopify/kubeaudit/blob/main/docs/auditors/limits.md",
"limitsPath",
},
}

for _, tc := range cases {
t.Run(tc.file, func(t *testing.T) {
fixture := filepath.Join("fixtures", tc.file)
auditor, err := kubeaudit.New(tc.auditors)
require.NoError(t, err)

manifest, openErr := os.Open(fixture)
require.NoError(t, openErr)

defer manifest.Close()

kubeAuditReport, err := auditor.AuditManifest(fixture, manifest)
require.NoError(t, err)
t.Run(tc.description, func(t *testing.T) {
kubeAuditReport := kubeaudit.NewReport([]kubeaudit.Result{&kubeaudit.WorkloadResult{
AuditResults: tc.auditResults,
}})

sarifReport, err := Create(kubeAuditReport)
require.NoError(t, err)
Expand All @@ -87,7 +101,7 @@ func TestCreateWithResults(t *testing.T) {

var ruleNames []string

// check for rules occurrences
//check for rules occurrences
for _, sarifRule := range sarifReport.Runs[0].Tool.Driver.Rules {
assert.Equal(t, []string{
"security",
Expand All @@ -106,32 +120,16 @@ func TestCreateWithResults(t *testing.T) {
assert.Contains(t, ruleNames, *sarifResult.RuleID)
assert.Equal(t, tc.expectedErrorLevel, *sarifResult.Level)
assert.Contains(t, *sarifResult.Message.Text, tc.expectedMessage)
assert.Contains(t, "sarif/fixtures/"+tc.file, *sarifResult.Locations[0].PhysicalLocation.ArtifactLocation.URI)
assert.Contains(t, tc.expectedFilePath, *sarifResult.Locations[0].PhysicalLocation.ArtifactLocation.URI)
}
})
}
}

func TestCreateWithNoResults(t *testing.T) {
apparmorAuditable := apparmor.New()

fixture := filepath.Join("fixtures", "apparmor-valid.yaml")
auditor, err := kubeaudit.New([]kubeaudit.Auditable{apparmorAuditable})
sarifReport, err := Create(&kubeaudit.Report{})
require.NoError(t, err)

manifest, openErr := os.Open(fixture)
require.NoError(t, openErr)

defer manifest.Close()

kubeAuditReport, err := auditor.AuditManifest(fixture, manifest)
require.NoError(t, err)

sarifReport, err := Create(kubeAuditReport)
require.NoError(t, err)

require.NotEmpty(t, *sarifReport.Runs[0])

// verify that the rules are only added as per report findings
assert.Len(t, sarifReport.Runs[0].Tool.Driver.Rules, 0)
}
20 changes: 12 additions & 8 deletions kubeaudit.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func (a *Kubeaudit) AuditManifest(manifestPath string, manifest io.Reader) (*Rep
}
}

report := &Report{results: results}
report := NewReport(results)

return report, nil
}
Expand All @@ -193,7 +193,7 @@ func (a *Kubeaudit) AuditCluster(options AuditOptions) (*Report, error) {
return nil, err
}

report := &Report{results: results}
report := NewReport(results)

return report, nil
}
Expand All @@ -216,7 +216,7 @@ func (a *Kubeaudit) AuditLocal(configpath string, context string, options AuditO
return nil, err
}

report := &Report{results: results}
report := NewReport(results)

return report, nil
}
Expand All @@ -226,6 +226,10 @@ type Report struct {
results []Result
}

func NewReport(results []Result) *Report {
return &Report{results}
}

// RawResults returns all of the results for each Kubernetes resource, including ones that had no audit results.
// Generally, you will want to use Results() instead.
func (r *Report) RawResults() []Result {
Expand All @@ -234,8 +238,8 @@ func (r *Report) RawResults() []Result {

// Results returns the audit results for each Kubernetes resource
func (r *Report) Results() []Result {
results := make([]Result, 0, len(r.results))
for _, result := range r.results {
results := make([]Result, 0, len(r.RawResults()))
for _, result := range r.RawResults() {
if len(result.GetAuditResults()) > 0 {
results = append(results, result)
}
Expand All @@ -246,15 +250,15 @@ func (r *Report) Results() []Result {
// ResultsWithMinSeverity returns the audit results for each Kubernetes resource with a minimum severity
func (r *Report) ResultsWithMinSeverity(minSeverity SeverityLevel) []Result {
var results []Result
for _, result := range r.results {
for _, result := range r.RawResults() {
var filteredAuditResults []*AuditResult
for _, auditResult := range result.GetAuditResults() {
if auditResult.Severity >= minSeverity {
filteredAuditResults = append(filteredAuditResults, auditResult)
}
}
if len(filteredAuditResults) > 0 {
results = append(results, &workloadResult{
results = append(results, &WorkloadResult{
Resource: result.GetResource(),
AuditResults: filteredAuditResults,
})
Expand Down Expand Up @@ -284,7 +288,7 @@ func (r *Report) PrintResults(printOptions ...PrintOption) {
// Fix tries to automatically patch any security concerns and writes the resulting manifest to the provided writer.
// Only applies when audit was performed on a manifest (not local or cluster)
func (r *Report) Fix(writer io.Writer) error {
fixed, err := fix(r.results)
fixed, err := fix(r.RawResults())
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions result.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ type PendingFix interface {
type Metadata = map[string]string

// Implements Result
type workloadResult struct {
type WorkloadResult struct {
Resource KubeResource
AuditResults []*AuditResult
}

func (wlResult *workloadResult) GetResource() KubeResource {
func (wlResult *WorkloadResult) GetResource() KubeResource {
return wlResult.Resource
}

func (wlResult *workloadResult) GetAuditResults() []*AuditResult {
func (wlResult *WorkloadResult) GetAuditResults() []*AuditResult {
return wlResult.AuditResults
}
2 changes: 1 addition & 1 deletion util.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func auditResources(resources []KubeResource, auditable []Auditable) ([]Result,
}

func auditResource(resource KubeResource, resources []KubeResource, auditables []Auditable) (Result, error) {
result := &workloadResult{
result := &WorkloadResult{
Resource: resource,
AuditResults: []*AuditResult{},
}
Expand Down
4 changes: 2 additions & 2 deletions util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type logEntry struct {
func TestPrintResults(t *testing.T) {
report := Report{
results: []Result{
&workloadResult{
&WorkloadResult{
AuditResults: []*AuditResult{
newTestAuditResult(Error),
newTestAuditResult(Warn),
Expand Down Expand Up @@ -74,7 +74,7 @@ func TestLogAuditResult(t *testing.T) {
auditResult := newTestAuditResult(severity)
report := &Report{
results: []Result{
&workloadResult{
&WorkloadResult{
AuditResults: []*AuditResult{
auditResult,
},
Expand Down