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

Commit

Permalink
adds violations to rules mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
dani-santos-code committed Jul 20, 2022
1 parent b0915a8 commit 44e7e36
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 59 deletions.
80 changes: 80 additions & 0 deletions internal/sarif/rules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package sarif

import (
"github.com/Shopify/kubeaudit/auditors/apparmor"
"github.com/Shopify/kubeaudit/auditors/asat"
"github.com/Shopify/kubeaudit/auditors/capabilities"
"github.com/Shopify/kubeaudit/auditors/deprecatedapis"
"github.com/Shopify/kubeaudit/auditors/hostns"
"github.com/Shopify/kubeaudit/auditors/image"
"github.com/Shopify/kubeaudit/auditors/limits"
"github.com/Shopify/kubeaudit/auditors/mounts"
"github.com/Shopify/kubeaudit/auditors/netpols"
"github.com/Shopify/kubeaudit/auditors/nonroot"
"github.com/Shopify/kubeaudit/auditors/privesc"
"github.com/Shopify/kubeaudit/auditors/privileged"
"github.com/Shopify/kubeaudit/auditors/rootfs"
"github.com/Shopify/kubeaudit/auditors/seccomp"
)

var allAuditors = map[string]string{
apparmor.Name: "Finds containers that do not have AppArmor enabled",
asat.Name: "Finds containers where the deprecated SA field is used or with a mounted default SA",
capabilities.Name: "Finds containers that do not drop the recommended capabilities or add new ones",
deprecatedapis.Name: "Finds any resource defined with a deprecated API version.",
hostns.Name: "Finds containers that have HostPID, HostIPC or HostNetwork enabled",
image.Name: "Finds containers which do not use the desired version of an image (via the tag) or use an image without a tag",
limits.Name: "Finds containers which exceed the specified CPU and memory limits or do not specify any",
mounts.Name: "Finds containers that have sensitive host paths mounted",
netpols.Name: "Finds namespaces that do not have a default-deny network policy",
nonroot.Name: "Finds containers allowed to run as root",
privesc.Name: "Finds containers that allow privilege escalation",
privileged.Name: "Finds containers running as privileged",
rootfs.Name: "Finds containers which do not have a read-only filesystem",
seccomp.Name: "Finds containers running without seccomp",
}

var violationsToRules = map[string]string{
apparmor.AppArmorAnnotationMissing: apparmor.Name,
apparmor.AppArmorDisabled: apparmor.Name,
apparmor.AppArmorInvalidAnnotation: apparmor.Name,
asat.AutomountServiceAccountTokenDeprecated: asat.Name,
asat.AutomountServiceAccountTokenTrueAndDefaultSA: asat.Name,
capabilities.CapabilityAdded: capabilities.Name,
capabilities.CapabilityOrSecurityContextMissing: capabilities.Name,
capabilities.CapabilityShouldDropAll: capabilities.Name,
deprecatedapis.DeprecatedAPIUsed: deprecatedapis.Name,
hostns.NamespaceHostIPCTrue: hostns.Name,
hostns.NamespaceHostNetworkTrue: hostns.Name,
hostns.NamespaceHostPIDTrue: hostns.Name,
image.ImageCorrect: image.Name,
image.ImageTagIncorrect: image.Name,
image.ImageTagMissing: image.Name,
limits.LimitsCPUExceeded: limits.Name,
limits.LimitsCPUNotSet: limits.Name,
limits.LimitsMemoryExceeded: limits.Name,
limits.LimitsMemoryNotSet: limits.Name,
limits.LimitsNotSet: limits.Name,
mounts.SensitivePathsMounted: mounts.Name,
netpols.MissingDefaultDenyIngressAndEgressNetworkPolicy: netpols.Name,
netpols.MissingDefaultDenyIngressNetworkPolicy: netpols.Name,
netpols.MissingDefaultDenyEgressNetworkPolicy: netpols.Name,
netpols.AllowAllIngressNetworkPolicyExists: netpols.Name,
netpols.AllowAllEgressNetworkPolicyExists: netpols.Name,
nonroot.RunAsUserCSCRoot: nonroot.Name,
nonroot.RunAsUserPSCRoot: nonroot.Name,
nonroot.RunAsNonRootCSCFalse: nonroot.Name,
nonroot.RunAsNonRootPSCNilCSCNil: nonroot.Name,
nonroot.RunAsNonRootPSCFalseCSCNil: nonroot.Name,
privesc.AllowPrivilegeEscalationNil: privesc.Name,
privesc.AllowPrivilegeEscalationTrue: privesc.Name,
privileged.PrivilegedTrue: privileged.Name,
privileged.PrivilegedNil: privileged.Name,
rootfs.ReadOnlyRootFilesystemFalse: rootfs.Name,
rootfs.ReadOnlyRootFilesystemNil: rootfs.Name,
seccomp.SeccompAnnotationMissing: seccomp.Name,
seccomp.SeccompDeprecatedPod: seccomp.Name,
seccomp.SeccompDisabledPod: seccomp.Name,
seccomp.SeccompDeprecatedContainer: seccomp.Name,
seccomp.SeccompDisabledContainer: seccomp.Name,
}
92 changes: 92 additions & 0 deletions internal/sarif/rules_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package sarif

