Skip to content

Commit

Permalink
feat: allow custom resource identifier (#114)
Browse files Browse the repository at this point in the history
Signed-off-by: Charles-Edouard Brétéché <[email protected]>
  • Loading branch information
eddycharly authored Oct 18, 2023
1 parent ece1ef4 commit 601d3a0
Show file tree
Hide file tree
Showing 12 changed files with 44 additions and 24 deletions.
1 change: 1 addition & 0 deletions docs/user/commands/kyverno-json_scan.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ kyverno-json scan [flags]

```
-h, --help help for scan
--identifier string JmesPath expression used to identify a resource
--labels strings Labels selectors for policies
--payload string Path to payload (json or yaml file)
--policy strings Path to kyverno-json policies
Expand Down
1 change: 1 addition & 0 deletions pkg/commands/scan/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ func Command() *cobra.Command {
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.Flags().StringSliceVar(&command.selectors, "labels", nil, "Labels selectors for policies")
cmd.Flags().StringVar(&command.identifier, "identifier", "", "JmesPath expression used to identify a resource")
return cmd
}
39 changes: 24 additions & 15 deletions pkg/commands/scan/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func Test_Execute(t *testing.T) {
payload string
preprocessors []string
policies []string
identifier string
wantErr bool
out string
}{{
Expand All @@ -24,23 +25,26 @@ func Test_Execute(t *testing.T) {
out: "../../../test/foo-bar/out.txt",
wantErr: false,
}, {
name: "wildcard",
payload: "../../../test/wildcard/payload.json",
policies: []string{"../../../test/wildcard/policy.yaml"},
out: "../../../test/wildcard/out.txt",
wantErr: false,
name: "wildcard",
payload: "../../../test/wildcard/payload.json",
policies: []string{"../../../test/wildcard/policy.yaml"},
identifier: "name",
out: "../../../test/wildcard/out.txt",
wantErr: false,
}, {
name: "pod-no-latest",
payload: "../../../test/pod-no-latest/payload.yaml",
policies: []string{"../../../test/pod-no-latest/policy.yaml"},
out: "../../../test/pod-no-latest/out.txt",
wantErr: false,
name: "pod-no-latest",
payload: "../../../test/pod-no-latest/payload.yaml",
policies: []string{"../../../test/pod-no-latest/policy.yaml"},
identifier: "metadata.name",
out: "../../../test/pod-no-latest/out.txt",
wantErr: false,
}, {
name: "pod-all-latest",
payload: "../../../test/pod-all-latest/payload.yaml",
policies: []string{"../../../test/pod-all-latest/policy.yaml"},
out: "../../../test/pod-all-latest/out.txt",
wantErr: false,
name: "pod-all-latest",
payload: "../../../test/pod-all-latest/payload.yaml",
policies: []string{"../../../test/pod-all-latest/policy.yaml"},
identifier: "metadata.name",
out: "../../../test/pod-all-latest/out.txt",
wantErr: false,
}, {
name: "scripted",
payload: "../../../test/scripted/payload.yaml",
Expand All @@ -52,13 +56,15 @@ func Test_Execute(t *testing.T) {
payload: "../../../test/payload-yaml/payload.yaml",
preprocessors: []string{"planned_values.root_module.resources"},
policies: []string{"../../../test/payload-yaml/policy.yaml"},
identifier: "address",
out: "../../../test/payload-yaml/out.txt",
wantErr: false,
}, {
name: "tf-plan",
payload: "../../../test/tf-plan/payload.json",
preprocessors: []string{"planned_values.root_module.resources"},
policies: []string{"../../../test/tf-plan/policy.yaml"},
identifier: "address",
out: "../../../test/tf-plan/out.txt",
wantErr: false,
}, {
Expand Down Expand Up @@ -87,6 +93,9 @@ func Test_Execute(t *testing.T) {
args = append(args, "--policy", policy)
}
args = append(args, "--payload", tt.payload)
if tt.identifier != "" {
args = append(args, "--identifier", tt.identifier)
}
cmd.SetArgs(args)
out := bytes.NewBufferString("")
cmd.SetOut(out)
Expand Down
12 changes: 10 additions & 2 deletions pkg/commands/scan/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/kyverno/kyverno-json/pkg/policy"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/output/pluralize"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
)

Expand All @@ -22,6 +21,7 @@ type options struct {
preprocessors []string
policies []string
selectors []string
identifier string
}

func (c *options) run(cmd *cobra.Command, _ []string) error {
Expand Down Expand Up @@ -80,7 +80,15 @@ func (c *options) run(cmd *cobra.Command, _ []string) error {
Policies: policies,
})
for _, response := range responses {
resourceName, _, _ := unstructured.NestedString(response.Resource.(map[string]interface{}), "address")
resourceName := "(unknown)"
if c.identifier != "" {
result, err := template.Execute(context.Background(), c.identifier, response.Resource, nil)
if err != nil {
resourceName = fmt.Sprintf("(error: %s)", err)
} else {
resourceName = fmt.Sprint(result)
}
}
if response.Failure != nil {
fmt.Fprintln(out, "-", response.Policy.Name, "/", response.Rule.Name, "/", resourceName, "ERROR:", response.Failure)
} else {
Expand Down
2 changes: 1 addition & 1 deletion test/dockerfile/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Loading policies ...
Loading payload ...
Pre processing ...
Running ( evaluating 1 resource against 1 policy ) ...
- check-dockerfile / deny-external-calls / FAILED: HTTP calls are not allowed: all[0].check.~.(Stages[].Commands[].Args[].Value)[0].(contains(@, 'https://') || contains(@, 'http://')): Invalid value: true: Expected value: false; wget is not allowed: all[3].check.~.(Stages[].Commands[].CmdLine[])[0].(contains(@, 'wget')): Invalid value: true: Expected value: false
- check-dockerfile / deny-external-calls / (unknown) FAILED: HTTP calls are not allowed: all[0].check.~.(Stages[].Commands[].Args[].Value)[0].(contains(@, 'https://') || contains(@, 'http://')): Invalid value: true: Expected value: false; wget is not allowed: all[3].check.~.(Stages[].Commands[].CmdLine[])[0].(contains(@, 'wget')): Invalid value: true: Expected value: false
Done
2 changes: 1 addition & 1 deletion test/escaped/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Loading policies ...
Loading payload ...
Pre processing ...
Running ( evaluating 1 resource against 1 policy ) ...
- test / foo-bar-4 / PASSED
- test / foo-bar-4 / (unknown) PASSED
Done
2 changes: 1 addition & 1 deletion test/foo-bar/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Loading policies ...
Loading payload ...
Pre processing ...
Running ( evaluating 1 resource against 1 policy ) ...
- test / foo-bar-4 / PASSED
- test / foo-bar-4 / (unknown) PASSED
Done
2 changes: 1 addition & 1 deletion test/pod-all-latest/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Loading policies ...
Loading payload ...
Pre processing ...
Running ( evaluating 1 resource against 1 policy ) ...
- test / pod-no-latest / PASSED
- test / pod-no-latest / webserver PASSED
Done
2 changes: 1 addition & 1 deletion test/pod-no-latest/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Loading policies ...
Loading payload ...
Pre processing ...
Running ( evaluating 1 resource against 1 policy ) ...
- test / pod-no-latest / FAILED: [all[0].check.spec.~foo.containers->foos[0].(at($foos, $foo).image)->foo.(ends_with($foo, $tag)): Invalid value: true: Expected value: false, all[0].check.spec.~foo.containers->foos[1].(at($foos, $foo).image)->foo.(ends_with($foo, $tag)): Invalid value: true: Expected value: false, all[0].check.spec.~foo.containers->foos[2].(at($foos, $foo).image)->foo.(ends_with($foo, $tag)): Invalid value: true: Expected value: false]; [all[1].check.spec.~.containers->foo[0].image.(ends_with(@, ':latest')): Invalid value: true: Expected value: false, all[1].check.spec.~.containers->foo[1].image.(ends_with(@, ':latest')): Invalid value: true: Expected value: false, all[1].check.spec.~.containers->foo[2].image.(ends_with(@, ':latest')): Invalid value: true: Expected value: false]; [all[2].check.~index.(spec.containers[*].image)->images[0].(ends_with(@, ':latest')): Invalid value: true: Expected value: false, all[2].check.~index.(spec.containers[*].image)->images[1].(ends_with(@, ':latest')): Invalid value: true: Expected value: false, all[2].check.~index.(spec.containers[*].image)->images[2].(ends_with(@, ':latest')): Invalid value: true: Expected value: false]
- test / pod-no-latest / webserver FAILED: [all[0].check.spec.~foo.containers->foos[0].(at($foos, $foo).image)->foo.(ends_with($foo, $tag)): Invalid value: true: Expected value: false, all[0].check.spec.~foo.containers->foos[1].(at($foos, $foo).image)->foo.(ends_with($foo, $tag)): Invalid value: true: Expected value: false, all[0].check.spec.~foo.containers->foos[2].(at($foos, $foo).image)->foo.(ends_with($foo, $tag)): Invalid value: true: Expected value: false]; [all[1].check.spec.~.containers->foo[0].image.(ends_with(@, ':latest')): Invalid value: true: Expected value: false, all[1].check.spec.~.containers->foo[1].image.(ends_with(@, ':latest')): Invalid value: true: Expected value: false, all[1].check.spec.~.containers->foo[2].image.(ends_with(@, ':latest')): Invalid value: true: Expected value: false]; [all[2].check.~index.(spec.containers[*].image)->images[0].(ends_with(@, ':latest')): Invalid value: true: Expected value: false, all[2].check.~index.(spec.containers[*].image)->images[1].(ends_with(@, ':latest')): Invalid value: true: Expected value: false, all[2].check.~index.(spec.containers[*].image)->images[2].(ends_with(@, ':latest')): Invalid value: true: Expected value: false]
Done
2 changes: 1 addition & 1 deletion test/scripted/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Loading policies ...
Loading payload ...
Pre processing ...
Running ( evaluating 1 resource against 1 policy ) ...
- test / foo-bar-4 / PASSED
- test / foo-bar-4 / (unknown) PASSED
Done
2 changes: 1 addition & 1 deletion test/wildcard/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Loading policies ...
Loading payload ...
Pre processing ...
Running ( evaluating 1 resource against 1 policy ) ...
- required-s3-tags / require-team-tag / FAILED: all[0].check.tags.(wildcard('?*', Team)): Invalid value: true: Expected value: false
- required-s3-tags / require-team-tag / bucket1 FAILED: all[0].check.tags.(wildcard('?*', Team)): Invalid value: true: Expected value: false
Done
1 change: 1 addition & 0 deletions website/docs/commands/kyverno-json_scan.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ kyverno-json scan [flags]

```
-h, --help help for scan
--identifier string JmesPath expression used to identify a resource
--labels strings Labels selectors for policies
--payload string Path to payload (json or yaml file)
--policy strings Path to kyverno-json policies
Expand Down

0 comments on commit 601d3a0

Please sign in to comment.