Skip to content

Commit

Permalink
redo changes reverted by merge
Browse files Browse the repository at this point in the history
Signed-off-by: Jim Bugwadia <jim@nirmata.com>
  • Loading branch information
JimBugwadia committed Feb 2, 2021
1 parent b4ab541 commit 2bb812a
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 22 deletions.
28 changes: 25 additions & 3 deletions pkg/engine/apiPath.go
Expand Up @@ -33,6 +33,8 @@ func NewAPIPath(path string) (*APIPath, error) {
}

if paths[0] == "api" {

// /api/v1/namespaces
if len(paths) == 3 {
return &APIPath{
Root: paths[0],
Expand All @@ -41,6 +43,7 @@ func NewAPIPath(path string) (*APIPath, error) {
}, nil
}

// /api/v1/namespaces/foo
if len(paths) == 4 {
return &APIPath{
Root: paths[0],
Expand All @@ -50,7 +53,27 @@ func NewAPIPath(path string) (*APIPath, error) {
}, nil
}

return nil, fmt.Errorf("invalid /api/v1 path %s", path)
// /api/v1/namespaces/foo/pods
if len(paths) == 5 {
return &APIPath{
Root: paths[0],
Group: paths[1],
Namespace: paths[3],
ResourceType: paths[4],
}, nil
}

if len(paths) == 6 {
return &APIPath{
Root: paths[0],
Group: paths[1],
Namespace: paths[3],
ResourceType: paths[4],
Name: paths[5],
}, nil
}

return nil, fmt.Errorf("invalid API v1 path %s", path)
}

// /apis/GROUP/VERSION/RESOURCETYPE/
Expand Down Expand Up @@ -97,7 +120,7 @@ func NewAPIPath(path string) (*APIPath, error) {
}, nil
}

return nil, fmt.Errorf("invalid /apis path %s", path)
return nil, fmt.Errorf("invalid API path %s", path)
}

func (a *APIPath) String() string {
Expand All @@ -116,7 +139,6 @@ func (a *APIPath) String() string {
}
}


