Skip to content

Commit

Permalink
Add priority class check, some test infra (#342)
Browse files Browse the repository at this point in the history
* add check for priority-class

* add test message

* lint
  • Loading branch information
rbren authored Jun 22, 2020
1 parent cea0ca7 commit b4e3d40
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 28 deletions.
9 changes: 9 additions & 0 deletions checks/priorityClassNotSet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
successMessage: Priority class has been set
failureMessage: Priority class should be set
category: Security
target: Pod
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
required:
- priorityClassName
1 change: 1 addition & 0 deletions examples/config-full.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
checks:
# reliability
multipleReplicasForDeployment: warning
priorityClassNotSet: warning
# resources
cpuRequestsMissing: warning
cpuLimitsMissing: warning
Expand Down
1 change: 1 addition & 0 deletions examples/config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
checks:
# reliability
multipleReplicasForDeployment: ignore
priorityClassNotSet: ignore
# resources
cpuRequestsMissing: warning
cpuLimitsMissing: warning
Expand Down
65 changes: 37 additions & 28 deletions pkg/kube/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,40 @@ func addResourcesFromYaml(contents string, resources *ResourceProvider) error {
return nil
}

// GetWorkloadFromBytes parses a GenericWorkload
func GetWorkloadFromBytes(contentBytes []byte) (*GenericWorkload, error) {
yamlNode := make(map[string]interface{})
err := yaml.Unmarshal(contentBytes, &yamlNode)
if err != nil {
logrus.Errorf("Invalid YAML: %s", string(contentBytes))
return nil, err
}
finalDoc := make(map[string]interface{})
finalDoc["metadata"] = yamlNode["metadata"]
finalDoc["apiVersion"] = "v1"
finalDoc["kind"] = "Pod"
podSpec := GetPodSpec(yamlNode)
if podSpec == nil {
return nil, nil
}
finalDoc["spec"] = podSpec
marshaledYaml, err := yaml.Marshal(finalDoc)
if err != nil {
logrus.Errorf("Could not marshal yaml: %v", err)
return nil, err
}
decoder := k8sYaml.NewYAMLOrJSONDecoder(bytes.NewReader(marshaledYaml), 1000)
pod := corev1.Pod{}
err = decoder.Decode(&pod)
newController, err := NewGenericWorkloadFromPod(pod, yamlNode)

if err != nil {
return nil, err
}
newController.Kind = yamlNode["kind"].(string)
return &newController, nil
}

func addResourceFromString(contents string, resources *ResourceProvider) error {
contentBytes := []byte(contents)
decoder := k8sYaml.NewYAMLOrJSONDecoder(bytes.NewReader(contentBytes), 1000)
Expand Down Expand Up @@ -268,36 +302,11 @@ func addResourceFromString(contents string, resources *ResourceProvider) error {
}
resources.Controllers = append(resources.Controllers, workload)
} else {
yamlNode := make(map[string]interface{})
err = yaml.Unmarshal(contentBytes, &yamlNode)
if err != nil {
logrus.Errorf("Invalid YAML: %s", string(contents))
return err
}
finalDoc := make(map[string]interface{})
finalDoc["metadata"] = yamlNode["metadata"]
finalDoc["apiVersion"] = "v1"
finalDoc["kind"] = "Pod"
podSpec := GetPodSpec(yamlNode)
if podSpec == nil {
return nil
}
finalDoc["spec"] = podSpec
marshaledYaml, err := yaml.Marshal(finalDoc)
if err != nil {
logrus.Errorf("Could not marshal yaml: %v", err)
return err
}
decoder := k8sYaml.NewYAMLOrJSONDecoder(bytes.NewReader(marshaledYaml), 1000)
pod := corev1.Pod{}
err = decoder.Decode(&pod)
newController, err := NewGenericWorkloadFromPod(pod, yamlNode)

if err != nil {
newController, err := GetWorkloadFromBytes(contentBytes)
if err != nil || newController == nil {
return err
}
newController.Kind = resource.Kind
resources.Controllers = append(resources.Controllers, newController)
resources.Controllers = append(resources.Controllers, *newController)
}
return err
}
1 change: 1 addition & 0 deletions pkg/validator/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ var (
"privilegeEscalationAllowed",
"dangerousCapabilities",
"insecureCapabilities",
"priorityClassNotSet",
}
)

Expand Down
11 changes: 11 additions & 0 deletions test/checks/priorityClassNotSet/failure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
12 changes: 12 additions & 0 deletions test/checks/priorityClassNotSet/success.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: high-priority
72 changes: 72 additions & 0 deletions test/checks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package test

import (
"io/ioutil"
"path/filepath"
"runtime"
"strings"
"testing"

"github.com/stretchr/testify/assert"

"github.com/fairwindsops/polaris/pkg/config"
"github.com/fairwindsops/polaris/pkg/kube"
"github.com/fairwindsops/polaris/pkg/validator"
)

var testCases = []testCase{}

type testCase struct {
check string
input []byte
failure bool
}

func init() {
_, baseDir, _, _ := runtime.Caller(0)
baseDir = filepath.Dir(baseDir) + "/checks"
dirs, err := ioutil.ReadDir(baseDir)
if err != nil {
panic(err)
}
for _, dir := range dirs {
check := dir.Name()
checkDir := baseDir + "/" + check
cases, err := ioutil.ReadDir(checkDir)
if err != nil {
panic(err)
}
for _, tc := range cases {
body, err := ioutil.ReadFile(checkDir + "/" + tc.Name())
if err != nil {
panic(err)
}
testCases = append(testCases, testCase{
check: check,
input: body,
failure: strings.Contains(tc.Name(), "failure"),
})
}
}
}

func TestChecks(t *testing.T) {
for _, tc := range testCases {
workload, err := kube.GetWorkloadFromBytes(tc.input)
assert.NoError(t, err)
c, err := config.Parse([]byte("checks:\n " + tc.check + ": danger"))
assert.NoError(t, err)
result, err := validator.ValidateController(&c, *workload)
assert.NoError(t, err)
summary := result.GetSummary()
if tc.failure {
message := "Check " + tc.check + " passed unexpectedly"
assert.Equal(t, uint(0), summary.Successes, message)
assert.Equal(t, uint(1), summary.Dangers, message)
} else {
message := "Check " + tc.check + " failed unexpectedly"
assert.Equal(t, uint(1), summary.Successes, message)
assert.Equal(t, uint(0), summary.Dangers, message)
}
}
}

0 comments on commit b4e3d40

Please sign in to comment.