1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 07:57:07 +00:00
kyverno/pkg/validation/policy/generate.go

70 lines
1.6 KiB
Go
Raw Normal View History

package policy
import (
"crypto/md5" //nolint:gosec
"encoding/hex"
"encoding/json"
"errors"
"fmt"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"k8s.io/apimachinery/pkg/util/sets"
)
func immutableGenerateFields(new, old kyvernov1.PolicyInterface) error {
if new == nil || old == nil {
return nil
}
if !new.GetSpec().HasGenerate() {
return nil
}
oldRuleHashes, err := buildHashes(old.GetSpec().Rules)
if err != nil {
return err
}
newRuleHashes, err := buildHashes(new.GetSpec().Rules)
if err != nil {
return err
}
switch len(old.GetSpec().Rules) <= len(new.GetSpec().Rules) {
case true:
if newRuleHashes.IsSuperset(oldRuleHashes) {
return nil
} else {
return errors.New("change of immutable fields for a generate rule is disallowed")
}
case false:
if oldRuleHashes.IsSuperset(newRuleHashes) {
return nil
} else {
return errors.New("rule deletion - change of immutable fields for a generate rule is disallowed")
}
}
return nil
}
func resetMutableFields(rule kyvernov1.Rule) *kyvernov1.Rule {
new := new(kyvernov1.Rule)
rule.DeepCopyInto(new)
new.Generation.Synchronize = true
new.Generation.SetData(nil)
return new
}
func buildHashes(rules []kyvernov1.Rule) (sets.Set[string], error) {
ruleHashes := sets.New[string]()
for _, rule := range rules {
r := resetMutableFields(rule)
data, err := json.Marshal(r)
if err != nil {
return ruleHashes, fmt.Errorf("failed to create hash from the generate rule %v", err)
}
hash := md5.Sum(data) //nolint:gosec
ruleHashes.Insert(hex.EncodeToString(hash[:]))
}
return ruleHashes, nil
}