Skip to content

Commit

Permalink
Enforce max request body size on channel participation join (hyperled…
Browse files Browse the repository at this point in the history
…ger#1434)

FAB-17895 #done

Signed-off-by: Will Lahti <[email protected]>
  • Loading branch information
wlahti committed Jul 8, 2020
1 parent 18c933c commit 2f8723b
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 9 deletions.
3 changes: 2 additions & 1 deletion integration/nwo/fabricconfig/orderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,6 @@ type OrdererStatsd struct {
}

type ChannelParticipation struct {
Enabled bool `yaml:"Enabled"`
Enabled bool `yaml:"Enabled"`
MaxRequestBodySize string `yaml:"MaxRequestBodySize,omitempty"`
}
1 change: 1 addition & 0 deletions integration/nwo/orderer_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,5 @@ Metrics:
{{- end }}
ChannelParticipation:
Enabled: {{ .ChannelParticipationEnabled }}
MaxRequestBodySize: 1 MB
`
8 changes: 5 additions & 3 deletions orderer/common/channelparticipation/restapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ type HTTPHandler struct {
config localconfig.ChannelParticipation
registrar ChannelManagement
router *mux.Router
// TODO skeleton
}

func NewHTTPHandler(config localconfig.ChannelParticipation, registrar ChannelManagement) *HTTPHandler {
Expand Down Expand Up @@ -192,8 +191,11 @@ func (h *HTTPHandler) serveJoin(resp http.ResponseWriter, req *http.Request) {
// Expect a multipart/form-data with a single part, of type file, with key FormDataConfigBlockKey.
func (h *HTTPHandler) multipartFormDataBodyToBlock(params map[string]string, req *http.Request, resp http.ResponseWriter) *cb.Block {
boundary := params["boundary"]
reader := multipart.NewReader(req.Body, boundary)
form, err := reader.ReadForm(100 * 1024 * 1024)
reader := multipart.NewReader(
http.MaxBytesReader(resp, req.Body, int64(h.config.MaxRequestBodySize)),
boundary,
)
form, err := reader.ReadForm(2 * int64(h.config.MaxRequestBodySize))
if err != nil {
h.sendResponseJsonError(resp, http.StatusBadRequest, errors.Wrap(err, "cannot read form from request body"))
return nil
Expand Down
18 changes: 17 additions & 1 deletion orderer/common/channelparticipation/restapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,11 @@ func TestHTTPHandler_ServeHTTP_ListSingle(t *testing.T) {
}

func TestHTTPHandler_ServeHTTP_Join(t *testing.T) {
config := localconfig.ChannelParticipation{Enabled: true, RemoveStorage: false}
config := localconfig.ChannelParticipation{
Enabled: true,
RemoveStorage: false,
MaxRequestBodySize: 1024 * 1024,
}

t.Run("created ok", func(t *testing.T) {
fakeManager, h := setup(config, t)
Expand Down Expand Up @@ -393,6 +397,18 @@ func TestHTTPHandler_ServeHTTP_Join(t *testing.T) {
h.ServeHTTP(resp, req)
checkErrorResponse(t, http.StatusBadRequest, "form contains too many parts", resp)
})

t.Run("body larger that MaxRequestBodySize", func(t *testing.T) {
config := localconfig.ChannelParticipation{
Enabled: true,
MaxRequestBodySize: 1,
}
_, h := setup(config, t)
resp := httptest.NewRecorder()
req := genJoinRequestFormData(t, []byte{1, 2, 3, 4})
h.ServeHTTP(resp, req)
checkErrorResponse(t, http.StatusBadRequest, "cannot read form from request body: multipart: NextPart: http: request body too large", resp)
})
}

func TestHTTPHandler_ServeHTTP_Remove(t *testing.T) {
Expand Down
10 changes: 6 additions & 4 deletions orderer/common/localconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,9 @@ type Statsd struct {
// ChannelParticipation provides the channel participation API configuration for the orderer.
// Channel participation uses the same ListenAddress and TLS settings of the Operations service.
type ChannelParticipation struct {
Enabled bool
RemoveStorage bool // Whether to permanently remove storage on channel removal.
Enabled bool
RemoveStorage bool // Whether to permanently remove storage on channel removal.
MaxRequestBodySize uint32
}

// Defaults carries the default orderer configuration values.
Expand Down Expand Up @@ -284,8 +285,9 @@ var Defaults = TopLevel{
Provider: "disabled",
},
ChannelParticipation: ChannelParticipation{
Enabled: false,
RemoveStorage: false,
Enabled: false,
RemoveStorage: false,
MaxRequestBodySize: 1024 * 1024,
},
}

Expand Down
3 changes: 3 additions & 0 deletions sampleconfig/orderer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,9 @@ ChannelParticipation:
# Defines the default behavior of channel removal.
RemoveStorage: false

# The maximum size of the request body when joining a channel.
MaxRequestBodySize: 1 MB


################################################################################
#
Expand Down

0 comments on commit 2f8723b

Please sign in to comment.