2020-07-10 18:12:19 +05:30
|
|
|
package policymutation
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/go-logr/logr"
|
2021-10-29 18:13:20 +02:00
|
|
|
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
2022-03-02 00:19:31 +01:00
|
|
|
"github.com/kyverno/kyverno/pkg/autogen"
|
2022-03-28 16:01:27 +02:00
|
|
|
"github.com/kyverno/kyverno/pkg/toggle"
|
2022-03-31 18:34:52 +02:00
|
|
|
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
2020-07-10 18:12:19 +05:30
|
|
|
)
|
|
|
|
|
2020-11-17 13:07:30 -08:00
|
|
|
// GenerateJSONPatchesForDefaults generates default JSON patches for
|
|
|
|
// - ValidationFailureAction
|
|
|
|
// - Background
|
|
|
|
// - auto-gen annotation and rules
|
2022-03-31 08:44:00 +02:00
|
|
|
func GenerateJSONPatchesForDefaults(policy kyverno.PolicyInterface, log logr.Logger) ([]byte, []string) {
|
2020-07-10 18:12:19 +05:30
|
|
|
var patches [][]byte
|
|
|
|
var updateMsgs []string
|
2022-03-31 08:44:00 +02:00
|
|
|
spec := policy.GetSpec()
|
2022-04-05 10:28:33 +02:00
|
|
|
// if autogenInternals is enabled, we don't mutate most of the policy fields
|
2022-03-28 16:01:27 +02:00
|
|
|
if !toggle.AutogenInternals() {
|
2022-04-05 10:28:33 +02:00
|
|
|
// default 'ValidationFailureAction'
|
|
|
|
if patch, updateMsg := defaultvalidationFailureAction(spec, log); patch != nil {
|
|
|
|
patches = append(patches, patch)
|
|
|
|
updateMsgs = append(updateMsgs, updateMsg)
|
|
|
|
}
|
|
|
|
// default 'Background'
|
|
|
|
if patch, updateMsg := defaultBackgroundFlag(spec, log); patch != nil {
|
|
|
|
patches = append(patches, patch)
|
|
|
|
updateMsgs = append(updateMsgs, updateMsg)
|
|
|
|
}
|
|
|
|
if patch, updateMsg := defaultFailurePolicy(spec, log); patch != nil {
|
|
|
|
patches = append(patches, patch)
|
|
|
|
updateMsgs = append(updateMsgs, updateMsg)
|
|
|
|
}
|
2022-03-31 08:44:00 +02:00
|
|
|
patch, errs := GeneratePodControllerRule(policy, log)
|
2022-03-28 16:01:27 +02:00
|
|
|
if len(errs) > 0 {
|
|
|
|
var errMsgs []string
|
|
|
|
for _, err := range errs {
|
|
|
|
errMsgs = append(errMsgs, err.Error())
|
|
|
|
log.Error(err, "failed to generate pod controller rule")
|
|
|
|
}
|
|
|
|
updateMsgs = append(updateMsgs, strings.Join(errMsgs, ";"))
|
2020-07-10 18:12:19 +05:30
|
|
|
}
|
2022-03-28 16:01:27 +02:00
|
|
|
patches = append(patches, patch...)
|
2020-07-10 18:12:19 +05:30
|
|
|
}
|
2021-09-14 19:46:04 -07:00
|
|
|
|
2022-05-09 18:50:50 -07:00
|
|
|
return jsonutils.JoinPatches(patches...), updateMsgs
|
2021-09-14 19:46:04 -07:00
|
|
|
}
|
|
|
|
|
2022-03-01 23:42:19 +01:00
|
|
|
func defaultBackgroundFlag(spec *kyverno.Spec, log logr.Logger) ([]byte, string) {
|
2020-07-10 18:12:19 +05:30
|
|
|
// set 'Background' flag to 'true' if not specified
|
2022-03-01 23:42:19 +01:00
|
|
|
if spec.Background == nil {
|
2022-04-01 07:26:47 +02:00
|
|
|
defaultVal := true
|
2020-07-11 18:12:35 +05:30
|
|
|
log.V(4).Info("setting default value", "spec.background", true)
|
2022-04-01 07:26:47 +02:00
|
|
|
patchByte, err := jsonutils.MarshalPatch("/spec/background", "add", &defaultVal)
|
2020-07-10 18:12:19 +05:30
|
|
|
if err != nil {
|
2020-07-11 18:12:35 +05:30
|
|
|
log.Error(err, "failed to set default value", "spec.background", true)
|
2020-07-10 18:12:19 +05:30
|
|
|
return nil, ""
|
|
|
|
}
|
2020-07-11 18:12:35 +05:30
|
|
|
log.V(3).Info("generated JSON Patch to set default", "spec.background", true)
|
2020-07-10 18:12:19 +05:30
|
|
|
return patchByte, fmt.Sprintf("default 'Background' to '%s'", strconv.FormatBool(true))
|
|
|
|
}
|
|
|
|
return nil, ""
|
|
|
|
}
|
|
|
|
|
2022-03-01 23:42:19 +01:00
|
|
|
func defaultvalidationFailureAction(spec *kyverno.Spec, log logr.Logger) ([]byte, string) {
|
2020-07-10 18:12:19 +05:30
|
|
|
// set ValidationFailureAction to "audit" if not specified
|
2022-03-01 23:42:19 +01:00
|
|
|
if spec.ValidationFailureAction == "" {
|
2022-04-01 07:26:47 +02:00
|
|
|
audit := kyverno.Audit
|
|
|
|
log.V(4).Info("setting default value", "spec.validationFailureAction", audit)
|
|
|
|
patchByte, err := jsonutils.MarshalPatch("/spec/validationFailureAction", "add", audit)
|
2020-07-10 18:12:19 +05:30
|
|
|
if err != nil {
|
2022-04-01 07:26:47 +02:00
|
|
|
log.Error(err, "failed to default value", "spec.validationFailureAction", audit)
|
2020-07-10 18:12:19 +05:30
|
|
|
return nil, ""
|
|
|
|
}
|
2022-04-01 07:26:47 +02:00
|
|
|
log.V(3).Info("generated JSON Patch to set default", "spec.validationFailureAction", audit)
|
|
|
|
return patchByte, fmt.Sprintf("default 'ValidationFailureAction' to '%s'", audit)
|
2020-07-10 18:12:19 +05:30
|
|
|
}
|
|
|
|
return nil, ""
|
|
|
|
}
|
2022-03-01 23:42:19 +01:00
|
|
|
|
|
|
|
func defaultFailurePolicy(spec *kyverno.Spec, log logr.Logger) ([]byte, string) {
|
2021-10-05 00:15:09 -07:00
|
|
|
// set failurePolicy to Fail if not present
|
2022-03-01 23:42:19 +01:00
|
|
|
if spec.FailurePolicy == nil {
|
2022-04-01 07:26:47 +02:00
|
|
|
failurePolicy := string(kyverno.Fail)
|
2021-10-05 00:15:09 -07:00
|
|
|
log.V(4).Info("setting default value", "spec.failurePolicy", failurePolicy)
|
2022-04-01 07:26:47 +02:00
|
|
|
patchByte, err := jsonutils.MarshalPatch("/spec/failurePolicy", "add", failurePolicy)
|
2021-10-05 00:15:09 -07:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err, "failed to set default value", "spec.failurePolicy", failurePolicy)
|
|
|
|
return nil, ""
|
|
|
|
}
|
|
|
|
log.V(3).Info("generated JSON Patch to set default", "spec.failurePolicy", failurePolicy)
|
|
|
|
return patchByte, fmt.Sprintf("default failurePolicy to '%s'", failurePolicy)
|
|
|
|
}
|
|
|
|
return nil, ""
|
|
|
|
}
|
2020-07-10 18:12:19 +05:30
|
|
|
|
|
|
|
// podControllersKey annotation could be:
|
|
|
|
// scenario A: not exist, set default to "all", which generates on all pod controllers
|
|
|
|
// - if name / selector exist in resource description -> skip
|
|
|
|
// as these fields may not be applicable to pod controllers
|
|
|
|
// scenario B: "none", user explicitly disable this feature -> skip
|
|
|
|
// scenario C: some certain controllers that user set -> generate on defined controllers
|
2020-12-01 22:50:40 -08:00
|
|
|
// copy entire match / exclude block, it's users' responsibility to
|
|
|
|
// make sure all fields are applicable to pod controllers
|
2020-07-10 18:12:19 +05:30
|
|
|
|
|
|
|
// GeneratePodControllerRule returns two patches: rulePatches and annotation patch(if necessary)
|
2022-03-31 08:44:00 +02:00
|
|
|
func GeneratePodControllerRule(policy kyverno.PolicyInterface, log logr.Logger) (patches [][]byte, errs []error) {
|
|
|
|
spec := policy.GetSpec()
|
2022-04-29 11:12:21 +02:00
|
|
|
applyAutoGen, desiredControllers := autogen.CanAutoGen(spec)
|
2021-04-29 14:59:37 -07:00
|
|
|
|
2022-01-19 23:12:31 +05:30
|
|
|
if !applyAutoGen {
|
|
|
|
desiredControllers = "none"
|
|
|
|
}
|
|
|
|
|
2020-07-10 18:12:19 +05:30
|
|
|
ann := policy.GetAnnotations()
|
2022-03-09 14:48:04 +01:00
|
|
|
actualControllers, ok := ann[kyverno.PodControllersAnnotation]
|
2020-07-10 18:12:19 +05:30
|
|
|
|
2021-04-29 14:59:37 -07:00
|
|
|
// - scenario A
|
|
|
|
// - predefined controllers are invalid, overwrite the value
|
|
|
|
if !ok || !applyAutoGen {
|
|
|
|
actualControllers = desiredControllers
|
2022-03-28 16:01:27 +02:00
|
|
|
annPatch, err := defaultPodControllerAnnotation(ann, actualControllers)
|
|
|
|
if err != nil {
|
2022-03-31 08:44:00 +02:00
|
|
|
errs = append(errs, fmt.Errorf("failed to generate pod controller annotation for policy '%s': %v", policy.GetName(), err))
|
2022-03-28 16:01:27 +02:00
|
|
|
} else {
|
|
|
|
patches = append(patches, annPatch)
|
2020-07-10 18:12:19 +05:30
|
|
|
}
|
2021-04-29 14:59:37 -07:00
|
|
|
} else {
|
|
|
|
if !applyAutoGen {
|
|
|
|
actualControllers = desiredControllers
|
|
|
|
}
|
2020-07-10 18:12:19 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
// scenario B
|
2021-04-29 14:59:37 -07:00
|
|
|
if actualControllers == "none" {
|
|
|
|
return patches, nil
|
2020-07-10 18:12:19 +05:30
|
|
|
}
|
|
|
|
|
2021-04-29 14:59:37 -07:00
|
|
|
log.V(3).Info("auto generating rule for pod controllers", "controllers", actualControllers)
|
2020-07-10 18:12:19 +05:30
|
|
|
|
2022-04-29 11:12:21 +02:00
|
|
|
p, err := autogen.GenerateRulePatches(spec, actualControllers)
|
2020-07-10 18:12:19 +05:30
|
|
|
patches = append(patches, p...)
|
|
|
|
errs = append(errs, err...)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-09-01 09:11:20 -07:00
|
|
|
// defaultPodControllerAnnotation inserts an annotation
|
2021-04-29 14:59:37 -07:00
|
|
|
// "pod-policies.kyverno.io/autogen-controllers=<controllers>" to policy
|
|
|
|
func defaultPodControllerAnnotation(ann map[string]string, controllers string) ([]byte, error) {
|
2020-07-10 18:12:19 +05:30
|
|
|
if ann == nil {
|
|
|
|
ann = make(map[string]string)
|
2022-03-09 14:48:04 +01:00
|
|
|
ann[kyverno.PodControllersAnnotation] = controllers
|
2022-04-01 07:26:47 +02:00
|
|
|
patchByte, err := jsonutils.MarshalPatch("/metadata/annotations", "add", ann)
|
2020-07-10 18:12:19 +05:30
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return patchByte, nil
|
|
|
|
}
|
2022-04-01 07:26:47 +02:00
|
|
|
patchByte, err := jsonutils.MarshalPatch("/metadata/annotations/pod-policies.kyverno.io~1autogen-controllers", "add", controllers)
|
2020-07-10 18:12:19 +05:30
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return patchByte, nil
|
|
|
|
}
|