Skip to content

Commit

Permalink
feat: add external bindings support to the engine (#401)
Browse files Browse the repository at this point in the history
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
  • Loading branch information
eddycharly authored Jun 10, 2024
1 parent 66a3679 commit 69a4a1f
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 1 deletion.
1 change: 1 addition & 0 deletions pkg/commands/scan/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func Command() *cobra.Command {
SilenceUsage: true,
RunE: command.run,
}
cmd.Flags().StringVar(&command.bindings, "bindings", "", "Bindings file (json or yaml file). Top level keys will be interpreted as bindings names.")
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")
Expand Down
11 changes: 11 additions & 0 deletions pkg/commands/scan/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
func Test_Execute(t *testing.T) {
tests := []struct {
name string
bindings string
payload string
preprocessors []string
policies []string
Expand All @@ -29,6 +30,13 @@ func Test_Execute(t *testing.T) {
policies: []string{"../../../test/commands/scan/wildcard/policy.yaml"},
out: "../../../test/commands/scan/wildcard/out.txt",
wantErr: false,
}, {
name: "bindings",
bindings: "../../../test/commands/scan/bindings/bindings.yaml",
payload: "../../../test/commands/scan/bindings/payload.yaml",
policies: []string{"../../../test/commands/scan/bindings/policy.yaml"},
out: "../../../test/commands/scan/bindings/out.txt",
wantErr: false,
}, {
name: "pod-no-latest",
payload: "../../../test/commands/scan/pod-no-latest/payload.yaml",
Expand Down Expand Up @@ -135,6 +143,9 @@ func Test_Execute(t *testing.T) {
args = append(args, "--policy", policy)
}
args = append(args, "--payload", tt.payload)
if tt.bindings != "" {
args = append(args, "--bindings", tt.bindings)
}
cmd.SetArgs(args)
out := bytes.NewBufferString("")
cmd.SetOut(out)
Expand Down
20 changes: 20 additions & 0 deletions pkg/commands/scan/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
)

type options struct {
bindings string
payload string
preprocessors []string
policies []string
Expand Down Expand Up @@ -48,6 +49,24 @@ func (c *options) run(cmd *cobra.Command, _ []string) error {
}
policies = filteredPolicies
}
var bindings map[string]any
if c.bindings != "" {
out.println("Loading bindings ...")
payload, err := payload.Load(c.bindings)
if err != nil {
return err
}
if payload != nil {
if m, ok := payload.(map[string]any); ok {
bindings = m
for key, value := range bindings {
out.println("-", key, "->", value)
}
} else {
return errors.New("bindings are not a map[string]any object")
}
}
}
out.println("Loading payload ...")
payload, err := payload.Load(c.payload)
if err != nil {
Expand Down Expand Up @@ -80,6 +99,7 @@ func (c *options) run(cmd *cobra.Command, _ []string) error {
responses = append(responses, e.Run(context.Background(), jsonengine.Request{
Resource: resource,
Policies: policies,
Bindings: bindings,
}))
}
for _, response := range responses {
Expand Down
13 changes: 12 additions & 1 deletion pkg/json-engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package jsonengine
import (
"context"
"fmt"
"time"

jpbinding "github.com/jmespath-community/go-jmespath/pkg/binding"
"github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
Expand All @@ -16,6 +17,7 @@ import (
type Request struct {
Resource any
Policies []*v1alpha1.ValidatingPolicy
Bindings map[string]any
}

type Response struct {
Expand All @@ -30,6 +32,7 @@ type PolicyResponse struct {

type RuleResponse struct {
Rule v1alpha1.ValidatingRule
Timestamp time.Time
Identifier string
Error error
Violations matching.Results
Expand Down Expand Up @@ -75,6 +78,7 @@ func New() engine.Engine[Request, Response] {
if err != nil {
return []RuleResponse{{
Rule: r.rule,
Timestamp: time.Now(),
Identifier: identifier,
Error: err,
}}
Expand All @@ -89,6 +93,7 @@ func New() engine.Engine[Request, Response] {
if err != nil {
return []RuleResponse{{
Rule: r.rule,
Timestamp: time.Now(),
Identifier: identifier,
Error: err,
}}
Expand All @@ -102,12 +107,14 @@ func New() engine.Engine[Request, Response] {
if err != nil {
return []RuleResponse{{
Rule: r.rule,
Timestamp: time.Now(),
Identifier: identifier,
Error: err,
}}
}
return []RuleResponse{{
Rule: r.rule,
Timestamp: time.Now(),
Identifier: identifier,
Violations: violations,
}}
Expand All @@ -132,7 +139,11 @@ func New() engine.Engine[Request, Response] {
response := Response{
Resource: r.Resource,
}
bindings := jpbinding.NewBindings().Register("$payload", jpbinding.NewBinding(r.Resource))
bindings := jpbinding.NewBindings()
for k, v := range r.Bindings {
bindings = bindings.Register("$"+k, jpbinding.NewBinding(v))
}
bindings = bindings.Register("$payload", jpbinding.NewBinding(r.Resource))
for _, policy := range r.Policies {
response.Policies = append(response.Policies, policyEngine.Run(ctx, policyRequest{
policy: policy,
Expand Down
1 change: 1 addition & 0 deletions test/commands/scan/bindings/bindings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo: bar
8 changes: 8 additions & 0 deletions test/commands/scan/bindings/out.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Loading policies ...
Loading bindings ...
- foo -> bar
Loading payload ...
Pre processing ...
Running ( evaluating 1 resource against 1 policy ) ...
- test / foo-bar-4 / PASSED
Done
2 changes: 2 additions & 0 deletions test/commands/scan/bindings/payload.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
foo:
bar: 4
15 changes: 15 additions & 0 deletions test/commands/scan/bindings/policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: json.kyverno.io/v1alpha1
kind: ValidatingPolicy
metadata:
name: test
spec:
rules:
- name: foo-bar-4
match:
all:
- ($foo): bar
assert:
all:
- check:
foo:
bar: 4
1 change: 1 addition & 0 deletions website/docs/cli/commands/kyverno-json_scan.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ kyverno-json scan [flags]
### Options

```
--bindings string Bindings file (json or yaml file). Top level keys will be interpreted as bindings names.
-h, --help help for scan
--labels strings Labels selectors for policies
--output string Output format (text or json) (default "text")
Expand Down

0 comments on commit 69a4a1f

Please sign in to comment.