Impose a size limit on JSON request body
The size limit on JSON request body is to ensure the server not being overwhelmed by extremly large JSON request body. Fixes bug #1215501 Change-Id: Ia58f6690e994d34212953c44821f7a4cc4c435fe
This commit is contained in:
parent
20a8a08333
commit
d899f8d9b7
@ -75,6 +75,15 @@
|
|||||||
#auth_encryption_key=notgood but just long enough i think
|
#auth_encryption_key=notgood but just long enough i think
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Options defined in heat.common.wsgi
|
||||||
|
#
|
||||||
|
|
||||||
|
# Maximum raw byte size of JSON request body. Should be larger
|
||||||
|
# than max_template_size. (integer value)
|
||||||
|
#max_json_body_size=1048576
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Options defined in heat.db.api
|
# Options defined in heat.db.api
|
||||||
#
|
#
|
||||||
|
@ -330,3 +330,7 @@ class StackRecursionLimitReached(HeatException):
|
|||||||
def __init__(self, recursion_depth):
|
def __init__(self, recursion_depth):
|
||||||
self.message = self.message % recursion_depth
|
self.message = self.message % recursion_depth
|
||||||
super(StackRecursionLimitReached, self).__init__()
|
super(StackRecursionLimitReached, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
|
class RequestLimitExceeded(HeatException):
|
||||||
|
message = _('Request limit exceeded: %(message)s')
|
||||||
|
@ -137,6 +137,12 @@ cfg.CONF.register_group(api_cw_group)
|
|||||||
cfg.CONF.register_opts(api_cw_opts,
|
cfg.CONF.register_opts(api_cw_opts,
|
||||||
group=api_cw_group)
|
group=api_cw_group)
|
||||||
|
|
||||||
|
json_size_opt = cfg.IntOpt('max_json_body_size',
|
||||||
|
default=1048576,
|
||||||
|
help='Maximum raw byte size of JSON request body.'
|
||||||
|
' Should be larger than max_template_size.')
|
||||||
|
cfg.CONF.register_opt(json_size_opt)
|
||||||
|
|
||||||
|
|
||||||
class WritableLogger(object):
|
class WritableLogger(object):
|
||||||
"""A thin wrapper that responds to `write` and logs."""
|
"""A thin wrapper that responds to `write` and logs."""
|
||||||
@ -524,6 +530,12 @@ class JSONRequestDeserializer(object):
|
|||||||
|
|
||||||
def from_json(self, datastring):
|
def from_json(self, datastring):
|
||||||
try:
|
try:
|
||||||
|
if len(datastring) > cfg.CONF.max_json_body_size:
|
||||||
|
msg = _('JSON body size (%(len)s bytes) exceeds maximum '
|
||||||
|
'allowed size (%(limit)s bytes).') % \
|
||||||
|
{'len': len(datastring),
|
||||||
|
'limit': cfg.CONF.max_json_body_size}
|
||||||
|
raise exception.RequestLimitExceeded(message=msg)
|
||||||
return json.loads(datastring)
|
return json.loads(datastring)
|
||||||
except ValueError as ex:
|
except ValueError as ex:
|
||||||
raise webob.exc.HTTPBadRequest(str(ex))
|
raise webob.exc.HTTPBadRequest(str(ex))
|
||||||
@ -638,11 +650,10 @@ class Resource(object):
|
|||||||
# ContentType=JSON results in a JSON serialized response...
|
# ContentType=JSON results in a JSON serialized response...
|
||||||
content_type = request.params.get("ContentType")
|
content_type = request.params.get("ContentType")
|
||||||
|
|
||||||
deserialized_request = self.dispatch(self.deserializer,
|
|
||||||
action, request)
|
|
||||||
action_args.update(deserialized_request)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
deserialized_request = self.dispatch(self.deserializer,
|
||||||
|
action, request)
|
||||||
|
action_args.update(deserialized_request)
|
||||||
action_result = self.dispatch(self.controller, action,
|
action_result = self.dispatch(self.controller, action,
|
||||||
request, **action_args)
|
request, **action_args)
|
||||||
except TypeError as err:
|
except TypeError as err:
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
|
from oslo.config import cfg
|
||||||
import stubout
|
import stubout
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
@ -380,3 +382,15 @@ class JSONRequestDeserializerTest(HeatTestCase):
|
|||||||
actual = wsgi.JSONRequestDeserializer().default(request)
|
actual = wsgi.JSONRequestDeserializer().default(request)
|
||||||
expected = {"body": {"key": "value"}}
|
expected = {"body": {"key": "value"}}
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
|
def test_from_json_exceeds_max_json_mb(self):
|
||||||
|
cfg.CONF.set_override('max_json_body_size', 10)
|
||||||
|
body = json.dumps(['a'] * cfg.CONF.max_json_body_size)
|
||||||
|
self.assertTrue(len(body) > cfg.CONF.max_json_body_size)
|
||||||
|
error = self.assertRaises(exception.RequestLimitExceeded,
|
||||||
|
wsgi.JSONRequestDeserializer().from_json,
|
||||||
|
body)
|
||||||
|
msg = 'Request limit exceeded: JSON body size ' + \
|
||||||
|
'(%s bytes) exceeds maximum allowed size (%s bytes).' % \
|
||||||
|
(len(body), cfg.CONF.max_json_body_size)
|
||||||
|
self.assertEqual(msg, str(error))
|
||||||
|
Loading…
Reference in New Issue
Block a user