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

implement wildcard support

This commit is contained in:
shuting 2019-04-30 17:26:50 -07:00
parent 5ba0b0b842
commit 91b3269aa1
4 changed files with 70 additions and 52 deletions

View file

@ -3,6 +3,7 @@ package v1alpha1
import (
"errors"
"fmt"
"regexp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -65,6 +66,14 @@ 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 + "$"
if _, err := regexp.Compile(*pr.Name); err != nil {
return fmt.Errorf("invalied regex, err: %v", err)
}
}
return nil
}

View file

@ -1,6 +1,9 @@
package webhooks
import (
"fmt"
"regexp"
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
"k8s.io/api/admission/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -43,65 +46,55 @@ func AdmissionIsRequired(request *v1beta1.AdmissionRequest) bool {
}
// Checks requests kind, name and labels to fit the policy
func IsRuleApplicableToRequest(policyResource types.PolicyResource, request *v1beta1.AdmissionRequest) bool {
func IsRuleApplicableToRequest(policyResource types.PolicyResource, request *v1beta1.AdmissionRequest) (bool, error) {
return IsRuleApplicableToResource(request.Kind.Kind, request.Object.Raw, policyResource)
// if policyResource.Kind != request.Kind.Kind {
// return false
// }
// if request.Object.Raw != nil {
// meta := parseMetadataFromObject(request.Object.Raw)
// name := parseNameFromMetadata(meta)
// if policyResource.Name != nil && *policyResource.Name != name {
// return false
// }
// if policyResource.Selector != nil {
// selector, err := metav1.LabelSelectorAsSelector(policyResource.Selector)
// if err != nil {
// return false
// }
// labelMap := parseLabelsFromMetadata(meta)
// if !selector.Matches(labelMap) {
// return false
// }
// }
// }
// return true
}
// kind is the type of object being manipulated
func IsRuleApplicableToResource(kind string, resourceRaw []byte, policyResource types.PolicyResource) bool {
// Checks requests kind, name and labels to fit the policy
func IsRuleApplicableToResource(kind string, resourceRaw []byte, policyResource types.PolicyResource) (bool, error) {
if policyResource.Kind != kind {
return false
return false, nil
}
if resourceRaw != nil {
meta := parseMetadataFromObject(resourceRaw)
name := parseNameFromMetadata(meta)
if policyResource.Name != nil && *policyResource.Name != name {
return false
}
// if policyResource.Name != nil && *policyResource.Name != name {
// return false, false
// }
if policyResource.Name != nil {
fmt.Println("*policyResource.Name, name", *policyResource.Name, name)
if policyResource.Selector != nil {
selector, err := metav1.LabelSelectorAsSelector(policyResource.Selector)
if err != nil {
return false
// if no regex used, check if names are matched, return directly
if policyResource.Name != nil && *policyResource.Name == name {
return true, nil
}
labelMap := parseLabelsFromMetadata(meta)
// validation of regex is peformed when validating the policyResource
// refer to policyResource.Validate()
parseRegexPolicyResourceName(*policyResource.Name)
match, _ := regexp.MatchString(*policyResource.Name, name)
if !selector.Matches(labelMap) {
return false
if !match {
return false, nil
}
if policyResource.Selector != nil {
selector, err := metav1.LabelSelectorAsSelector(policyResource.Selector)
if err != nil {
return false, err
}
labelMap := parseLabelsFromMetadata(meta)
if !selector.Matches(labelMap) {
return false, nil
}
}
}
}
return true
return true, nil
}

View file

@ -64,7 +64,7 @@ func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.Ad
for _, policy := range policies {
mw.logger.Printf("Applying policy %s with %d rules", policy.ObjectMeta.Name, len(policy.Spec.Rules))
policyPatches, err := mw.applyPolicyRules(request, policy)
policyPatches, _, err := mw.applyPolicyRules(request, policy)
if err != nil {
mw.controller.LogPolicyError(policy.Name, err.Error())
@ -103,37 +103,43 @@ 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, error) {
func (mw *MutationWebhook) applyPolicyRules(request *v1beta1.AdmissionRequest, policy types.Policy) ([]PatchBytes, int, 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, error) {
func (mw *MutationWebhook) applyPolicyRulesOnResource(kind string, rawResource []byte, policy types.Policy) ([]PatchBytes, int, error) {
patchingSets := getPolicyPatchingSets(policy)
var policyPatches []PatchBytes
violationCount := 0
for ruleIdx, rule := range policy.Spec.Rules {
err := rule.Validate()
if err != nil {
mw.logger.Printf("Invalid rule detected: #%d in policy %s", ruleIdx, policy.ObjectMeta.Name)
mw.logger.Printf("Invalid rule detected: #%d in policy %s, err: %v\n", ruleIdx, policy.ObjectMeta.Name, err)
violationCount++
continue
}
if !IsRuleApplicableToResource(kind, rawResource, rule.Resource) {
return nil, nil
if ok, err := IsRuleApplicableToResource(kind, rawResource, rule.Resource); !ok {
// mw.logger.Printf("Rule %d of policy %s does not match the request %v", ruleIdx, policy.Name, request.UID)
violationCount++
return nil, violationCount, err
}
// configMapGenerator and secretGenerator can be applied only to namespaces
if kind == "Namespace" {
err = mw.applyRuleGenerators(rawResource, rule)
if err != nil && patchingSets == PatchingSetsStopOnError {
return nil, fmt.Errorf("Failed to apply generators from rule #%d: %s", ruleIdx, err)
violationCount++
return nil, violationCount, fmt.Errorf("Failed to apply generators from rule #%d: %s", ruleIdx, err)
}
}
rulePatchesProcessed, err := ProcessPatches(rule.Patches, rawResource, patchingSets)
if err != nil {
return nil, fmt.Errorf("Failed to process patches from rule #%d: %s", ruleIdx, err)
violationCount++
return nil, violationCount, fmt.Errorf("Failed to process patches from rule #%d: %s", ruleIdx, err)
}
if rulePatchesProcessed != nil {
@ -144,7 +150,12 @@ func (mw *MutationWebhook) applyPolicyRulesOnResource(kind string, rawResource [
}
}
return policyPatches, nil
// if no rules are validate, return error to deny resource creation
if policyPatches == nil {
return nil, violationCount, fmt.Errorf("no patches prepared, violations: %v", violationCount)
}
return policyPatches, violationCount, nil
}
// Applies "configMapGenerator" and "secretGenerator" described in PolicyRule

View file

@ -38,3 +38,8 @@ func parseNamespaceFromMetadata(meta map[string]interface{}) string {
}
return ""
}
// TODO:
func parseRegexPolicyResourceName(policyResourceName string) string {
return ""
}