diff options
| author | Michael Still <mikal@stillhq.com> | 2012-08-11 20:51:27 +1000 |
|---|---|---|
| committer | Michael Still <mikal@stillhq.com> | 2012-08-14 09:56:58 +1000 |
| commit | 4d350dc82ecfe1d272bfbd43445a78c69a32fc90 (patch) | |
| tree | ec33ab174447f7861522410b4e486fc35588dd64 | |
| parent | 4d9cca956c7df53e0ca47e88b01ea34e541d1a3e (diff) | |
| download | nova-4d350dc82ecfe1d272bfbd43445a78c69a32fc90.tar.gz nova-4d350dc82ecfe1d272bfbd43445a78c69a32fc90.tar.xz nova-4d350dc82ecfe1d272bfbd43445a78c69a32fc90.zip | |
Simple checks for instance user data.
Check that instance user data wont be truncated, and that it is
valid base64 data. This partially resolves bug 1035055. I don't
love the hard coded maximum length, but I haven't worked out how
to get sqlalchemy to tell me the maximum size of the data type.
Change-Id: I045d6b4481563d01cae371cf61a91781cfed6f4b
| -rw-r--r-- | nova/compute/api.py | 15 | ||||
| -rw-r--r-- | nova/exception.py | 10 | ||||
| -rw-r--r-- | nova/tests/compute/test_compute.py | 49 |
3 files changed, 74 insertions, 0 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py index cd3ffdf56..971540de1 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -21,6 +21,7 @@ """Handles all requests relating to compute resources (e.g. guest VMs, networking and storage of VMs, and compute hosts on which they run).""" +import base64 import functools import re import string @@ -58,6 +59,7 @@ LOG = logging.getLogger(__name__) FLAGS = flags.FLAGS flags.DECLARE('consoleauth_topic', 'nova.consoleauth') +MAX_USERDATA_SIZE = 65535 QUOTAS = quota.QUOTAS @@ -473,6 +475,19 @@ class API(base.Base): 'architecture': architecture, 'progress': 0} + if user_data: + l = len(user_data) + if l > MAX_USERDATA_SIZE: + # NOTE(mikal): user_data is stored in a text column, and the + # database might silently truncate if its over length. + raise exception.InstanceUserDataTooLarge( + length=l, maxsize=MAX_USERDATA_SIZE) + + try: + base64.decodestring(user_data) + except base64.binascii.Error: + raise exception.InstanceUserDataMalformed() + options_from_image = self._inherit_properties_from_image( image, auto_disk_config) diff --git a/nova/exception.py b/nova/exception.py index 315147764..de8982488 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -1155,6 +1155,16 @@ class ConfigDriveUnknownFormat(NovaException): "iso9660 or vfat.") +class InstanceUserDataTooLarge(NovaException): + message = _("User data too large. User data must be no larger than " + "%(maxsize)s bytes once base64 encoded. Your data is " + "%(length)d bytes") + + +class InstanceUserDataMalformed(NovaException): + message = _("User data needs to be valid base 64.") + + def get_context_from_function_and_args(function, args, kwargs): """Find an arg of type RequestContext and return it. diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index a625397ea..10cc325e5 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -18,6 +18,7 @@ # under the License. """Tests for compute service""" +import base64 import copy import datetime import functools @@ -2364,6 +2365,54 @@ class ComputeAPITestCase(BaseTestCase): self.assertEqual(pre_build_len, len(db.instance_get_all(context.get_admin_context()))) + def test_create_with_large_user_data(self): + """Test an instance type with too much user data.""" + + inst_type = instance_types.get_default_instance_type() + + def fake_show(*args): + img = copy.copy(self.fake_image) + img['min_ram'] = 2 + return img + self.stubs.Set(fake_image._FakeImageService, 'show', fake_show) + + self.assertRaises(exception.InstanceUserDataTooLarge, + self.compute_api.create, self.context, inst_type, None, + user_data=('1' * 65536)) + + def test_create_with_malformed_user_data(self): + """Test an instance type with malformed user data.""" + + inst_type = instance_types.get_default_instance_type() + + def fake_show(*args): + img = copy.copy(self.fake_image) + img['min_ram'] = 2 + return img + self.stubs.Set(fake_image._FakeImageService, 'show', fake_show) + + self.assertRaises(exception.InstanceUserDataMalformed, + self.compute_api.create, self.context, inst_type, None, + user_data='banana') + + def test_create_with_base64_user_data(self): + """Test an instance type with ok much user data.""" + + inst_type = instance_types.get_default_instance_type() + + def fake_show(*args): + img = copy.copy(self.fake_image) + img['min_ram'] = 2 + return img + self.stubs.Set(fake_image._FakeImageService, 'show', fake_show) + + # NOTE(mikal): a string of length 48510 encodes to 65532 characters of + # base64 + (refs, resv_id) = self.compute_api.create( + self.context, inst_type, None, + user_data=base64.encodestring('1' * 48510)) + db.instance_destroy(self.context, refs[0]['uuid']) + def test_default_hostname_generator(self): fake_uuids = [str(utils.gen_uuid()) for x in xrange(4)] |
