From 22df43e2f1e4dd6050e61f0808e6970b0cb05dac Mon Sep 17 00:00:00 2001 From: Angus Salkeld Date: Mon, 27 Oct 2014 10:23:33 +1000 Subject: [PATCH] Validate nova server's metadata This prevents "foo" getting passed into the metadata. This can happen when using get_attr() to return a dynamic value. Change-Id: I17eab659e65a51963e510add4d71fbc90a3a3a53 Closes-bug: #1338811 --- heat/engine/clients/os/nova.py | 5 +++++ heat/tests/test_nova_client.py | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/heat/engine/clients/os/nova.py b/heat/engine/clients/os/nova.py index 1740efaa6d..52dca39f67 100644 --- a/heat/engine/clients/os/nova.py +++ b/heat/engine/clients/os/nova.py @@ -11,6 +11,7 @@ # License for the specific language governing permissions and limitations # under the License. +import collections import email from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText @@ -375,6 +376,10 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers Serialize non-string metadata values before sending them to Nova. """ + if not isinstance(metadata, collections.Mapping): + raise exception.StackValidationFailed(message=_( + "nova server metadata needs to be a Map.")) + return dict((key, (value if isinstance(value, six.string_types) else json.dumps(value)) diff --git a/heat/tests/test_nova_client.py b/heat/tests/test_nova_client.py index 2120c8e98a..3eb6ff20aa 100644 --- a/heat/tests/test_nova_client.py +++ b/heat/tests/test_nova_client.py @@ -15,6 +15,7 @@ import mock from novaclient import exceptions as nova_exceptions from oslo.config import cfg +import six import uuid from heat.common import exception @@ -232,6 +233,14 @@ class NovaUtilsMetadataTests(NovaClientPluginTestCase): expected = {'test_key': 'null'} self.assertEqual(expected, self.nova_plugin.meta_serialize(original)) + def test_serialize_no_value(self): + """This test is to prove that the user can only pass in a dict to nova + metadata. + """ + excp = self.assertRaises(exception.StackValidationFailed, + self.nova_plugin.meta_serialize, "foo") + self.assertIn('metadata needs to be a Map', six.text_type(excp)) + def test_serialize_combined(self): original = { 'test_key_1': 123,