Skip to content

Commit

Permalink
refactor failure checker
Browse files Browse the repository at this point in the history
the new checking logic does not use string contains
which makes it more durable if there is output which
happens to match the expected failure text.

new logic checks succesful results against all policies
which have been run, and logs a failure if any policies
did not yield a success.
  • Loading branch information
xchapter7x committed Nov 11, 2019
1 parent 380b3ab commit b4509f3
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 11 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/huandu/xstrings v1.2.0 // indirect
github.com/imdario/mergo v0.3.8 // indirect
github.com/jessevdk/go-flags v1.4.0
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/onsi/gomega v1.7.0
github.com/open-policy-agent/opa v0.14.2
Expand All @@ -23,7 +24,7 @@ require (
github.com/sergi/go-diff v1.0.0
github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b // indirect
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect
gopkg.in/yaml.v2 v2.2.4
golang.org/x/sys v0.0.0-20191008105621-543471e840be // indirect
gopkg.in/yaml.v3 v3.0.0-20191010095647-fc94e3f71652
k8s.io/apimachinery v0.0.0-20191006235458-f9f2f3f8ab02 // indirect
k8s.io/helm v2.14.3+incompatible
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
Expand Down Expand Up @@ -122,6 +124,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
60 changes: 50 additions & 10 deletions pkg/commands/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import (

"github.com/golang/protobuf/ptypes/timestamp"
"github.com/helm/helm/pkg/renderutil"
"github.com/mitchellh/colorstring"
"github.com/open-policy-agent/opa/rego"
"github.com/open-policy-agent/opa/tester"
"github.com/open-policy-agent/opa/topdown"
yaml "gopkg.in/yaml.v3"
"k8s.io/helm/pkg/chartutil"
Expand Down Expand Up @@ -174,28 +176,54 @@ func validateFilePath(filePath string) (*os.File, error) {
return fileFile, nil
}

func getQueryList(policy string) []string {
res := []string{}
mods, _, _ := tester.Load([]string{policy}, nil)
for _, mod := range mods {
for _, rule := range mod.Rules {
if strings.HasPrefix("expect[", string(rule.Head.Name)) ||
strings.HasPrefix("assert[", string(rule.Head.Name)) {
res = append(res, fmt.Sprintf("%s[%s]", rule.Head.Name, rule.Head.Key))
}
}
}
return res
}

func evalPolicyOnInput(writer io.Writer, policy string, namespace string, input interface{}) error {
bufWriter := new(bytes.Buffer)
testResults := make(map[string]bool)
ctx := context.Background()
var results rego.ResultSet
for _, querySuffix := range []string{"expect[_]", "assert[_]"} {
for _, querySuffix := range getQueryList(policy) {
queryString := fmt.Sprintf("data.%s.%s", namespace, querySuffix)
buf := topdown.NewBufferTracer()
query, err := rego.New(
rego.Query(fmt.Sprintf("data.%s.%s", namespace, querySuffix)),
r := rego.New(
rego.Query(queryString),
rego.Tracer(buf),
rego.Load([]string{policy}, nil),
).PrepareForEval(ctx)
)
query, err := r.PrepareForEval(ctx)
if err != nil {
return fmt.Errorf("failed preparing for eval on policies: %w", err)
}

r, err := query.Eval(ctx, rego.EvalInput(input))
resultSet, err := query.Eval(ctx, rego.EvalInput(input))
if err != nil {
return fmt.Errorf("failed eval on policies: %w", err)
}

if len(r) > 0 {
results = append(results, r...)
testResults[queryString] = false
for _, result := range resultSet {
for _, expression := range result.Expressions {
if expression.Text == queryString {
testResults[queryString] = true
}
}
}

if len(resultSet) > 0 {
results = append(results, resultSet...)
topdown.PrettyTrace(bufWriter, *buf)
fmt.Fprint(writer, bufWriter.String())
}
Expand All @@ -205,11 +233,23 @@ func evalPolicyOnInput(writer io.Writer, policy string, namespace string, input
return UnmatchedQuery
}

if strings.Contains(bufWriter.String(), "Fail ") {
fmt.Println("[FAIL] Your policy rules are violated in your rendered output!")
testFailed := false
for testname, passed := range testResults {
if passed {
colorstring.Print("[green]PASS: ")
fmt.Println(testname)
} else {
testFailed = true
colorstring.Print("[red]FAIL: ")
fmt.Println(testname)
}
}

if testFailed {
colorstring.Println("[red][FAILURE] Policy violations found on the Helm Chart!")
return PolicyFailure
}

fmt.Println("[PASS] Your policy rules have been run successfully!")
colorstring.Println("[green][SUCCESS] Your Helm Chart complies with all policies!")
return nil
}

0 comments on commit b4509f3

Please sign in to comment.