import (
"testing"

"github.com/Shopify/kubeaudit/auditors/all"
"github.com/stretchr/testify/assert"
)

func TestAuditorsLength(t *testing.T) {
// if new auditors are created
// make sure they're added with a matching description
assert.Len(t, allAuditors, len(all.AuditorNames))
}

func TestViolationToRules(t *testing.T) {
cases := []struct {
auditorName string
expectedCount int
}{
{
"apparmor",
3,
},
{
"asat",
2,
},
{
"capabilities",
3,
},
{
"deprecatedapis",
1,
},
{
"hostns",
3,
},
{
"image",
3,
},
{
"limits",
5,
},
{
"mounts",
1,
},
{
"netpols",
5,
},
{
"nonroot",
5,
},
{
"privesc",
2,
},
{
"privileged",
2,
},
{
"rootfs",
2,
},
{
"seccomp",
5,
},
}

assert.Len(t, cases, len(all.AuditorNames))

for _, c := range cases {
var totalCount int

for _, v := range violationsToRules {
if v == c.auditorName {
totalCount += 1
}
}

assert.Equal(t, c.expectedCount, totalCount)
}
}
38 changes: 4 additions & 34 deletions internal/sarif/sarif.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,10 @@ import (
"strings"

"github.com/Shopify/kubeaudit"
"github.com/Shopify/kubeaudit/auditors/apparmor"
"github.com/Shopify/kubeaudit/auditors/asat"
"github.com/Shopify/kubeaudit/auditors/capabilities"
"github.com/Shopify/kubeaudit/auditors/deprecatedapis"
"github.com/Shopify/kubeaudit/auditors/hostns"
"github.com/Shopify/kubeaudit/auditors/image"
"github.com/Shopify/kubeaudit/auditors/limits"
"github.com/Shopify/kubeaudit/auditors/mounts"
"github.com/Shopify/kubeaudit/auditors/netpols"
"github.com/Shopify/kubeaudit/auditors/nonroot"
"github.com/Shopify/kubeaudit/auditors/privesc"
"github.com/Shopify/kubeaudit/auditors/privileged"
"github.com/Shopify/kubeaudit/auditors/rootfs"
"github.com/Shopify/kubeaudit/auditors/seccomp"
"github.com/owenrumney/go-sarif/v2/sarif"
"github.com/xeipuuv/gojsonschema"
)

var Auditors = map[string]string{
apparmor.Name: "Finds containers that do not have AppArmor enabled",
asat.Name: "Finds containers where the deprecated SA field is used or with a mounted default SA",
capabilities.Name: "Finds containers that do not drop the recommended capabilities or add new ones",
deprecatedapis.Name: "Finds any resource defined with a deprecated API version.",
hostns.Name: "Finds containers that have HostPID, HostIPC or HostNetwork enabled",
image.Name: "Finds containers which do not use the desired version of an image (via the tag) or use an image without a tag",
limits.Name: "Finds containers which exceed the specified CPU and memory limits or do not specify any",
mounts.Name: "Finds containers that have sensitive host paths mounted",
netpols.Name: "Finds namespaces that do not have a default-deny network policy",
nonroot.Name: "Finds containers allowed to run as root",
privesc.Name: "Finds containers that allow privilege escalation",
privileged.Name: "Finds containers running as privileged",
rootfs.Name: "Finds containers which do not have a read-only filesystem",
seccomp.Name: "Finds containers running without seccomp",
}

