mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-07 15:17:03 +02:00
Merge pull request #2108 from hashicorp/f-req-size-limit
http: limit maximum request size
This commit is contained in:
commit
300b72e75c
@ -26,6 +26,11 @@ const (
|
|||||||
// NoRequestForwardingHeaderName is the name of the header telling Vault
|
// NoRequestForwardingHeaderName is the name of the header telling Vault
|
||||||
// not to use request forwarding
|
// not to use request forwarding
|
||||||
NoRequestForwardingHeaderName = "X-Vault-No-Request-Forwarding"
|
NoRequestForwardingHeaderName = "X-Vault-No-Request-Forwarding"
|
||||||
|
|
||||||
|
// MaxRequestSize is the maximum accepted request size. This is to prevent
|
||||||
|
// a denial of service attack where no Content-Length is provided and the server
|
||||||
|
// is fed ever more data until it exhausts memory.
|
||||||
|
MaxRequestSize = 32 * 1024 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler returns an http.Handler for the API. This can be used on
|
// Handler returns an http.Handler for the API. This can be used on
|
||||||
@ -109,7 +114,10 @@ func stripPrefix(prefix, path string) (string, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseRequest(r *http.Request, out interface{}) error {
|
func parseRequest(r *http.Request, out interface{}) error {
|
||||||
err := jsonutil.DecodeJSONFromReader(r.Body, out)
|
// Limit the maximum number of bytes to MaxRequestSize to protect
|
||||||
|
// against an indefinite amount of data being read.
|
||||||
|
limit := &io.LimitedReader{R: r.Body, N: MaxRequestSize}
|
||||||
|
err := jsonutil.DecodeJSONFromReader(limit, out)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
return fmt.Errorf("Failed to parse JSON input: %s", err)
|
return fmt.Errorf("Failed to parse JSON input: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,11 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques
|
|||||||
return nil, http.StatusNotFound, nil
|
return nil, http.StatusNotFound, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify the content length does not exceed the maximum size
|
||||||
|
if r.ContentLength >= MaxRequestSize {
|
||||||
|
return nil, http.StatusRequestEntityTooLarge, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Determine the operation
|
// Determine the operation
|
||||||
var op logical.Operation
|
var op logical.Operation
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
|
@ -231,3 +231,16 @@ func TestLogical_RawHTTP(t *testing.T) {
|
|||||||
t.Fatalf("Bad: %s", body.Bytes())
|
t.Fatalf("Bad: %s", body.Bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLogical_RequestSizeLimit(t *testing.T) {
|
||||||
|
core, _, token := vault.TestCoreUnsealed(t)
|
||||||
|
ln, addr := TestServer(t, core)
|
||||||
|
defer ln.Close()
|
||||||
|
TestServerAuth(t, addr, token)
|
||||||
|
|
||||||
|
// Write a very large object, should fail
|
||||||
|
resp := testHttpPut(t, token, addr+"/v1/secret/foo", map[string]interface{}{
|
||||||
|
"data": make([]byte, MaxRequestSize),
|
||||||
|
})
|
||||||
|
testResponseStatus(t, resp, 413)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user