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
This commit is contained in:
Vishvananda Ishaya 2013-01-02 13:10:01 -08:00
parent 4690b501b5
commit aa2dea35c6
3 changed files with 32 additions and 12 deletions

View File

@ -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')

View File

@ -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()

View File

@ -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))