result := "/" + strings.Join(paths, "/")
result = strings.ReplaceAll(result, "//", "/")
return result
Expand Down
37 changes: 31 additions & 6 deletions pkg/engine/context/context.go
Expand Up @@ -38,10 +38,11 @@ type EvalInterface interface {

//Context stores the data resources as JSON
type Context struct {
mu sync.RWMutex
jsonRaw []byte
builtInVars []string
log logr.Logger
mutex sync.RWMutex
jsonRaw []byte
jsonRawCheckpoint []byte
builtInVars []string
log logr.Logger
}

//NewContext returns a new context
Expand All @@ -60,8 +61,8 @@ func NewContext(builtInVars ...string) *Context {
// AddJSON merges json data
func (ctx *Context) AddJSON(dataRaw []byte) error {
var err error
ctx.mu.Lock()
defer ctx.mu.Unlock()
ctx.mutex.Lock()
defer ctx.mutex.Unlock()
// merge json
ctx.jsonRaw, err = jsonpatch.MergePatch(ctx.jsonRaw, dataRaw)
if err != nil {
Expand Down Expand Up @@ -179,3 +180,27 @@ func (ctx *Context) AddServiceAccount(userName string) error {

return nil
}

// Checkpoint creates a copy of the internal state.
// Prior checkpoints will be overridden.
func (ctx *Context) Checkpoint() {
ctx.mutex.Lock()
defer ctx.mutex.Unlock()

ctx.jsonRawCheckpoint = make([]byte, len(ctx.jsonRaw))
copy(ctx.jsonRawCheckpoint, ctx.jsonRaw)
}

// Restore restores internal state from a prior checkpoint, if one exists.
// If a prior checkpoint does not exist, the state will not be changed.
func (ctx *Context) Restore() {
ctx.mutex.Lock()
defer ctx.mutex.Unlock()

if ctx.jsonRawCheckpoint == nil || len(ctx.jsonRawCheckpoint) == 0 {
return
}

ctx.jsonRaw = make([]byte, len(ctx.jsonRawCheckpoint))
copy(ctx.jsonRaw, ctx.jsonRawCheckpoint)
}
4 changes: 2 additions & 2 deletions pkg/engine/context/evaluate.go
Expand Up @@ -28,8 +28,8 @@ func (ctx *Context) Query(query string) (interface{}, error) {
return emptyResult, fmt.Errorf("incorrect query %s: %v", query, err)
}
// search
ctx.mu.RLock()
defer ctx.mu.RUnlock()
ctx.mutex.RLock()
defer ctx.mutex.RUnlock()

var data interface{}
if err := json.Unmarshal(ctx.jsonRaw, &data); err != nil {
Expand Down
3 changes: 3 additions & 0 deletions pkg/engine/generation.go
Expand Up @@ -81,6 +81,9 @@ func filterRule(rule kyverno.Rule, policyContext *PolicyContext) *response.RuleR
return nil
}

policyContext.JSONContext.Checkpoint()
defer policyContext.JSONContext.Restore()

// add configmap json data to context
if err := LoadContext(logger, rule.Context, resCache, policyContext); err != nil {
logger.V(4).Info("cannot add configmaps to context", "reason", err.Error())
Expand Down
17 changes: 12 additions & 5 deletions pkg/engine/jsonContext.go
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/jmespath/go-jmespath"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/resourcecache"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/dynamic/dynamiclister"
Expand Down Expand Up @@ -44,7 +45,7 @@ func LoadContext(logger logr.Logger, contextEntries []kyverno.ContextEntry, resC
}

func loadAPIData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyContext) error {
jsonData, err := fetchAPIData(entry, ctx)
jsonData, err := fetchAPIData(logger, entry, ctx)
if err != nil {
return err
}
Expand Down Expand Up @@ -94,14 +95,20 @@ func applyJMESPath(jmesPath string, jsonData []byte) (interface{}, error) {
return jp.Search(data)
}

func fetchAPIData(entry kyverno.ContextEntry, ctx *PolicyContext) ([]byte, error) {
func fetchAPIData(log logr.Logger, entry kyverno.ContextEntry, ctx *PolicyContext) ([]byte, error) {
if entry.APICall == nil {
return nil, fmt.Errorf("missing APICall in context entry %v", entry)
return nil, fmt.Errorf("missing APICall in context entry %s %v", entry.Name, entry.APICall)
}

p, err := NewAPIPath(entry.APICall.URLPath)
path, err := variables.SubstituteVars(log, ctx.JSONContext, entry.APICall.URLPath)
if err != nil {
return nil, fmt.Errorf("failed to build API path for %v: %v", entry, err)
return nil, fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.APICall.URLPath, err)
}

pathStr := path.(string)
p, err := NewAPIPath(pathStr)
if err != nil {
return nil, fmt.Errorf("failed to build API path for %s %v: %v", entry.Name, entry.APICall, err)
}

var jsonData []byte
Expand Down
7 changes: 5 additions & 2 deletions pkg/engine/mutation.go
Expand Up @@ -44,6 +44,9 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
return
}

policyContext.JSONContext.Checkpoint()
defer policyContext.JSONContext.Restore()

for _, rule := range policy.Spec.Rules {
var ruleResponse response.RuleResponse
logger := logger.WithValues("rule", rule.Name)
Expand All @@ -66,9 +69,9 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {

logger.V(3).Info("matched mutate rule")

// add configmap json data to context
policyContext.JSONContext.Restore()
if err := LoadContext(logger, rule.Context, resCache, policyContext); err != nil {
logger.V(2).Info("failed to add configmaps to context", "reason", err.Error())
logger.V(2).Info("failed to load context", "reason", err.Error())
continue
}

Expand Down
11 changes: 7 additions & 4 deletions pkg/engine/validation.go
Expand Up @@ -90,20 +90,23 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
return resp
}

ctx.JSONContext.Checkpoint()
defer ctx.JSONContext.Restore()

for _, rule := range ctx.Policy.Spec.Rules {
if !rule.HasValidate() {
continue
}

log = log.WithValues("rule", rule.Name)

// add configmap json data to context
if err := LoadContext(log, rule.Context, ctx.ResourceCache, ctx); err != nil {
log.V(2).Info("failed to add configmaps to context", "reason", err.Error())
if !matches(log, rule, ctx) {
continue
}

if !matches(log, rule, ctx) {
ctx.JSONContext.Restore()
if err := LoadContext(log, rule.Context, ctx.ResourceCache, ctx); err != nil {
log.V(2).Info("failed to load context", "reason", err.Error())
continue
}

Expand Down

0 comments on commit 2bb812a

Please sign in to comment.