mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-21 08:47:16 +00:00
Configure JSON content type for generic webhook RESTClient.
Authorization, token authentication, imagepolicy admission, and audit webhooks configure RESTClients that encode to JSON regardless of the ContentType of the provided rest.Config. Because this is opaque to the RESTClient, configuring a ContentType other than "application/json" results in requests with JSON-encoded bodies and a non-JSON media type in the Content-Type header. Webhook servers that respect the Content-Type request header will be unable to decode an object from the request body. Explicitly overriding the ContentType of the provided rest.Config fixes this issue and is consistent with how clients are constructed for conversion and admission webhooks.
This commit is contained in:
@@ -83,6 +83,7 @@ func NewGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFact
|
||||
clientConfig := rest.CopyConfig(config)
|
||||
|
||||
codec := codecFactory.LegacyCodec(groupVersions...)
|
||||
clientConfig.ContentType = runtime.ContentTypeJSON
|
||||
clientConfig.ContentConfig.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})
|
||||
|
||||
clientConfig.Wrap(x509metrics.NewDeprecatedCertificateRoundTripperWrapperConstructor(
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -33,11 +34,15 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
exampleinstall "k8s.io/apiserver/pkg/apis/example/install"
|
||||
examplev1 "k8s.io/apiserver/pkg/apis/example/v1"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
v1 "k8s.io/client-go/tools/clientcmd/api/v1"
|
||||
@@ -927,3 +932,57 @@ func getSingleCounterValueFromRegistry(t *testing.T, r metrics.Gatherer, name st
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
func TestRESTConfigContentType(t *testing.T) {
|
||||
server, err := newTestServer(clientCert, clientKey, caCert, func(w http.ResponseWriter, r *http.Request) {
|
||||
if got := r.Header.Get("Content-Type"); got != runtime.ContentTypeJSON {
|
||||
t.Errorf("expected request content-type: want %q got %q", runtime.ContentTypeJSON, got)
|
||||
}
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
t.Errorf("failed to read request body: %v", err)
|
||||
return
|
||||
}
|
||||
if err := json.Unmarshal(body, new(any)); err != nil {
|
||||
switch {
|
||||
case len(body) == 0:
|
||||
t.Log("empty request body")
|
||||
case utf8.Valid(body):
|
||||
t.Logf("request body: %s", string(body))
|
||||
default:
|
||||
t.Logf("request body: 0x%x", body)
|
||||
}
|
||||
t.Errorf("failed to unmarshal request body as json: %v", err)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("failed to create server: %v", err)
|
||||
return
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
config := &rest.Config{
|
||||
ContentConfig: rest.ContentConfig{
|
||||
ContentType: "foo/bar",
|
||||
},
|
||||
Host: server.URL,
|
||||
TLSClientConfig: rest.TLSClientConfig{
|
||||
CAData: caCert,
|
||||
CertData: clientCert,
|
||||
KeyData: clientKey,
|
||||
},
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
exampleinstall.Install(scheme)
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
groupVersions := []schema.GroupVersion{examplev1.SchemeGroupVersion}
|
||||
wh, err := NewGenericWebhook(scheme, codecs, config, groupVersions, retryBackoff)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create the webhook: %v", err)
|
||||
}
|
||||
|
||||
if err := wh.RestClient.Post().Body(&examplev1.Pod{}).Do(context.TODO()).Error(); err != nil {
|
||||
t.Fatalf("failed to complete request: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user