Skip to content

Commit a169f8b

Browse files
committed
add missing limitedReader
Signed-off-by: Tim Ramlot <[email protected]>
1 parent 13c946d commit a169f8b

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-2
lines changed

pkg/webhook/admission/http.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ import (
3434
var admissionScheme = runtime.NewScheme()
3535
var admissionCodecs = serializer.NewCodecFactory(admissionScheme)
3636

37+
// based on https://github.com/kubernetes/kubernetes/blob/c28c2009181fcc44c5f6b47e10e62dacf53e4da0/staging/src/k8s.io/pod-security-admission/cmd/webhook/server/server.go
38+
var maxRequestSize = int64(3 * 1024 * 1024)
39+
3740
func init() {
3841
utilruntime.Must(v1.AddToScheme(admissionScheme))
3942
utilruntime.Must(v1beta1.AddToScheme(admissionScheme))
@@ -55,12 +58,19 @@ func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5558
}
5659

5760
defer r.Body.Close()
58-
body, err := io.ReadAll(r.Body)
61+
limitedReader := &io.LimitedReader{R: r.Body, N: maxRequestSize}
62+
body, err := io.ReadAll(limitedReader)
5963
if err != nil {
6064
wh.getLogger(nil).Error(err, "unable to read the body from the incoming request")
6165
wh.writeResponse(w, Errored(http.StatusBadRequest, err))
6266
return
6367
}
68+
if limitedReader.N <= 0 {
69+
err := fmt.Errorf("request entity is too large; limit is %d bytes", maxRequestSize)
70+
wh.getLogger(nil).Error(err, "unable to read the body from the incoming request; limit reached")
71+
wh.writeResponse(w, Errored(http.StatusBadRequest, err))
72+
return
73+
}
6474

6575
// verify the content type is accurate
6676
if contentType := r.Header.Get("Content-Type"); contentType != "application/json" {

pkg/webhook/admission/http_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package admission
1919
import (
2020
"bytes"
2121
"context"
22+
"crypto/rand"
2223
"fmt"
2324
"io"
2425
"net/http"
@@ -84,6 +85,19 @@ var _ = Describe("Admission Webhooks", func() {
8485
Expect(respRecorder.Body.String()).To(Equal(expected))
8586
})
8687

88+
It("should error when given an infinite body", func() {
89+
req := &http.Request{
90+
Header: http.Header{"Content-Type": []string{"application/json"}},
91+
Method: http.MethodPost,
92+
Body: nopCloser{Reader: rand.Reader},
93+
}
94+
95+
expected := `{"response":{"uid":"","allowed":false,"status":{"metadata":{},"message":"request entity is too large; limit is 3145728 bytes","code":400}}}
96+
`
97+
webhook.ServeHTTP(respRecorder, req)
98+
Expect(respRecorder.Body.String()).To(Equal(expected))
99+
})
100+
87101
It("should return the response given by the handler with version defaulted to v1", func() {
88102
req := &http.Request{
89103
Header: http.Header{"Content-Type": []string{"application/json"}},

pkg/webhook/authentication/http.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ import (
3434
var authenticationScheme = runtime.NewScheme()
3535
var authenticationCodecs = serializer.NewCodecFactory(authenticationScheme)
3636

37+
// based on https://github.com/kubernetes/kubernetes/blob/c28c2009181fcc44c5f6b47e10e62dacf53e4da0/staging/src/k8s.io/pod-security-admission/cmd/webhook/server/server.go
38+
var maxRequestSize = int64(3 * 1024 * 1024)
39+
3740
func init() {
3841
utilruntime.Must(authenticationv1.AddToScheme(authenticationScheme))
3942
utilruntime.Must(authenticationv1beta1.AddToScheme(authenticationScheme))
@@ -55,12 +58,19 @@ func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5558
}
5659

5760
defer r.Body.Close()
58-
body, err := io.ReadAll(r.Body)
61+
limitedReader := &io.LimitedReader{R: r.Body, N: maxRequestSize}
62+
body, err := io.ReadAll(limitedReader)
5963
if err != nil {
6064
wh.getLogger(nil).Error(err, "unable to read the body from the incoming request")
6165
wh.writeResponse(w, Errored(err))
6266
return
6367
}
68+
if limitedReader.N <= 0 {
69+
err := fmt.Errorf("request entity is too large; limit is %d bytes", maxRequestSize)
70+
wh.getLogger(nil).Error(err, "unable to read the body from the incoming request; limit reached")
71+
wh.writeResponse(w, Errored(err))
72+
return
73+
}
6474

6575
// verify the content type is accurate
6676
if contentType := r.Header.Get("Content-Type"); contentType != "application/json" {

pkg/webhook/authentication/http_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package authentication
1919
import (
2020
"bytes"
2121
"context"
22+
"crypto/rand"
2223
"fmt"
2324
"io"
2425
"net/http"
@@ -94,6 +95,19 @@ var _ = Describe("Authentication Webhooks", func() {
9495
Expect(respRecorder.Body.String()).To(Equal(expected))
9596
})
9697

98+
It("should error when given an infinite body", func() {
99+
req := &http.Request{
100+
Header: http.Header{"Content-Type": []string{"application/json"}},
101+
Method: http.MethodPost,
102+
Body: nopCloser{Reader: rand.Reader},
103+
}
104+
105+
expected := `{"metadata":{"creationTimestamp":null},"spec":{},"status":{"user":{},"error":"request entity is too large; limit is 3145728 bytes"}}
106+
`
107+
webhook.ServeHTTP(respRecorder, req)
108+
Expect(respRecorder.Body.String()).To(Equal(expected))
109+
})
110+
97111
It("should return the response given by the handler with version defaulted to v1", func() {
98112
req := &http.Request{
99113
Header: http.Header{"Content-Type": []string{"application/json"}},

0 commit comments

Comments
 (0)