mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
move webhooks/patches.go webhooks/utils.go to pkg/policymanager/
This commit is contained in:
parent
2b4ac9d07b
commit
0c744db0e9
7 changed files with 96 additions and 83 deletions
|
@ -1,4 +1,4 @@
|
||||||
package webhooks
|
package policymanager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -20,6 +20,15 @@ const (
|
||||||
|
|
||||||
type PatchBytes []byte
|
type PatchBytes []byte
|
||||||
|
|
||||||
|
func GetPolicyPatchingSets(policy types.Policy) PatchingSets {
|
||||||
|
// failurePolicy property is the only available way for now to define behavior on patching error.
|
||||||
|
// TODO: define new failurePolicy values specific for patching and other policy features.
|
||||||
|
if policy.Spec.FailurePolicy != nil && *policy.Spec.FailurePolicy == "continueOnError" {
|
||||||
|
return PatchingSetsContinueAlways
|
||||||
|
}
|
||||||
|
return PatchingSetsDefault
|
||||||
|
}
|
||||||
|
|
||||||
// Test patches on given document according to given sets.
|
// Test patches on given document according to given sets.
|
||||||
// Returns array from separate patches that can be applied to the document
|
// Returns array from separate patches that can be applied to the document
|
||||||
// Returns error ONLY in case when creation of resource should be denied.
|
// Returns error ONLY in case when creation of resource should be denied.
|
||||||
|
@ -27,7 +36,6 @@ func ProcessPatches(patches []types.PolicyPatch, originalDocument []byte, sets P
|
||||||
if len(originalDocument) == 0 {
|
if len(originalDocument) == 0 {
|
||||||
return nil, errors.New("Source document for patching is empty")
|
return nil, errors.New("Source document for patching is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
var appliedPatches []PatchBytes
|
var appliedPatches []PatchBytes
|
||||||
patchedDocument := originalDocument
|
patchedDocument := originalDocument
|
||||||
for _, patch := range patches {
|
for _, patch := range patches {
|
|
@ -1,10 +1,9 @@
|
||||||
package webhooks_test
|
package policymanager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gotest.tools/assert"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nirmata/kube-policy/webhooks"
|
"gotest.tools/assert"
|
||||||
|
|
||||||
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
||||||
)
|
)
|
||||||
|
@ -36,7 +35,7 @@ const endpointsDocument string = `{
|
||||||
|
|
||||||
func TestProcessPatches_EmptyPatches(t *testing.T) {
|
func TestProcessPatches_EmptyPatches(t *testing.T) {
|
||||||
var empty []types.PolicyPatch
|
var empty []types.PolicyPatch
|
||||||
patches, err := webhooks.ProcessPatches(empty, []byte(endpointsDocument), webhooks.PatchingSetsDefault)
|
patches, err := ProcessPatches(empty, []byte(endpointsDocument), PatchingSetsDefault)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Assert(t, len(patches) == 0)
|
assert.Assert(t, len(patches) == 0)
|
||||||
}
|
}
|
||||||
|
@ -52,13 +51,13 @@ func makeAddIsMutatedLabelPatch() types.PolicyPatch {
|
||||||
func TestProcessPatches_EmptyDocument(t *testing.T) {
|
func TestProcessPatches_EmptyDocument(t *testing.T) {
|
||||||
var patches []types.PolicyPatch
|
var patches []types.PolicyPatch
|
||||||
patches = append(patches, makeAddIsMutatedLabelPatch())
|
patches = append(patches, makeAddIsMutatedLabelPatch())
|
||||||
patchesBytes, err := webhooks.ProcessPatches(patches, nil, webhooks.PatchingSetsDefault)
|
patchesBytes, err := ProcessPatches(patches, nil, PatchingSetsDefault)
|
||||||
assert.Assert(t, err != nil)
|
assert.Assert(t, err != nil)
|
||||||
assert.Assert(t, len(patchesBytes) == 0)
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProcessPatches_AllEmpty(t *testing.T) {
|
func TestProcessPatches_AllEmpty(t *testing.T) {
|
||||||
patchesBytes, err := webhooks.ProcessPatches(nil, nil, webhooks.PatchingSetsDefault)
|
patchesBytes, err := ProcessPatches(nil, nil, PatchingSetsDefault)
|
||||||
assert.Assert(t, err != nil)
|
assert.Assert(t, err != nil)
|
||||||
assert.Assert(t, len(patchesBytes) == 0)
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
}
|
}
|
||||||
|
@ -67,7 +66,7 @@ func TestProcessPatches_AddPathDoesntExist_StopOnError(t *testing.T) {
|
||||||
patch := makeAddIsMutatedLabelPatch()
|
patch := makeAddIsMutatedLabelPatch()
|
||||||
patch.Path = "/metadata/additional/is-mutated"
|
patch.Path = "/metadata/additional/is-mutated"
|
||||||
patches := []types.PolicyPatch{patch}
|
patches := []types.PolicyPatch{patch}
|
||||||
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsStopOnError)
|
patchesBytes, err := ProcessPatches(patches, []byte(endpointsDocument), PatchingSetsStopOnError)
|
||||||
assert.Assert(t, err != nil)
|
assert.Assert(t, err != nil)
|
||||||
assert.Assert(t, len(patchesBytes) == 0)
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
}
|
}
|
||||||
|
@ -76,7 +75,7 @@ func TestProcessPatches_AddPathDoesntExist_ContinueOnError(t *testing.T) {
|
||||||
patch := makeAddIsMutatedLabelPatch()
|
patch := makeAddIsMutatedLabelPatch()
|
||||||
patch.Path = "/metadata/additional/is-mutated"
|
patch.Path = "/metadata/additional/is-mutated"
|
||||||
patches := []types.PolicyPatch{patch}
|
patches := []types.PolicyPatch{patch}
|
||||||
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueAlways)
|
patchesBytes, err := ProcessPatches(patches, []byte(endpointsDocument), PatchingSetsContinueAlways)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Assert(t, len(patchesBytes) == 0)
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
}
|
}
|
||||||
|
@ -84,7 +83,7 @@ func TestProcessPatches_AddPathDoesntExist_ContinueOnError(t *testing.T) {
|
||||||
func TestProcessPatches_RemovePathDoesntExist_StopOnError(t *testing.T) {
|
func TestProcessPatches_RemovePathDoesntExist_StopOnError(t *testing.T) {
|
||||||
patch := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
patch := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||||
patches := []types.PolicyPatch{patch}
|
patches := []types.PolicyPatch{patch}
|
||||||
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsStopOnError)
|
patchesBytes, err := ProcessPatches(patches, []byte(endpointsDocument), PatchingSetsStopOnError)
|
||||||
assert.Assert(t, err != nil)
|
assert.Assert(t, err != nil)
|
||||||
assert.Assert(t, len(patchesBytes) == 0)
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
}
|
}
|
||||||
|
@ -93,7 +92,7 @@ func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_EmptyResult(t
|
||||||
patch1 := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
patch1 := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||||
patch2 := types.PolicyPatch{Path: "/spec/labels/label3", Operation: "add", Value: "label3Value"}
|
patch2 := types.PolicyPatch{Path: "/spec/labels/label3", Operation: "add", Value: "label3Value"}
|
||||||
patches := []types.PolicyPatch{patch1, patch2}
|
patches := []types.PolicyPatch{patch1, patch2}
|
||||||
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueAlways)
|
patchesBytes, err := ProcessPatches(patches, []byte(endpointsDocument), PatchingSetsContinueAlways)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Assert(t, len(patchesBytes) == 0)
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
}
|
}
|
||||||
|
@ -103,7 +102,7 @@ func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_NotEmptyResul
|
||||||
patch2 := types.PolicyPatch{Path: "/spec/labels/label2", Operation: "remove", Value: "label2Value"}
|
patch2 := types.PolicyPatch{Path: "/spec/labels/label2", Operation: "remove", Value: "label2Value"}
|
||||||
patch3 := types.PolicyPatch{Path: "/metadata/labels/label3", Operation: "add", Value: "label3Value"}
|
patch3 := types.PolicyPatch{Path: "/metadata/labels/label3", Operation: "add", Value: "label3Value"}
|
||||||
patches := []types.PolicyPatch{patch1, patch2, patch3}
|
patches := []types.PolicyPatch{patch1, patch2, patch3}
|
||||||
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueAlways)
|
patchesBytes, err := ProcessPatches(patches, []byte(endpointsDocument), PatchingSetsContinueAlways)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Assert(t, len(patchesBytes) == 1)
|
assert.Assert(t, len(patchesBytes) == 1)
|
||||||
assertEqStringAndData(t, `{"path":"/metadata/labels/label3","op":"add","value":"label3Value"}`, patchesBytes[0])
|
assertEqStringAndData(t, `{"path":"/metadata/labels/label3","op":"add","value":"label3Value"}`, patchesBytes[0])
|
||||||
|
@ -112,7 +111,7 @@ func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_NotEmptyResul
|
||||||
func TestProcessPatches_RemovePathDoesntExist_IgnoreRemoveFailures_EmptyResult(t *testing.T) {
|
func TestProcessPatches_RemovePathDoesntExist_IgnoreRemoveFailures_EmptyResult(t *testing.T) {
|
||||||
patch := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
patch := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||||
patches := []types.PolicyPatch{patch}
|
patches := []types.PolicyPatch{patch}
|
||||||
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueOnRemoveFailure)
|
patchesBytes, err := ProcessPatches(patches, []byte(endpointsDocument), PatchingSetsContinueOnRemoveFailure)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Assert(t, len(patchesBytes) == 0)
|
assert.Assert(t, len(patchesBytes) == 0)
|
||||||
}
|
}
|
||||||
|
@ -121,8 +120,16 @@ func TestProcessPatches_RemovePathDoesntExist_IgnoreRemoveFailures_NotEmptyResul
|
||||||
patch1 := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
patch1 := types.PolicyPatch{Path: "/metadata/labels/is-mutated", Operation: "remove"}
|
||||||
patch2 := types.PolicyPatch{Path: "/metadata/labels/label2", Operation: "add", Value: "label2Value"}
|
patch2 := types.PolicyPatch{Path: "/metadata/labels/label2", Operation: "add", Value: "label2Value"}
|
||||||
patches := []types.PolicyPatch{patch1, patch2}
|
patches := []types.PolicyPatch{patch1, patch2}
|
||||||
patchesBytes, err := webhooks.ProcessPatches(patches, []byte(endpointsDocument), webhooks.PatchingSetsContinueOnRemoveFailure)
|
patchesBytes, err := ProcessPatches(patches, []byte(endpointsDocument), PatchingSetsContinueOnRemoveFailure)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Assert(t, len(patchesBytes) == 1)
|
assert.Assert(t, len(patchesBytes) == 1)
|
||||||
assertEqStringAndData(t, `{"path":"/metadata/labels/label2","op":"add","value":"label2Value"}`, patchesBytes[0])
|
assertEqStringAndData(t, `{"path":"/metadata/labels/label2","op":"add","value":"label2Value"}`, patchesBytes[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func TestProcessSamePatch_AddAndRemovePathsDontExist_ContinueOnError_EmptyResult(t *testing.T) {
|
||||||
|
// patch1 := types.PolicyPatch{Path: "/metadata/labels/label3", Operation: "add", Value: "label3Value"}
|
||||||
|
// patches := []types.PolicyPatch{patch1}
|
||||||
|
// patchesBytes, err := ProcessPatches(patches, []byte(endpointsDocument), PatchingSetsContinueAlways)
|
||||||
|
// assert.NilError(t, err)
|
||||||
|
// assert.Assert(t, len(patchesBytes) == 1)
|
||||||
|
// }
|
|
@ -1,4 +1,4 @@
|
||||||
package webhooks
|
package policymanager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -7,21 +7,21 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseMetadataFromObject(bytes []byte) map[string]interface{} {
|
func ParseMetadataFromObject(bytes []byte) map[string]interface{} {
|
||||||
var objectJSON map[string]interface{}
|
var objectJSON map[string]interface{}
|
||||||
json.Unmarshal(bytes, &objectJSON)
|
json.Unmarshal(bytes, &objectJSON)
|
||||||
|
|
||||||
return objectJSON["metadata"].(map[string]interface{})
|
return objectJSON["metadata"].(map[string]interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseKindFromObject(bytes []byte) string {
|
func ParseKindFromObject(bytes []byte) string {
|
||||||
var objectJSON map[string]interface{}
|
var objectJSON map[string]interface{}
|
||||||
json.Unmarshal(bytes, &objectJSON)
|
json.Unmarshal(bytes, &objectJSON)
|
||||||
|
|
||||||
return objectJSON["kind"].(string)
|
return objectJSON["kind"].(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseLabelsFromMetadata(meta map[string]interface{}) labels.Set {
|
func ParseLabelsFromMetadata(meta map[string]interface{}) labels.Set {
|
||||||
if interfaceMap, ok := meta["labels"].(map[string]interface{}); ok {
|
if interfaceMap, ok := meta["labels"].(map[string]interface{}); ok {
|
||||||
labelMap := make(labels.Set, len(interfaceMap))
|
labelMap := make(labels.Set, len(interfaceMap))
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ func parseLabelsFromMetadata(meta map[string]interface{}) labels.Set {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNameFromObject(bytes []byte) string {
|
func ParseNameFromObject(bytes []byte) string {
|
||||||
var objectJSON map[string]interface{}
|
var objectJSON map[string]interface{}
|
||||||
json.Unmarshal(bytes, &objectJSON)
|
json.Unmarshal(bytes, &objectJSON)
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ func parseNameFromObject(bytes []byte) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNamespaceFromObject(bytes []byte) string {
|
func ParseNamespaceFromObject(bytes []byte) string {
|
||||||
var objectJSON map[string]interface{}
|
var objectJSON map[string]interface{}
|
||||||
json.Unmarshal(bytes, &objectJSON)
|
json.Unmarshal(bytes, &objectJSON)
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ func parseNamespaceFromObject(bytes []byte) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if policyResourceName is a regexp
|
// returns true if policyResourceName is a regexp
|
||||||
func parseRegexPolicyResourceName(policyResourceName string) (string, bool) {
|
func ParseRegexPolicyResourceName(policyResourceName string) (string, bool) {
|
||||||
regex := strings.Split(policyResourceName, "regex:")
|
regex := strings.Split(policyResourceName, "regex:")
|
||||||
if len(regex) == 1 {
|
if len(regex) == 1 {
|
||||||
return regex[0], false
|
return regex[0], false
|
|
@ -1,4 +1,4 @@
|
||||||
package webhooks_test
|
package policymanager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
43
pkg/policymanager/validate.go
Normal file
43
pkg/policymanager/validate.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package policymanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/minio/minio/pkg/wildcard"
|
||||||
|
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// kind is the type of object being manipulated
|
||||||
|
// 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, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if resourceRaw != nil {
|
||||||
|
meta := ParseMetadataFromObject(resourceRaw)
|
||||||
|
name := ParseNameFromObject(resourceRaw)
|
||||||
|
|
||||||
|
if policyResource.Name != nil {
|
||||||
|
|
||||||
|
if !wildcard.Match(*policyResource.Name, name) {
|
||||||
|
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, nil
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
package webhooks
|
package webhooks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/minio/minio/pkg/wildcard"
|
|
||||||
kubeclient "github.com/nirmata/kube-policy/kubeclient"
|
kubeclient "github.com/nirmata/kube-policy/kubeclient"
|
||||||
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
||||||
|
policymanager "github.com/nirmata/kube-policy/pkg/policymanager"
|
||||||
"k8s.io/api/admission/v1beta1"
|
"k8s.io/api/admission/v1beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func kindIsSupported(kind string) bool {
|
func kindIsSupported(kind string) bool {
|
||||||
|
@ -25,41 +24,5 @@ func AdmissionIsRequired(request *v1beta1.AdmissionRequest) bool {
|
||||||
|
|
||||||
// Checks requests kind, name and labels to fit the policy
|
// Checks requests kind, name and labels to fit the policy
|
||||||
func IsRuleApplicableToRequest(policyResource types.PolicyResource, request *v1beta1.AdmissionRequest) (bool, error) {
|
func IsRuleApplicableToRequest(policyResource types.PolicyResource, request *v1beta1.AdmissionRequest) (bool, error) {
|
||||||
return IsRuleApplicableToResource(request.Kind.Kind, request.Object.Raw, policyResource)
|
return policymanager.IsRuleApplicableToResource(request.Kind.Kind, request.Object.Raw, policyResource)
|
||||||
}
|
|
||||||
|
|
||||||
// kind is the type of object being manipulated
|
|
||||||
// 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, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if resourceRaw != nil {
|
|
||||||
meta := parseMetadataFromObject(resourceRaw)
|
|
||||||
name := parseNameFromObject(resourceRaw)
|
|
||||||
|
|
||||||
if policyResource.Name != nil {
|
|
||||||
|
|
||||||
if !wildcard.Match(*policyResource.Name, name) {
|
|
||||||
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, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
controllerinterfaces "github.com/nirmata/kube-policy/controller/interfaces"
|
controllerinterfaces "github.com/nirmata/kube-policy/controller/interfaces"
|
||||||
kubeclient "github.com/nirmata/kube-policy/kubeclient"
|
kubeclient "github.com/nirmata/kube-policy/kubeclient"
|
||||||
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
||||||
|
policymanager "github.com/nirmata/kube-policy/pkg/policymanager"
|
||||||
v1beta1 "k8s.io/api/admission/v1beta1"
|
v1beta1 "k8s.io/api/admission/v1beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
@ -65,7 +66,7 @@ func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.Ad
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var allPatches []PatchBytes
|
var allPatches []policymanager.PatchBytes
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
mw.logger.Printf("Applying policy %s with %d rules", policy.ObjectMeta.Name, len(policy.Spec.Rules))
|
mw.logger.Printf("Applying policy %s with %d rules", policy.ObjectMeta.Name, len(policy.Spec.Rules))
|
||||||
|
|
||||||
|
@ -79,8 +80,8 @@ func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.Ad
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(policyPatches) > 0 {
|
if len(policyPatches) > 0 {
|
||||||
namespace := parseNamespaceFromObject(request.Object.Raw)
|
namespace := policymanager.ParseNamespaceFromObject(request.Object.Raw)
|
||||||
name := parseNameFromObject(request.Object.Raw)
|
name := policymanager.ParseNameFromObject(request.Object.Raw)
|
||||||
mw.controller.LogPolicyInfo(policy.Name, fmt.Sprintf("Applied to %s %s/%s", request.Kind.Kind, namespace, name))
|
mw.controller.LogPolicyInfo(policy.Name, fmt.Sprintf("Applied to %s %s/%s", request.Kind.Kind, namespace, name))
|
||||||
mw.logger.Printf("%s applied to %s %s/%s", policy.Name, request.Kind.Kind, namespace, name)
|
mw.logger.Printf("%s applied to %s %s/%s", policy.Name, request.Kind.Kind, namespace, name)
|
||||||
|
|
||||||
|
@ -91,31 +92,22 @@ func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.Ad
|
||||||
patchType := v1beta1.PatchTypeJSONPatch
|
patchType := v1beta1.PatchTypeJSONPatch
|
||||||
return &v1beta1.AdmissionResponse{
|
return &v1beta1.AdmissionResponse{
|
||||||
Allowed: true,
|
Allowed: true,
|
||||||
Patch: JoinPatches(allPatches),
|
Patch: policymanager.JoinPatches(allPatches),
|
||||||
PatchType: &patchType,
|
PatchType: &patchType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPolicyPatchingSets(policy types.Policy) PatchingSets {
|
|
||||||
// failurePolicy property is the only available way for now to define behavior on patching error.
|
|
||||||
// TODO: define new failurePolicy values specific for patching and other policy features.
|
|
||||||
if policy.Spec.FailurePolicy != nil && *policy.Spec.FailurePolicy == "continueOnError" {
|
|
||||||
return PatchingSetsContinueAlways
|
|
||||||
}
|
|
||||||
return PatchingSetsDefault
|
|
||||||
}
|
|
||||||
|
|
||||||
// Applies all policy rules to the created object and returns list of processed JSON patches.
|
// 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.
|
// 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.
|
// 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) ([]policymanager.PatchBytes, error) {
|
||||||
return mw.applyPolicyRulesOnResource(request.Kind.Kind, request.Object.Raw, policy)
|
return mw.applyPolicyRulesOnResource(request.Kind.Kind, request.Object.Raw, policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// kind is the type of object being manipulated
|
// 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) ([]policymanager.PatchBytes, error) {
|
||||||
patchingSets := getPolicyPatchingSets(policy)
|
patchingSets := policymanager.GetPolicyPatchingSets(policy)
|
||||||
var policyPatches []PatchBytes
|
var policyPatches []policymanager.PatchBytes
|
||||||
|
|
||||||
for ruleIdx, rule := range policy.Spec.Rules {
|
for ruleIdx, rule := range policy.Spec.Rules {
|
||||||
err := rule.Validate()
|
err := rule.Validate()
|
||||||
|
@ -124,7 +116,7 @@ func (mw *MutationWebhook) applyPolicyRulesOnResource(kind string, rawResource [
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok, err := IsRuleApplicableToResource(kind, rawResource, rule.Resource); !ok {
|
if ok, err := policymanager.IsRuleApplicableToResource(kind, rawResource, rule.Resource); !ok {
|
||||||
mw.logger.Printf("Rule %d of policy %s is not applicable to the request", ruleIdx, policy.Name)
|
mw.logger.Printf("Rule %d of policy %s is not applicable to the request", ruleIdx, policy.Name)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -132,12 +124,12 @@ func (mw *MutationWebhook) applyPolicyRulesOnResource(kind string, rawResource [
|
||||||
// configMapGenerator and secretGenerator can be applied only to namespaces
|
// configMapGenerator and secretGenerator can be applied only to namespaces
|
||||||
if kind == "Namespace" {
|
if kind == "Namespace" {
|
||||||
err = mw.applyRuleGenerators(rawResource, rule)
|
err = mw.applyRuleGenerators(rawResource, rule)
|
||||||
if err != nil && patchingSets == PatchingSetsStopOnError {
|
if err != nil && patchingSets == policymanager.PatchingSetsStopOnError {
|
||||||
return nil, fmt.Errorf("Failed to apply generators from rule #%d: %s", ruleIdx, err)
|
return nil, fmt.Errorf("Failed to apply generators from rule #%d: %s", ruleIdx, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rulePatchesProcessed, err := ProcessPatches(rule.Patches, rawResource, patchingSets)
|
rulePatchesProcessed, err := policymanager.ProcessPatches(rule.Patches, rawResource, patchingSets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to process patches from rule #%d: %s", ruleIdx, err)
|
return nil, fmt.Errorf("Failed to process patches from rule #%d: %s", ruleIdx, err)
|
||||||
}
|
}
|
||||||
|
@ -160,7 +152,7 @@ func (mw *MutationWebhook) applyPolicyRulesOnResource(kind string, rawResource [
|
||||||
|
|
||||||
// Applies "configMapGenerator" and "secretGenerator" described in PolicyRule
|
// Applies "configMapGenerator" and "secretGenerator" described in PolicyRule
|
||||||
func (mw *MutationWebhook) applyRuleGenerators(rawResource []byte, rule types.PolicyRule) error {
|
func (mw *MutationWebhook) applyRuleGenerators(rawResource []byte, rule types.PolicyRule) error {
|
||||||
namespaceName := parseNameFromObject(rawResource)
|
namespaceName := policymanager.ParseNameFromObject(rawResource)
|
||||||
|
|
||||||
err := mw.applyConfigGenerator(rule.ConfigMapGenerator, namespaceName, "ConfigMap")
|
err := mw.applyConfigGenerator(rule.ConfigMapGenerator, namespaceName, "ConfigMap")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
Loading…
Reference in a new issue