Limit maximum size of all templates
Templates of an extremely large size can eat up tons of CPU time, memory and storage. By refusing to parse any template over a certain size, we can prevent users from abusing the service. Fixes bug #1214234 Change-Id: I2f731c8e2fc9e1f497199e310de81fa48c9582af
This commit is contained in:
parent
1623b03517
commit
9fe8cbacd2
@ -70,6 +70,9 @@
|
|||||||
# Keystone role for heat template-defined users (string value)
|
# Keystone role for heat template-defined users (string value)
|
||||||
#heat_stack_user_role=heat_stack_user
|
#heat_stack_user_role=heat_stack_user
|
||||||
|
|
||||||
|
# Maximum raw byte size of any template. (integer value)
|
||||||
|
#max_template_size=524288
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Options defined in heat.common.crypt
|
# Options defined in heat.common.crypt
|
||||||
|
@ -81,7 +81,10 @@ service_opts = [
|
|||||||
help='Instance connection to cfn/cw API validate certs if ssl'),
|
help='Instance connection to cfn/cw API validate certs if ssl'),
|
||||||
cfg.StrOpt('heat_stack_user_role',
|
cfg.StrOpt('heat_stack_user_role',
|
||||||
default="heat_stack_user",
|
default="heat_stack_user",
|
||||||
help='Keystone role for heat template-defined users')]
|
help='Keystone role for heat template-defined users'),
|
||||||
|
cfg.IntOpt('max_template_size',
|
||||||
|
default=524288,
|
||||||
|
help='Maximum raw byte size of any template.')]
|
||||||
|
|
||||||
db_opts = [
|
db_opts = [
|
||||||
cfg.StrOpt('sql_connection',
|
cfg.StrOpt('sql_connection',
|
||||||
|
@ -297,3 +297,7 @@ class HTTPExceptionDisguise(Exception):
|
|||||||
def __init__(self, exception):
|
def __init__(self, exception):
|
||||||
self.exc = exception
|
self.exc = exception
|
||||||
self.tb = sys.exc_info()[2]
|
self.tb = sys.exc_info()[2]
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateTooBig(OpenstackException):
|
||||||
|
message = _('Template exceeds maximum allowed size.')
|
||||||
|
@ -17,6 +17,12 @@ import re
|
|||||||
import yaml
|
import yaml
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from oslo.config import cfg
|
||||||
|
|
||||||
|
from heat.common import exception
|
||||||
|
|
||||||
|
cfg.CONF.import_opt('max_template_size', 'heat.common.config')
|
||||||
|
|
||||||
HEAT_VERSIONS = (u'2012-12-12',)
|
HEAT_VERSIONS = (u'2012-12-12',)
|
||||||
CFN_VERSIONS = (u'2010-09-09',)
|
CFN_VERSIONS = (u'2010-09-09',)
|
||||||
|
|
||||||
@ -43,6 +49,8 @@ def parse(tmpl_str, add_template_sections=True):
|
|||||||
This includes determination of whether the string is using the
|
This includes determination of whether the string is using the
|
||||||
JSON or YAML format.
|
JSON or YAML format.
|
||||||
'''
|
'''
|
||||||
|
if len(tmpl_str) > cfg.CONF.max_template_size:
|
||||||
|
raise exception.TemplateTooBig()
|
||||||
if tmpl_str.startswith('{'):
|
if tmpl_str.startswith('{'):
|
||||||
tpl = json.loads(tmpl_str)
|
tpl = json.loads(tmpl_str)
|
||||||
else:
|
else:
|
||||||
|
@ -14,8 +14,11 @@
|
|||||||
|
|
||||||
from testtools import skipIf
|
from testtools import skipIf
|
||||||
import os
|
import os
|
||||||
|
import yaml
|
||||||
|
|
||||||
from heat.engine import clients
|
from heat.engine import clients
|
||||||
|
from heat.common import config
|
||||||
|
from heat.common import exception
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
from heat.tests.common import HeatTestCase
|
from heat.tests.common import HeatTestCase
|
||||||
from heat.tests import utils
|
from heat.tests import utils
|
||||||
@ -89,6 +92,15 @@ Outputs: {}
|
|||||||
tpl2 = template_format.parse(yaml2)
|
tpl2 = template_format.parse(yaml2)
|
||||||
self.assertEqual(tpl1, tpl2)
|
self.assertEqual(tpl1, tpl2)
|
||||||
|
|
||||||
|
def test_long_yaml(self):
|
||||||
|
template = {'HeatTemplateVersion': '2012-12-12'}
|
||||||
|
template['Resources'] = ['a'] * (config.cfg.CONF.max_template_size / 3)
|
||||||
|
limit = config.cfg.CONF.max_template_size
|
||||||
|
long_yaml = yaml.safe_dump(template)
|
||||||
|
self.assertTrue(len(long_yaml) > limit)
|
||||||
|
self.assertRaises(exception.TemplateTooBig, template_format.parse,
|
||||||
|
long_yaml)
|
||||||
|
|
||||||
|
|
||||||
class YamlEnvironmentTest(HeatTestCase):
|
class YamlEnvironmentTest(HeatTestCase):
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user