diff --git a/pkg/webhook/policy.go b/pkg/webhook/policy.go index be6830957a2..6d4eaebd5cb 100644 --- a/pkg/webhook/policy.go +++ b/pkg/webhook/policy.go @@ -336,6 +336,11 @@ func (h *validationHandler) getValidationMessages(res []*rtypes.Result, req *adm // validateGatekeeperResources returns whether an issue is user error (vs internal) and any errors // validating internal resources. func (h *validationHandler) validateGatekeeperResources(ctx context.Context, req *admission.Request) (bool, error) { + if req.Operation == admissionv1.Delete && req.Name == "" { + // Allow the general DELETE of resources like "/apis/config.gatekeeper.sh/v1alpha1/namespaces//configs" + return true, nil + } + gvk := req.AdmissionRequest.Kind switch { @@ -349,15 +354,15 @@ func (h *validationHandler) validateGatekeeperResources(ctx context.Context, req if err := h.validateConfigResource(req); err != nil { return true, err } - case req.AdmissionRequest.Kind.Group == mutationsGroup && req.AdmissionRequest.Kind.Kind == "AssignMetadata": + case gvk.Group == mutationsGroup && gvk.Kind == "AssignMetadata": return h.validateAssignMetadata(req) - case req.AdmissionRequest.Kind.Group == mutationsGroup && req.AdmissionRequest.Kind.Kind == "Assign": + case gvk.Group == mutationsGroup && gvk.Kind == "Assign": return h.validateAssign(req) - case req.AdmissionRequest.Kind.Group == mutationsGroup && req.AdmissionRequest.Kind.Kind == "ModifySet": + case gvk.Group == mutationsGroup && gvk.Kind == "ModifySet": return h.validateModifySet(req) - case req.AdmissionRequest.Kind.Group == mutationsGroup && req.AdmissionRequest.Kind.Kind == "AssignImage": + case gvk.Group == mutationsGroup && gvk.Kind == "AssignImage": return h.validateAssignImage(req) - case req.AdmissionRequest.Kind.Group == externalDataGroup && req.AdmissionRequest.Kind.Kind == "Provider": + case gvk.Group == externalDataGroup && gvk.Kind == "Provider": return h.validateProvider(req) } diff --git a/pkg/webhook/policy_test.go b/pkg/webhook/policy_test.go index d3c87f8ede7..024ce6382b3 100644 --- a/pkg/webhook/policy_test.go +++ b/pkg/webhook/policy_test.go @@ -11,6 +11,7 @@ import ( "github.com/open-policy-agent/frameworks/constraint/pkg/core/templates" rtypes "github.com/open-policy-agent/frameworks/constraint/pkg/types" "github.com/open-policy-agent/gatekeeper/v3/apis/config/v1alpha1" + configv1alpha1 "github.com/open-policy-agent/gatekeeper/v3/apis/config/v1alpha1" "github.com/open-policy-agent/gatekeeper/v3/pkg/controller/config/process" "github.com/open-policy-agent/gatekeeper/v3/pkg/expansion" "github.com/open-policy-agent/gatekeeper/v3/pkg/mutation" @@ -811,36 +812,51 @@ func TestGetValidationMessages(t *testing.T) { func TestValidateConfigResource(t *testing.T) { tc := []struct { - TestName string - Name string - Err bool + name string + rName string + deleteOp bool + expectErr bool }{ { - TestName: "Wrong name", - Name: "FooBar", - Err: true, + name: "Wrong name", + rName: "FooBar", + expectErr: true, }, { - TestName: "Correct name", - Name: "config", + name: "Correct name", + rName: "config", + }, + { + name: "Delete operation with no name", + deleteOp: true, + }, + { + name: "Delete operation with name", + deleteOp: true, + rName: "abc", + expectErr: true, }, } for _, tt := range tc { - t.Run(tt.TestName, func(t *testing.T) { + t.Run(tt.name, func(t *testing.T) { handler := validationHandler{log: log} req := &admission.Request{ AdmissionRequest: admissionv1.AdmissionRequest{ - Name: tt.Name, + Name: tt.rName, + Kind: metav1.GroupVersionKind(configv1alpha1.GroupVersion.WithKind("Config")), }, } + if tt.deleteOp { + req.AdmissionRequest.Operation = admissionv1.Delete + } - err := handler.validateConfigResource(req) + _, err := handler.validateGatekeeperResources(context.Background(), req) - if tt.Err && err == nil { + if tt.expectErr && err == nil { t.Errorf("Expected error but received nil") } - if !tt.Err && err != nil { + if !tt.expectErr && err != nil { t.Errorf("Did not expect error but received: %v", err) } })