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:
parent
0ec59e2d63
commit
06e5c433b9
4 changed files with 54 additions and 19 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Add table
Reference in a new issue