Enforce size verification on content-length
Closes-Bug: #1261579 Previously, Marconi used to enforce the message and queue size limit on the resource itself. In the case of a Message, it'd verify that the message body wouldn't exceed the message size limit. This enforcement has been moved, by this patch, up to the request size. For both cases, the content_length is required to be smaller than the size limit configured by the service admin. None of the default values were modified. Change-Id: I06e28acaac234242a40cd2afafb12be067851c20
This commit is contained in:
parent
e82e5fe3c0
commit
9205b0c3a3
@ -13,11 +13,12 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
from marconi.openstack.common.gettextutils import _
|
||||
|
||||
|
||||
_TRANSPORT_LIMITS_OPTIONS = [
|
||||
cfg.IntOpt('queue_paging_uplimit', default=20),
|
||||
@ -89,28 +90,21 @@ class Validator(object):
|
||||
'Limit must be at least 1 and no greater than %d.' %
|
||||
self._limits_conf.queue_paging_uplimit)
|
||||
|
||||
def queue_content(self, metadata, check_size):
|
||||
"""Restrictions on queue metadata.
|
||||
def queue_metadata_length(self, content_length):
|
||||
"""Restrictions on queue's length.
|
||||
|
||||
:param metadata: Metadata as a Python dict
|
||||
:param check_size: Whether this size checking is required
|
||||
:param content_length: Queue request's length.
|
||||
:raises: ValidationFailed if the metadata is oversize.
|
||||
"""
|
||||
if content_length > self._limits_conf.metadata_size_uplimit:
|
||||
error = _(u'Queue request size is too large. Max size %s')
|
||||
raise ValidationFailed(error %
|
||||
self._limits_conf.metadata_size_uplimit)
|
||||
|
||||
if check_size:
|
||||
length = _compact_json_length(metadata)
|
||||
if length > self._limits_conf.metadata_size_uplimit:
|
||||
raise ValidationFailed(
|
||||
('Queue metadata may not exceed %d characters, '
|
||||
'excluding whitespace.') %
|
||||
self._limits_conf.metadata_size_uplimit)
|
||||
|
||||
def message_posting(self, messages, check_size=True):
|
||||
def message_posting(self, messages):
|
||||
"""Restrictions on a list of messages.
|
||||
|
||||
:param messages: A list of messages
|
||||
:param check_size: Whether the size checking for each message
|
||||
is required
|
||||
:raises: ValidationFailed if any message has a out-of-range
|
||||
TTL, or an oversize message body.
|
||||
"""
|
||||
@ -118,9 +112,20 @@ class Validator(object):
|
||||
self.message_listing(limit=len(messages))
|
||||
|
||||
for msg in messages:
|
||||
self.message_content(msg, check_size)
|
||||
self.message_content(msg)
|
||||
|
||||
def message_content(self, message, check_size):
|
||||
def message_length(self, content_length):
|
||||
"""Restrictions on message post length.
|
||||
|
||||
:param content_length: Queue request's length.
|
||||
:raises: ValidationFailed if the metadata is oversize.
|
||||
"""
|
||||
if content_length > self._limits_conf.message_size_uplimit:
|
||||
error = _(u'Message collection size is too large. Max size %s')
|
||||
raise ValidationFailed(error %
|
||||
self._limits_conf.message_size_uplimit)
|
||||
|
||||
def message_content(self, message):
|
||||
"""Restrictions on each message."""
|
||||
|
||||
if not (60 <= message['ttl'] <= self._limits_conf.message_ttl_max):
|
||||
@ -129,14 +134,6 @@ class Validator(object):
|
||||
'must be at least 60 seconds long.') %
|
||||
self._limits_conf.message_ttl_max)
|
||||
|
||||
if check_size:
|
||||
body_length = _compact_json_length(message['body'])
|
||||
if body_length > self._limits_conf.message_size_uplimit:
|
||||
raise ValidationFailed(
|
||||
('Message bodies may not exceed %d characters, '
|
||||
'excluding whitespace.') %
|
||||
self._limits_conf.message_size_uplimit)
|
||||
|
||||
def message_listing(self, limit=None, **kwargs):
|
||||
"""Restrictions involving a list of messages.
|
||||
|
||||
@ -182,12 +179,3 @@ class Validator(object):
|
||||
('The TTL for a claim may not exceed %d seconds, and must be '
|
||||
'at least 60 seconds long.') %
|
||||
self._limits_conf.claim_ttl_max)
|
||||
|
||||
|
||||
def _compact_json_length(obj):
|
||||
# UTF-8 encoded, without whitespace
|
||||
# TODO(zyuan): Replace this redundent re-serialization
|
||||
# with a sizing-only parser.
|
||||
return len(json.dumps(obj,
|
||||
ensure_ascii=False,
|
||||
separators=(',', ':')))
|
||||
|
@ -138,10 +138,12 @@ class CollectionResource(object):
|
||||
|
||||
client_uuid = wsgi_utils.get_client_uuid(req)
|
||||
|
||||
# Place JSON size restriction before parsing
|
||||
if req.content_length > self._wsgi_conf.content_max_length:
|
||||
description = _(u'Message collection size is too large.')
|
||||
raise wsgi_errors.HTTPBadRequestBody(description)
|
||||
try:
|
||||
# Place JSON size restriction before parsing
|
||||
self._validate.message_length(req.content_length)
|
||||
except validation.ValidationFailed as ex:
|
||||
LOG.debug(ex)
|
||||
raise wsgi_errors.HTTPBadRequestAPI(six.text_type(ex))
|
||||
|
||||
# Pull out just the fields we care about
|
||||
messages = wsgi_utils.filter_stream(
|
||||
@ -154,12 +156,7 @@ class CollectionResource(object):
|
||||
partial = False
|
||||
|
||||
try:
|
||||
# No need to check each message's size if it
|
||||
# can not exceed the request size limit
|
||||
self._validate.message_posting(
|
||||
messages, check_size=(
|
||||
self._validate._limits_conf.message_size_uplimit <
|
||||
self._wsgi_conf.content_max_length))
|
||||
self._validate.message_posting(messages)
|
||||
|
||||
message_ids = self.message_controller.post(
|
||||
queue_name,
|
||||
|
@ -63,10 +63,12 @@ class Resource(object):
|
||||
u'project: %(project)s'),
|
||||
{'queue': queue_name, 'project': project_id})
|
||||
|
||||
# Place JSON size restriction before parsing
|
||||
if req.content_length > self._wsgi_conf.metadata_max_length:
|
||||
description = _(u'Queue metadata size is too large.')
|
||||
raise wsgi_errors.HTTPBadRequestBody(description)
|
||||
try:
|
||||
# Place JSON size restriction before parsing
|
||||
self._validate.queue_metadata_length(req.content_length)
|
||||
except validation.ValidationFailed as ex:
|
||||
LOG.debug(ex)
|
||||
raise wsgi_errors.HTTPBadRequestAPI(six.text_type(ex))
|
||||
|
||||
# Deserialize queue metadata
|
||||
metadata, = wsgi_utils.filter_stream(req.stream,
|
||||
@ -74,10 +76,6 @@ class Resource(object):
|
||||
spec=None)
|
||||
|
||||
try:
|
||||
self._validate.queue_content(
|
||||
metadata, check_size=(
|
||||
self._validate._limits_conf.metadata_size_uplimit <
|
||||
self._wsgi_conf.metadata_max_length))
|
||||
self.queue_ctrl.set_metadata(queue_name,
|
||||
metadata=metadata,
|
||||
project=project_id)
|
||||
|
Loading…
x
Reference in New Issue
Block a user