-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
- Loading branch information
1 parent
52c3f10
commit 8e113d5
Showing
8 changed files
with
254 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,94 +1,24 @@ | ||
package commands | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/kyverno/kyverno-json/pkg/commands/docs" | ||
"github.com/kyverno/kyverno-json/pkg/engine/template" | ||
jsonengine "github.com/kyverno/kyverno-json/pkg/json-engine" | ||
"github.com/kyverno/kyverno-json/pkg/payload" | ||
"github.com/kyverno/kyverno-json/pkg/policy" | ||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/output/pluralize" | ||
"github.com/kyverno/kyverno-json/pkg/commands/scan" | ||
"github.com/spf13/cobra" | ||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
) | ||
|
||
type command struct { | ||
payload string | ||
preprocessors []string | ||
policies []string | ||
} | ||
|
||
func (c *command) Run(cmd *cobra.Command, _ []string) error { | ||
out := cmd.OutOrStdout() | ||
fmt.Fprintln(out, "Loading policies ...") | ||
policies, err := policy.Load(c.policies...) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Fprintln(out, "Loading payload ...") | ||
payload, err := payload.Load(c.payload) | ||
if err != nil { | ||
return err | ||
} | ||
if payload == nil { | ||
return errors.New("payload is `null`") | ||
} | ||
fmt.Fprintln(out, "Pre processing ...") | ||
for _, preprocessor := range c.preprocessors { | ||
result, err := template.Execute(preprocessor, payload, nil) | ||
if err != nil { | ||
return err | ||
} | ||
if result == nil { | ||
return fmt.Errorf("prepocessor resulted in `null` payload (%s)", preprocessor) | ||
} | ||
payload = result | ||
} | ||
var resources []interface{} | ||
if slice, ok := payload.([]interface{}); ok { | ||
resources = slice | ||
} else { | ||
resources = append(resources, payload) | ||
} | ||
fmt.Fprintln(out, "Running", "(", "evaluating", len(resources), pluralize.Pluralize(len(resources), "resource", "resources"), "against", len(policies), pluralize.Pluralize(len(policies), "policy", "policies"), ")", "...") | ||
e := jsonengine.New() | ||
responses := e.Run(jsonengine.JsonEngineRequest{ | ||
Resources: resources, | ||
Policies: policies, | ||
}) | ||
for _, response := range responses { | ||
resourceName, _, _ := unstructured.NestedString(response.Resource.(map[string]interface{}), "address") | ||
if response.Failure != nil { | ||
fmt.Fprintln(out, "-", response.Policy.Name, "/", response.Rule.Name, "/", resourceName, "ERROR:", response.Failure) | ||
} else { | ||
if response.Error == nil { | ||
fmt.Fprintln(out, "-", response.Policy.Name, "/", response.Rule.Name, "/", resourceName, "PASSED") | ||
} else { | ||
fmt.Fprintln(out, "-", response.Policy.Name, "/", response.Rule.Name, "/", resourceName, "FAILED:", response.Error) | ||
} | ||
} | ||
} | ||
fmt.Fprintln(out, "Done") | ||
return nil | ||
} | ||
|
||
func NewRootCommand() *cobra.Command { | ||
var command command | ||
func RootCommand() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "kyverno-json", | ||
Short: "kyverno-json", | ||
Long: "kyverno-json is a CLI tool to apply policies to json resources", | ||
Args: cobra.NoArgs, | ||
RunE: command.Run, | ||
SilenceUsage: true, | ||
RunE: func(cmd *cobra.Command, _ []string) error { | ||
return cmd.Help() | ||
}, | ||
} | ||
cmd.Flags().StringVar(&command.payload, "payload", "", "Path to payload (json or yaml file)") | ||
cmd.Flags().StringSliceVar(&command.preprocessors, "pre-process", nil, "JmesPath expression used to pre process payload") | ||
cmd.Flags().StringSliceVar(&command.policies, "policy", nil, "Path to kyverno-json policies") | ||
cmd.AddCommand( | ||
docs.Command(cmd), | ||
scan.Command(cmd), | ||
) | ||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package scan | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func Command(root *cobra.Command) *cobra.Command { | ||
var command options | ||
cmd := &cobra.Command{ | ||
Use: "scan", | ||
Short: "scan", | ||
Long: "Apply policies to json resources", | ||
Args: cobra.NoArgs, | ||
SilenceUsage: true, | ||
RunE: command.run, | ||
} | ||
cmd.Flags().StringVar(&command.payload, "payload", "", "Path to payload (json or yaml file)") | ||
cmd.Flags().StringSliceVar(&command.preprocessors, "pre-process", nil, "JmesPath expression used to pre process payload") | ||
cmd.Flags().StringSliceVar(&command.policies, "policy", nil, "Path to kyverno-json policies") | ||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package scan | ||
|
||
import ( | ||
"bytes" | ||
"io" | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_Execute(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
payload string | ||
preprocessors []string | ||
policies []string | ||
wantErr bool | ||
out string | ||
}{{ | ||
name: "foo-bar", | ||
payload: "../../../testdata/foo-bar/payload.yaml", | ||
policies: []string{"../../../testdata/foo-bar/policy.yaml"}, | ||
out: "../../../testdata/foo-bar/out.txt", | ||
wantErr: false, | ||
}, { | ||
name: "jim", | ||
payload: "../../../testdata/jim/payload.json", | ||
policies: []string{"../../../testdata/jim/policy.yaml"}, | ||
out: "../../../testdata/jim/out.txt", | ||
wantErr: false, | ||
}, { | ||
name: "pod-no-latest", | ||
payload: "../../../testdata/pod-no-latest/payload.yaml", | ||
policies: []string{"../../../testdata/pod-no-latest/policy.yaml"}, | ||
out: "../../../testdata/pod-no-latest/out.txt", | ||
wantErr: false, | ||
}, { | ||
name: "pod-all-latest", | ||
payload: "../../../testdata/pod-all-latest/payload.yaml", | ||
policies: []string{"../../../testdata/pod-all-latest/policy.yaml"}, | ||
out: "../../../testdata/pod-all-latest/out.txt", | ||
wantErr: false, | ||
}, { | ||
name: "scripted", | ||
payload: "../../../testdata/scripted/payload.yaml", | ||
policies: []string{"../../../testdata/scripted/policy.yaml"}, | ||
out: "../../../testdata/scripted/out.txt", | ||
wantErr: false, | ||
}, { | ||
name: "payload-yaml", | ||
payload: "../../../testdata/payload-yaml/payload.yaml", | ||
preprocessors: []string{"planned_values.root_module.resources"}, | ||
policies: []string{"../../../testdata/payload-yaml/policy.yaml"}, | ||
out: "../../../testdata/payload-yaml/out.txt", | ||
wantErr: false, | ||
}, { | ||
name: "tf-plan", | ||
payload: "../../../testdata/tf-plan/tf.plan.json", | ||
preprocessors: []string{"planned_values.root_module.resources"}, | ||
policies: []string{"../../../testdata/tf-plan/policy.yaml"}, | ||
out: "../../../testdata/tf-plan/out.txt", | ||
wantErr: false, | ||
}, { | ||
name: "escaped", | ||
payload: "../../../testdata/escaped/payload.yaml", | ||
policies: []string{"../../../testdata/escaped/policy.yaml"}, | ||
out: "../../../testdata/escaped/out.txt", | ||
wantErr: false, | ||
}} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
cmd := Command(nil) | ||
assert.NotNil(t, cmd) | ||
var args []string | ||
args = append(args, "--payload", tt.payload) | ||
for _, preprocessor := range tt.preprocessors { | ||
args = append(args, "--pre-process", preprocessor) | ||
} | ||
for _, policy := range tt.policies { | ||
args = append(args, "--policy", policy) | ||
} | ||
args = append(args, "--payload", tt.payload) | ||
cmd.SetArgs(args) | ||
out := bytes.NewBufferString("") | ||
cmd.SetOut(out) | ||
if err := cmd.Execute(); (err != nil) != tt.wantErr { | ||
t.Errorf("command.Run() error = %v, wantErr %v", err, tt.wantErr) | ||
} | ||
actual, err := io.ReadAll(out) | ||
assert.NoError(t, err) | ||
if tt.out != "" { | ||
expected, err := os.ReadFile(tt.out) | ||
assert.NoError(t, err) | ||
assert.Equal(t, string(expected), string(actual)) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package scan |
Oops, something went wrong.