fix: echo request TypeMeta in admission response to comply with Kubernetes webhook spec#304
Open
dom-colangelo wants to merge 1 commit into
Open
Conversation
…h json.Unmarshal
The webhook was returning AdmissionReview responses with an empty
apiVersion and kind, causing API servers (including K3s and vanilla
upstream Kubernetes) to reject the webhook response with:
"received invalid webhook response: got /, Kind="
Root cause: the response AdmissionReview struct was never given a
TypeMeta, so it serialized as {"response": ...} with no apiVersion or
kind fields. EKS patches its API server to tolerate missing TypeMeta,
but upstream Kubernetes strictly requires it.
Fix: copy ar.TypeMeta into the response before marshalling, so the
response echoes back whatever apiVersion/kind the request carried.
The deserializer.Decode call is also replaced with json.Unmarshal.
The old codec scheme only registered corev1 and
admissionregistrationv1beta1, not admission/v1 or admission/v1beta1,
so decode would fail on v1 AdmissionReview requests from Kubernetes
>= 1.16. json.Unmarshal decodes both v1beta1 and v1 payloads without
a registered scheme.
The runtimeScheme/codecs/deserializer package-level vars and the init()
that populated the scheme are removed as they are no longer used.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Kubernetes webhook specification requires that a webhook response include the same
apiVersionandkindas the request. The handler was building the responseAdmissionReviewstruct without copying TypeMeta from the request, so every response serialized as:{"response": {"uid": "...", "allowed": true, "patch": "..."}}API servers enforce this strictly:
This is a known issue — see #225, where an EKS cluster upgraded to Kubernetes 1.27 with
admissionReviewVersions: v1began rejecting webhook responses and injection stopped working. The only workaround was to downgrade tov1beta1. The root cause is the same: when the API server negotiates v1, the response comes back with an emptyapiVersion/kindand is rejected.A related issue:
deserializer.Decodeused a codec scheme that registered onlycorev1andadmissionregistrationv1beta1— not the admission API types. Any cluster sendingadmission.k8s.io/v1requests would fail to decode before mutation ran.Fix
pkg/handler/handler.goar.TypeMetainto the response struct before marshalling — the response echoes back whateverapiVersion/kindthe request carried, as the spec requires.deserializer.Decodewithjson.Unmarshal.json.Unmarshaldecodes bothv1andv1beta1payloads correctly without a registered scheme. The old codec scheme did not include the admission API types, so it was incapable of decoding v1 requests.runtimeScheme,codecs,deserializerpackage vars andinit().pkg/handler/handler_test.gojson.Unmarshalerror strings.ValidRequestV1TypeMetaEchoed: sends anAdmissionReviewwithapiVersion: admission.k8s.io/v1and asserts the response echoes it back.Testing
All tests pass.
Related
admissionReviewVersions: v1; workaround was to forcev1beta1