diff --git a/etc/murano/murano-api.conf.sample b/etc/murano/murano-api.conf.sample index 9dad793f..eb81cd21 100644 --- a/etc/murano/murano-api.conf.sample +++ b/etc/murano/murano-api.conf.sample @@ -14,6 +14,9 @@ bind_port = 8082 # Directory to store application package cache # packages_cache = +# Maximum application package size, Mb +package_size_limit = 5 + # Set up logging. Make sure the user has permissions to write to this file! To use syslog just set use_syslog parameter value to 'True'. log_file = /tmp/murano-api.log diff --git a/muranoapi/api/v1/catalog.py b/muranoapi/api/v1/catalog.py index 9d77a931..2bb2ca89 100644 --- a/muranoapi/api/v1/catalog.py +++ b/muranoapi/api/v1/catalog.py @@ -74,9 +74,26 @@ def _get_filters(query_params): def _validate_body(body): + """ + Check multipart/form-data has two parts: text (which is json string and + should parsed into dictionary in serializer) and file, which stores as + cgi.FieldStorage instance. Also validate file size doesn't exceed + the limit: seek to the end of the file, get the position of EOF and + reset the file position to the beginning + """ + def check_file_size(f): + pkg_size_limit = CONF.package_size_limit * 1024 * 1024 + f.seek(0, 2) + size = f.tell() + f.seek(0) + if size > pkg_size_limit: + raise exc.HTTPBadRequest('Uploading file is too large.' + ' The limit is {0}' + ' Mb'.format(CONF.package_size_limit)) + if len(body.keys()) != 2: msg = _("'multipart/form-data' request body should contain " - "2 parts: json string and zip archivel. Current body consist " + "2 parts: json string and zip archive. Current body consist " "of {0} part(s)").format(len(body.keys())) LOG.error(msg) raise exc.HTTPBadRequest(msg) @@ -85,15 +102,16 @@ def _validate_body(body): for part in body.values(): if isinstance(part, cgi.FieldStorage): file_obj = part - # dict if json deserialized successfully + check_file_size(file_obj.file) + if isinstance(part, dict): package_meta = part if file_obj is None: - msg = _("There is no file package with application description") + msg = _('There is no file package with application description') LOG.error(msg) raise exc.HTTPBadRequest(msg) if package_meta is None: - msg = _("There is no json with meta information about package") + msg = _('There is no json with meta information about package') LOG.error(msg) raise exc.HTTPBadRequest(msg) return file_obj, package_meta diff --git a/muranoapi/common/config.py b/muranoapi/common/config.py index a0239c30..4e12870b 100644 --- a/muranoapi/common/config.py +++ b/muranoapi/common/config.py @@ -98,6 +98,8 @@ metadata_dir = cfg.StrOpt('metadata-dir', default='./meta') temp_pkg_cache = os.path.join(tempfile.gettempdir(), 'murano-packages-cache') packages_cache = cfg.StrOpt('packages-cache', default=temp_pkg_cache) +package_size_limit = cfg.IntOpt('package_size_limit', default=5) + CONF = cfg.CONF CONF.register_opts(paste_deploy_opts, group='paste_deploy') CONF.register_cli_opts(bind_opts) @@ -111,6 +113,7 @@ CONF.register_opt(cfg.StrOpt('file_server')) CONF.register_cli_opt(cfg.StrOpt('murano_metadata_url')) CONF.register_cli_opt(metadata_dir) CONF.register_cli_opt(packages_cache) +CONF.register_cli_opt(package_size_limit) CONF.register_opts(stats_opt, group='stats') CONF.import_opt('connection',