// Create generates new sarif Report or returns an error
func Create(kubeauditReport *kubeaudit.Report) (*sarif.Report, error) {
// create a new report object
Expand All @@ -65,14 +34,15 @@ func Create(kubeauditReport *kubeaudit.Report) (*sarif.Report, error) {
for _, result := range results {
severityLevel := result.Severity.String()
auditor := strings.ToLower(result.Auditor)
ruleID := strings.ToLower(result.Rule)

var docsURL string
if strings.Contains(ruleID, auditor) {

auditor, ok := violationsToRules[result.Rule]
if ok {
docsURL = "https://github.com/Shopify/kubeaudit/blob/main/docs/auditors/" + auditor + ".md"
}

helpMessage := fmt.Sprintf("**Type**: kubernetes\n**Docs**: %s\n**Description:** %s", docsURL, Auditors[auditor])
helpMessage := fmt.Sprintf("**Type**: kubernetes\n**Docs**: %s\n**Description:** %s", docsURL, allAuditors[auditor])

// we only add rules to the report based on the result findings
run.AddRule(result.Rule).
Expand Down
19 changes: 7 additions & 12 deletions internal/sarif/sarif_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestCreate(t *testing.T) {
expectedRule string
expectedErrorLevel string
expectedMessage string
expectedURI string
}{
{
"apparmor-invalid.yaml",
Expand All @@ -35,6 +36,7 @@ func TestCreate(t *testing.T) {
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",
},
{
"capabilities-added.yaml",
Expand All @@ -43,6 +45,7 @@ func TestCreate(t *testing.T) {
capabilities.CapabilityAdded,
"error",
"It should be removed from the capability add list",
"https://github.com/Shopify/kubeaudit/blob/main/docs/auditors/capabilities.md",
},
{
"image-tag-present.yaml",
Expand All @@ -51,6 +54,7 @@ func TestCreate(t *testing.T) {
image.ImageCorrect,
"note",
"Image tag is correct",
"https://github.com/Shopify/kubeaudit/blob/main/docs/auditors/image.md",
},
}

Expand All @@ -65,17 +69,6 @@ func TestCreate(t *testing.T) {
kubeAuditReport, err := auditor.AuditManifest(fixture, manifest)
require.NoError(t, err)

// we're only appending sarif to the path here for testing purposes
// this allows us to visualize the sarif output preview correctly
for _, reportResult := range kubeAuditReport.Results() {
r := reportResult.GetAuditResults()

for _, auditResult := range r {
auditResult.FilePath = filepath.Join("sarif/", auditResult.FilePath)
}

}

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

Expand All @@ -95,13 +88,15 @@ func TestCreate(t *testing.T) {
})

ruleNames = append(ruleNames, sarifRule.ID)

assert.Equal(t, tc.expectedURI, *sarifRule.Help.Text)
}

for _, sarifResult := range sarifReport.Runs[0].Results {
assert.Contains(t, ruleNames, *sarifResult.RuleID)
assert.Equal(t, tc.expectedErrorLevel, *sarifResult.Level)
assert.Contains(t, *sarifResult.Message.Text, tc.expectedMessage)
assert.Equal(t, "sarif/fixtures/"+tc.file, *sarifResult.Locations[0].PhysicalLocation.ArtifactLocation.URI)
assert.Contains(t, *sarifResult.Locations[0].PhysicalLocation.ArtifactLocation.URI, "sarif/fixtures/"+tc.file)
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion kubeaudit.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ import (
"fmt"
"io"
"io/ioutil"
"path/filepath"

"github.com/Shopify/kubeaudit/internal/k8sinternal"
"github.com/Shopify/kubeaudit/pkg/k8s"
Expand Down Expand Up @@ -157,7 +158,12 @@ func (a *Kubeaudit) AuditManifest(manifestPath string, manifest io.Reader) (*Rep
for _, result := range results {
auditResults := result.GetAuditResults()
for _, ar := range auditResults {
ar.FilePath = manifestPath
path, err := filepath.Abs(manifestPath)
if err != nil {
return nil, err
}

ar.FilePath = path
}
}

Expand Down
12 changes: 0 additions & 12 deletions profile.out

This file was deleted.

0 comments on commit 44e7e36

Please sign in to comment.