1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 10:28:36 +00:00

combine policy engine returns into single struct

This commit is contained in:
Shuting Zhao 2019-08-14 15:18:46 -07:00
parent e87c72291f
commit 6b1b6dddfa
9 changed files with 63 additions and 48 deletions

View file

@ -1,6 +1,8 @@
package engine
import (
"errors"
jsonpatch "github.com/evanphx/json-patch"
"github.com/golang/glog"
types "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
@ -45,11 +47,13 @@ func applyPolicy(client *client.Client, policy *types.Policy, res resourceInfo)
return nil, err
}
// Validation
vruleInfos, err := Validate(*policy, rawResource, *res.Gvk)
policyInfo.AddRuleInfos(vruleInfos)
if err != nil {
return nil, err
response := Validate(*policy, rawResource, *res.Gvk)
if response != nil {
policyInfo.AddRuleInfos(response.RuleInfos)
} else {
return nil, errors.New("Failed to process validate rule, error parsing rawResource")
}
if res.Gvk.Kind == "Namespace" {
// Generation
@ -61,7 +65,10 @@ func applyPolicy(client *client.Client, policy *types.Policy, res resourceInfo)
}
func mutation(p *types.Policy, rawResource []byte, gvk *metav1.GroupVersionKind) ([]*info.RuleInfo, error) {
patches, _, ruleInfos := Mutate(*p, rawResource, *gvk)
response := Mutate(*p, rawResource, *gvk)
patches := response.Patches
ruleInfos := response.RuleInfos
if len(ruleInfos) == 0 {
// no rules were processed
return nil, nil

View file

@ -8,7 +8,7 @@ import (
)
// Mutate performs mutation. Overlay first and then mutation patches
func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) ([][]byte, []byte, []*info.RuleInfo) {
func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) *EngineResponse {
var allPatches, rulePatches [][]byte
var err error
var errs []error
@ -69,5 +69,9 @@ func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersio
ris = append(ris, ri)
}
return allPatches, patchedDocument, ris
return &EngineResponse{
Patches: allPatches,
PatchedDocument: patchedDocument,
RuleInfos: ris,
}
}

View file

@ -12,6 +12,7 @@ import (
types "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
v1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
client "github.com/nirmata/kyverno/pkg/dclient"
"github.com/nirmata/kyverno/pkg/info"
"github.com/nirmata/kyverno/pkg/utils"
v1helper "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -20,6 +21,12 @@ import (
"k8s.io/apimachinery/pkg/labels"
)
type EngineResponse struct {
Patches [][]byte
PatchedDocument []byte
RuleInfos []*info.RuleInfo
}
//ListResourcesThatApplyToPolicy returns list of resources that are filtered by policy rules
func ListResourcesThatApplyToPolicy(client *client.Client, policy *types.Policy, filterK8Resources []utils.K8Resource) map[string]resourceInfo {
// key uid

View file

@ -17,13 +17,13 @@ import (
// Validate handles validating admission request
// Checks the target resources for rules defined in the policy
func Validate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) ([]*info.RuleInfo, error) {
func Validate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) *EngineResponse {
var resource interface{}
ris := []*info.RuleInfo{}
err := json.Unmarshal(rawResource, &resource)
if err != nil {
return nil, err
if err := json.Unmarshal(rawResource, &resource); err != nil {
glog.Errorf("Failed to parse rawResource err: %v\n", err)
return nil
}
for _, rule := range policy.Spec.Rules {
@ -49,7 +49,9 @@ func Validate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVers
ris = append(ris, ri)
}
return ris, nil
return &EngineResponse{
RuleInfos: ris,
}
}
// validateResourceWithPattern is a start of element-by-element validation process

View file

@ -1573,8 +1573,8 @@ func TestValidate_ServiceTest(t *testing.T) {
gvk := metav1.GroupVersionKind{
Kind: "Service",
}
_, err := Validate(policy, rawResource, gvk)
assert.Assert(t, err == nil)
res := Validate(policy, rawResource, gvk)
assert.Assert(t, res != nil)
}
func TestValidate_MapHasFloats(t *testing.T) {
@ -1672,6 +1672,6 @@ func TestValidate_MapHasFloats(t *testing.T) {
Kind: "Deployment",
}
_, err := Validate(policy, rawResource, gvk)
assert.NilError(t, err)
res := Validate(policy, rawResource, gvk)
assert.Assert(t, res != nil)
}

View file

@ -9,14 +9,13 @@ import (
)
// HandleMutation handles mutating webhook admission request
func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) (bool, [][]byte, []byte) {
var allPatches, policyPatches [][]byte
func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) (bool, *engine.EngineResponse) {
var allPatches [][]byte
policyInfos := []*info.PolicyInfo{}
var ruleInfos []*info.RuleInfo
patchedDocument := request.Object.Raw
engineResponse := &engine.EngineResponse{PatchedDocument: request.Object.Raw}
if request.Operation == v1beta1.Delete {
return true, nil, patchedDocument
return true, engineResponse
}
glog.V(4).Infof("Receive request in mutating webhook: Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s",
@ -27,7 +26,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) (bool
// Unable to connect to policy Lister to access policies
glog.Errorln("Unable to connect to policy controller to access policies. Mutation Rules are NOT being applied")
glog.Warning(err)
return true, nil, patchedDocument
return true, engineResponse
}
rname := engine.ParseNameFromObject(request.Object.Raw)
@ -59,13 +58,12 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) (bool
glog.Infof("Applying policy %s with %d rules\n", policy.ObjectMeta.Name, len(policy.Spec.Rules))
policyPatches, patchedDocument, ruleInfos = engine.Mutate(*policy, patchedDocument, request.Kind)
policyInfo.AddRuleInfos(ruleInfos)
engineResponse = engine.Mutate(*policy, engineResponse.PatchedDocument, request.Kind)
policyInfo.AddRuleInfos(engineResponse.RuleInfos)
if !policyInfo.IsSuccessful() {
glog.Infof("Failed to apply policy %s on resource %s/%s", policy.Name, rname, rns)
for _, r := range ruleInfos {
for _, r := range engineResponse.RuleInfos {
glog.Warningf("%s: %s\n", r.Name, r.Msgs)
}
} else {
@ -74,7 +72,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) (bool
if err != nil {
glog.Info(err)
}
allPatches = append(allPatches, policyPatches...)
allPatches = append(allPatches, engineResponse.Patches...)
glog.Infof("Mutation from policy %s has applied succesfully to %s %s/%s", policy.Name, request.Kind.Kind, rns, rname)
}
policyInfos = append(policyInfos, policyInfo)
@ -93,9 +91,10 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) (bool
ok, msg := isAdmSuccesful(policyInfos)
if ok {
return true, allPatches, patchedDocument
engineResponse.Patches = allPatches
return true, engineResponse
}
glog.Errorf("Failed to mutate the resource: %s\n", msg)
return false, nil, patchedDocument
return false, engineResponse
}

View file

@ -140,7 +140,7 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
func (ws *WebhookServer) HandleAdmissionRequest(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
var response *v1beta1.AdmissionResponse
allowed, allPatches, patchedDocument := ws.HandleMutation(request)
allowed, engineResponse := ws.HandleMutation(request)
if !allowed {
// TODO: add failure message to response
return &v1beta1.AdmissionResponse{
@ -148,10 +148,10 @@ func (ws *WebhookServer) HandleAdmissionRequest(request *v1beta1.AdmissionReques
}
}
response = ws.HandleValidation(request, patchedDocument)
if response.Allowed && len(allPatches) > 0 {
response = ws.HandleValidation(request, engineResponse.PatchedDocument)
if response.Allowed && len(engineResponse.Patches) > 0 {
patchType := v1beta1.PatchTypeJSONPatch
response.Patch = engine.JoinPatches(allPatches)
response.Patch = engine.JoinPatches(engineResponse.Patches)
response.PatchType = &patchType
}

View file

@ -57,19 +57,16 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, raw
request.Kind.Kind, rns, rname, request.UID, request.Operation)
glog.Infof("Validating resource %s/%s/%s with policy %s with %d rules", rkind, rns, rname, policy.ObjectMeta.Name, len(policy.Spec.Rules))
ruleInfos, err := engine.Validate(*policy, rawResource, request.Kind)
if err != nil {
// This is not policy error
// but if unable to parse request raw resource
// TODO : create event ? dont think so
glog.Error(err)
engineResponse := engine.Validate(*policy, rawResource, request.Kind)
if engineResponse == nil {
glog.Errorln("Failed to process validate rule, error parsing rawResource")
continue
}
policyInfo.AddRuleInfos(ruleInfos)
policyInfo.AddRuleInfos(engineResponse.RuleInfos)
if !policyInfo.IsSuccessful() {
glog.Infof("Failed to apply policy %s on resource %s/%s", policy.Name, rname, rns)
for _, r := range ruleInfos {
for _, r := range engineResponse.RuleInfos {
glog.Warningf("%s: %s\n", r.Name, r.Msgs)
}
} else {
@ -79,7 +76,7 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, raw
glog.Info(err)
}
if len(ruleInfos) > 0 {
if len(engineResponse.RuleInfos) > 0 {
glog.Infof("Validation from policy %s has applied succesfully to %s %s/%s", policy.Name, request.Kind.Kind, rname, rns)
}
}

View file

@ -26,14 +26,13 @@ func (ws *WebhookServer) manageWebhookConfigurations(policy v1alpha1.Policy, op
}
func (ws *WebhookServer) registerWebhookConfigurations(policy v1alpha1.Policy) error {
for _, rule := range policy.Spec.Rules {
if rule.Mutation != nil && !ws.webhookRegistrationClient.MutationRegistered.IsSet() {
if err := ws.webhookRegistrationClient.RegisterMutatingWebhook(); err != nil {
return err
}
glog.Infof("Mutating webhook registered")
if !ws.webhookRegistrationClient.MutationRegistered.IsSet() {
if err := ws.webhookRegistrationClient.RegisterMutatingWebhook(); err != nil {
return err
}
glog.Infof("Mutating webhook registered")
}
return nil
}