diff options
| author | Sean Dague <sdague@linux.vnet.ibm.com> | 2013-01-16 14:36:00 -0500 |
|---|---|---|
| committer | Sean Dague <sdague@linux.vnet.ibm.com> | 2013-01-16 18:21:37 -0500 |
| commit | 5956ea0079befa7e3e5d5316213fad4d00f25652 (patch) | |
| tree | 56991b7f0c9803a0f54e4173562eac6f20f25b6b | |
| parent | 9670c932c913fccbca263713bd9cee1b5e149d1c (diff) | |
| download | nova-5956ea0079befa7e3e5d5316213fad4d00f25652.tar.gz nova-5956ea0079befa7e3e5d5316213fad4d00f25652.tar.xz nova-5956ea0079befa7e3e5d5316213fad4d00f25652.zip | |
enforce server_id can only be uuid or int
the get() function takes an arbitrary id coming from the rest url
for the server. In our current code it checks if this is a proper uuid
and sends it down the uuid path, everything else gets dispatched to
the version that selects by integer id. This means that arbitrary
garbage fuzzed server ids will get sent down the int path, all the way
to the database.
In postgresql, where the db is strongly typed, this causes a type error.
This error was found by tempest nightly runs where we send some 35 and 37
character strings in.
This patch creates and equivalent is_int_like function. If the server_id
is neither uuid_like nor int_like, we throw the InstanceNotFound exception
early. This also saves us a trip to the database in these cases.
Make the is_int_like a little more robust, and don't succeed on floats
Once more with feeling, to let us actually use is_int_like on ints, not
just strings.
Fixes bug #1100253
Change-Id: If4ae8005fd33a23ac50a6408ecd5933a2ff6425c
| -rw-r--r-- | nova/compute/api.py | 4 | ||||
| -rw-r--r-- | nova/tests/test_utils.py | 21 | ||||
| -rw-r--r-- | nova/utils.py | 8 |
3 files changed, 32 insertions, 1 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py index 7770bc9e6..70bcb7bef 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -1168,8 +1168,10 @@ class API(base.Base): # NOTE(ameade): we still need to support integer ids for ec2 if uuidutils.is_uuid_like(instance_id): instance = self.db.instance_get_by_uuid(context, instance_id) - else: + elif utils.is_int_like(instance_id): instance = self.db.instance_get(context, instance_id) + else: + raise exception.InstanceNotFound(instance_id=instance_id) check_policy(context, 'get', instance) diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py index 2c46b27bd..9eab72c5b 100644 --- a/nova/tests/test_utils.py +++ b/nova/tests/test_utils.py @@ -757,3 +757,24 @@ class LastBytesTestCase(test.TestCase): content = '1234567890' flo.write(content) self.assertEqual((content, 0), utils.last_bytes(flo, 1000)) + + +class IntLikeTestCase(test.TestCase): + + def test_is_int_like(self): + self.assertTrue(utils.is_int_like(1)) + self.assertTrue(utils.is_int_like("1")) + self.assertTrue(utils.is_int_like("514")) + self.assertTrue(utils.is_int_like("0")) + + self.assertFalse(utils.is_int_like(1.1)) + self.assertFalse(utils.is_int_like("1.1")) + self.assertFalse(utils.is_int_like("1.1.1")) + self.assertFalse(utils.is_int_like(None)) + self.assertFalse(utils.is_int_like("0.")) + self.assertFalse(utils.is_int_like("aaaaaa")) + self.assertFalse(utils.is_int_like("....")) + self.assertFalse(utils.is_int_like("1g")) + self.assertFalse( + utils.is_int_like("0cc3346e-9fef-4445-abe6-5d2b2690ec64")) + self.assertFalse(utils.is_int_like("a1")) diff --git a/nova/utils.py b/nova/utils.py index 115791b64..75cba0a7c 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -859,6 +859,14 @@ def bool_from_str(val): val.lower() == 'y' +def is_int_like(val): + """Check if a value looks like an int.""" + try: + return str(int(val)) == str(val) + except Exception: + return False + + def is_valid_boolstr(val): """Check if the provided string is a valid bool string or not.""" val = str(val).lower() |
