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

add violations when patches are not applied

This commit is contained in:
shuting 2019-05-01 14:48:50 -07:00
parent 0ec59e2d63
commit 06e5c433b9
4 changed files with 54 additions and 19 deletions

View file

@ -67,8 +67,7 @@ func (pr *PolicyResource) Validate() error {
}
if pr.Name != nil {
// // make non-regexp a regexp to match exactly to the given name
// *pr.Name = "^" + *pr.Name + "$"
// make non-regexp a regexp to match exactly to the given name
if _, err := regexp.Compile(*pr.Name); err != nil {
return fmt.Errorf("invalied regex, err: %v", err)
}

View file

@ -1,7 +1,6 @@
package webhooks
import (
"fmt"
"regexp"
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
@ -64,7 +63,6 @@ func IsRuleApplicableToResource(kind string, resourceRaw []byte, policyResource
if policyResource.Name != nil {
policyResourceName, isRegex := parseRegexPolicyResourceName(*policyResource.Name)
fmt.Println("policyResourceName, name, isRegex", policyResourceName, name, isRegex)
// if no regex used, check if names are matched, return directly
if !isRegex && policyResourceName != name {

View file

@ -6,6 +6,8 @@ import (
"log"
"os"
"github.com/nirmata/kube-policy/pkg/violation"
controller "github.com/nirmata/kube-policy/controller"
kubeclient "github.com/nirmata/kube-policy/kubeclient"
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
@ -104,59 +106,88 @@ func getPolicyPatchingSets(policy types.Policy) PatchingSets {
// Applies all policy rules to the created object and returns list of processed JSON patches.
// May return nil patches if it is not necessary to create patches for requested object.
// Returns error ONLY in case when creation of resource should be denied.
func (mw *MutationWebhook) applyPolicyRules(request *v1beta1.AdmissionRequest, policy types.Policy) ([]PatchBytes, int, error) {
func (mw *MutationWebhook) applyPolicyRules(request *v1beta1.AdmissionRequest, policy types.Policy) ([]PatchBytes, []violation.Info, error) {
return mw.applyPolicyRulesOnResource(request.Kind.Kind, request.Object.Raw, policy)
}
// TODO: add another violation field in return elements
// kind is the type of object being manipulated
func (mw *MutationWebhook) applyPolicyRulesOnResource(kind string, rawResource []byte, policy types.Policy) ([]PatchBytes, int, error) {
func (mw *MutationWebhook) applyPolicyRulesOnResource(kind string, rawResource []byte, policy types.Policy) ([]PatchBytes, []violation.Info, error) {
patchingSets := getPolicyPatchingSets(policy)
var policyPatches []PatchBytes
violationCount := 0
var violations []violation.Info
meta := parseMetadataFromObject(rawResource)
resourceKind := parseKindFromObject(rawResource)
resourceName := parseNameFromMetadata(meta)
ns := parseNamespaceFromMetadata(meta)
for ruleIdx, rule := range policy.Spec.Rules {
err := rule.Validate()
if err != nil {
mw.logger.Printf("Invalid rule detected: #%d in policy %s, err: %v\n", ruleIdx, policy.ObjectMeta.Name, err)
violationCount++
continue
}
if ok, err := IsRuleApplicableToResource(kind, rawResource, rule.Resource); !ok {
mw.logger.Printf("Rule %d of policy %s does not match the request", ruleIdx, policy.Name)
violationCount++
return nil, violationCount, err
mw.logger.Printf("Rule %d of policy %s is not applicable to the request", ruleIdx, policy.Name)
return nil, nil, err
}
// configMapGenerator and secretGenerator can be applied only to namespaces
if kind == "Namespace" {
err = mw.applyRuleGenerators(rawResource, rule)
if err != nil && patchingSets == PatchingSetsStopOnError {
violationCount++
return nil, violationCount, fmt.Errorf("Failed to apply generators from rule #%d: %s", ruleIdx, err)
if err != nil {
violations = append(violations, violation.Info{
Kind: resourceKind,
Resource: ns + "/" + resourceName,
Policy: policy.Name,
RuleName: string(ruleIdx),
Reason: err.Error(),
})
if patchingSets == PatchingSetsStopOnError {
return nil, violations, fmt.Errorf("Failed to apply generators from rule #%d: %s", ruleIdx, err)
}
}
}
rulePatchesProcessed, err := ProcessPatches(rule.Patches, rawResource, patchingSets)
if err != nil {
violationCount++
return nil, violationCount, fmt.Errorf("Failed to process patches from rule #%d: %s", ruleIdx, err)
violations = append(violations, violation.Info{
Kind: resourceKind,
Resource: ns + "/" + resourceName,
Policy: policy.Name,
RuleName: string(ruleIdx),
Reason: err.Error(),
})
return nil, violations, fmt.Errorf("Failed to process patches from rule #%d: %s", ruleIdx, err)
}
if rulePatchesProcessed != nil {
policyPatches = append(policyPatches, rulePatchesProcessed...)
mw.logger.Printf("Rule %d: prepared %d patches", ruleIdx, len(rulePatchesProcessed))
if len(rulePatchesProcessed) < len(rule.Patches) {
violations = append(violations, violation.Info{
Kind: resourceKind,
Resource: ns + "/" + resourceName,
Policy: policy.Name,
RuleName: string(ruleIdx),
Reason: fmt.Sprintf("%v out of %v patches prepared", len(rulePatchesProcessed), len(rule.Patches)),
})
}
} else {
mw.logger.Printf("Rule %d: no patches prepared", ruleIdx)
}
}
// if no rules are validate, return error to deny resource creation
// empty patch, return error to deny resource creation
if policyPatches == nil {
return nil, violationCount, fmt.Errorf("no patches prepared, violations: %v", violationCount)
return nil, nil, fmt.Errorf("no patches prepared")
}
return policyPatches, violationCount, nil
return policyPatches, violations, nil
}
// Applies "configMapGenerator" and "secretGenerator" described in PolicyRule

View file

@ -14,6 +14,13 @@ func parseMetadataFromObject(bytes []byte) map[string]interface{} {
return objectJSON["metadata"].(map[string]interface{})
}
func parseKindFromObject(bytes []byte) string {
var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON)
return objectJSON["kind"].(string)
}
func parseLabelsFromMetadata(meta map[string]interface{}) labels.Set {
if interfaceMap, ok := meta["labels"].(map[string]interface{}); ok {
labelMap := make(labels.Set, len(interfaceMap))