summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@gmail.com>2013-01-02 13:10:01 -0800
committerVishvananda Ishaya <vishvananda@gmail.com>2013-01-04 09:18:23 -0800
commitaa2dea35c6e1cfc913e85834b9b98eda4155bd06 (patch)
tree3e1740683b45094735477794f8f158b0ab360a2a /nova
parent4690b501b58bc499029bc4586ff4b7c0917d2395 (diff)
Allow larger encrypted password posts to metadata
System Metadata only supports values up to 255 characters, but passwords encrypted with an rsa key are generally much longer than that, so we support longer passwords by chunking into four fields. Change-Id: Iceae6cbc7609ec3bdf1b3814aec5b73f19613349
Diffstat (limited to 'nova')
-rw-r--r--nova/api/metadata/base.py7
-rw-r--r--nova/api/metadata/password.py34
-rw-r--r--nova/tests/test_metadata.py3
3 files changed, 32 insertions, 12 deletions
diff --git a/nova/api/metadata/base.py b/nova/api/metadata/base.py
index 2377da7b7..34d412268 100644
--- a/nova/api/metadata/base.py
+++ b/nova/api/metadata/base.py
@@ -136,12 +136,7 @@ class InstanceMetadata():
for item in instance.get('metadata', []):
self.launch_metadata[item['key']] = item['value']
- self.password = ''
- # get password if set
- for item in instance.get('system_metadata', []):
- if item['key'] == 'password':
- self.password = item['value'] or ''
- break
+ self.password = password.extract_password(instance)
self.uuid = instance.get('uuid')
diff --git a/nova/api/metadata/password.py b/nova/api/metadata/password.py
index 3cda67eee..b2bb83b15 100644
--- a/nova/api/metadata/password.py
+++ b/nova/api/metadata/password.py
@@ -19,7 +19,34 @@ from nova import context
from nova import db
-MAX_SIZE = 256
+CHUNKS = 4
+CHUNK_LENGTH = 255
+MAX_SIZE = CHUNKS * CHUNK_LENGTH
+
+
+def extract_password(instance):
+ result = ''
+ for datum in sorted(instance.get('system_metadata', []),
+ key=lambda x: x['key']):
+ if datum['key'].startswith('password_'):
+ result += datum['value']
+ return result or None
+
+
+def set_password(context, instance_uuid, password):
+ """Stores password as system_metadata items.
+
+ Password is stored with the keys 'password_0' -> 'password_3'.
+ """
+ password = password or ''
+ meta = {}
+ for i in xrange(CHUNKS):
+ meta['password_%d' % i] = password[:CHUNK_LENGTH]
+ password = password[CHUNK_LENGTH:]
+ db.instance_system_metadata_update(context,
+ instance_uuid,
+ meta,
+ False)
def handle_password(req, meta_data):
@@ -36,9 +63,6 @@ def handle_password(req, meta_data):
if (req.content_length > MAX_SIZE or len(req.body) > MAX_SIZE):
msg = _("Request is too large.")
raise exc.HTTPBadRequest(explanation=msg)
- db.instance_system_metadata_update(ctxt,
- meta_data.uuid,
- {'password': req.body},
- False)
+ set_password(ctxt, meta_data.uuid, req.body)
else:
raise exc.HTTPBadRequest()
diff --git a/nova/tests/test_metadata.py b/nova/tests/test_metadata.py
index 1f2ea4bc5..25c26ca9c 100644
--- a/nova/tests/test_metadata.py
+++ b/nova/tests/test_metadata.py
@@ -550,4 +550,5 @@ class MetadataPasswordTestCase(test.TestCase):
def test_too_large(self):
self.mdinst.password = ''
self.assertRaises(webob.exc.HTTPBadRequest,
- self._try_set_password, 'a' * 257)
+ self._try_set_password,
+ 'a' * (password.MAX_SIZE + 1))