Skip to content

Commit 902eccc

Browse files
authored
Add delete validation to the webhook and ignore marshalling (kptdev#1114)
* Add delete validation to the webhook and ignore marshalling Signed-off-by: Kushal Harish Naidu <kushal.harish.naidu@ericsson.com> * Check for error during response write Signed-off-by: Kushal Harish Naidu <kushal.harish.naidu@ericsson.com> * Add unit test to cover repo delete validation Signed-off-by: Kushal Harish Naidu <kushal.harish.naidu@ericsson.com> --------- Signed-off-by: Kushal Harish Naidu <kushal.harish.naidu@ericsson.com>
1 parent 27408d6 commit 902eccc

2 files changed

Lines changed: 60 additions & 0 deletions

File tree

pkg/apiserver/webhooks.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ func createValidatingWebhook(ctx context.Context, cfg *WebhookConfig, caCert []b
291291
Operations: []admissionregistrationv1.OperationType{
292292
admissionregistrationv1.Create,
293293
admissionregistrationv1.Update,
294+
admissionregistrationv1.Delete,
294295
},
295296
Rule: admissionregistrationv1.Rule{
296297
APIGroups: []string{configapi.GroupVersion.Group},
@@ -520,6 +521,31 @@ func validateRepository(w http.ResponseWriter, r *http.Request, clientReader cli
520521
return
521522
}
522523

524+
// For DELETE operations, Object.Raw is empty — the API server sends the object in OldObject.
525+
// No conflict detection needed for deletes, just allow them through.
526+
if admissionReviewRequest.Request.Operation == admissionv1.Delete {
527+
klog.Infof("repository deletion validated for %s", repoName)
528+
resp := &admissionv1.AdmissionResponse{
529+
Allowed: true,
530+
Result: &metav1.Status{
531+
Status: "Success",
532+
Message: "Repository deletion validated successfully",
533+
},
534+
}
535+
responseBytes, err := constructResponse(resp, admissionReviewRequest)
536+
if err != nil {
537+
writeErr(fmt.Sprintf("error constructing response: %v", err), &w)
538+
return
539+
}
540+
w.Header().Set("Content-Type", "application/json")
541+
_, err = w.Write(responseBytes) // #nosec G705
542+
if err != nil {
543+
klog.Errorf("error writing response: %v", err)
544+
return
545+
}
546+
return
547+
}
548+
523549
var attempted configapi.Repository
524550
if err := json.Unmarshal(admissionReviewRequest.Request.Object.Raw, &attempted); err != nil {
525551
klog.Errorf("failed to unmarshal repository object: %v", err)

pkg/apiserver/webhooks_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,40 @@ func TestValidateRepository(t *testing.T) {
372372
response.Body.String())
373373
})
374374

375+
t.Run("delete operation skips unmarshal and allows", func(t *testing.T) {
376+
admissionReview := admissionv1.AdmissionReview{
377+
TypeMeta: v1.TypeMeta{
378+
Kind: "AdmissionReview",
379+
APIVersion: "admission.k8s.io/v1",
380+
},
381+
Request: &admissionv1.AdmissionRequest{
382+
UID: "delete-123",
383+
Resource: v1.GroupVersionResource{
384+
Group: "config.porch.kpt.dev",
385+
Version: "v1alpha1",
386+
Resource: "repositories",
387+
},
388+
Operation: admissionv1.Delete,
389+
Name: "my-repo",
390+
Namespace: "test-ns",
391+
// Object.Raw is empty on DELETE — this is the scenario that was failing
392+
OldObject: runtime.RawExtension{Raw: []byte(`{"metadata":{"name":"my-repo","namespace":"test-ns"}}`)},
393+
},
394+
}
395+
body, err := json.Marshal(admissionReview)
396+
require.NoError(t, err)
397+
398+
request, err := http.NewRequest(http.MethodPost, repositoryValidationEndpoint, bytes.NewReader(body))
399+
require.NoError(t, err)
400+
request.Header.Set("Content-Type", "application/json")
401+
402+
response := httptest.NewRecorder()
403+
validateRepository(response, request, fakeClient)
404+
405+
require.Equal(t, http.StatusOK, response.Code)
406+
require.Contains(t, response.Body.String(), "Repository deletion validated successfully")
407+
})
408+
375409
createAdmissionReview := func(name, namespace, gitURL, directory, branch string) []byte {
376410
repo := configapi.Repository{
377411
ObjectMeta: v1.ObjectMeta{

0 commit comments

Comments
 (0)