To prevent remote code injection on Sheepdog store
Change-Id: Iae92eaf9eb023f36a1bab7c20ea41c985f2bf51b Signed-off-by: Zhi Yan Liu <zhiyanl@cn.ibm.com>
This commit is contained in:
parent
438ec09c5f
commit
f06ca34e7d
@ -20,6 +20,7 @@ import hashlib
|
|||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
from glance.common import exception
|
from glance.common import exception
|
||||||
|
from glance.common import utils
|
||||||
from glance.openstack.common import excutils
|
from glance.openstack.common import excutils
|
||||||
import glance.openstack.common.log as logging
|
import glance.openstack.common.log as logging
|
||||||
from glance.openstack.common import processutils
|
from glance.openstack.common import processutils
|
||||||
@ -31,7 +32,7 @@ import glance.store.location
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_ADDR = 'localhost'
|
DEFAULT_ADDR = '127.0.0.1'
|
||||||
DEFAULT_PORT = 7000
|
DEFAULT_PORT = 7000
|
||||||
DEFAULT_CHUNKSIZE = 64 # in MiB
|
DEFAULT_CHUNKSIZE = 64 # in MiB
|
||||||
|
|
||||||
@ -62,18 +63,14 @@ class SheepdogImage:
|
|||||||
self.chunk_size = chunk_size
|
self.chunk_size = chunk_size
|
||||||
|
|
||||||
def _run_command(self, command, data, *params):
|
def _run_command(self, command, data, *params):
|
||||||
cmd = ("collie vdi %(command)s -a %(addr)s -p %(port)d %(name)s "
|
cmd = ["collie", "vdi"]
|
||||||
"%(params)s" %
|
cmd.extend(command)
|
||||||
{"command": command,
|
cmd.extend(["-a", self.addr, "-p", self.port, self.name])
|
||||||
"addr": self.addr,
|
cmd.extend(params)
|
||||||
"port": self.port,
|
|
||||||
"name": self.name,
|
|
||||||
"params": " ".join(map(str, params))})
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return processutils.execute(
|
return processutils.execute(*cmd, process_input=data)[0]
|
||||||
cmd, process_input=data, shell=True)[0]
|
except (processutils.ProcessExecutionError, OSError) as exc:
|
||||||
except processutils.ProcessExecutionError as exc:
|
|
||||||
LOG.error(exc)
|
LOG.error(exc)
|
||||||
raise glance.store.BackendException(exc)
|
raise glance.store.BackendException(exc)
|
||||||
|
|
||||||
@ -83,7 +80,7 @@ class SheepdogImage:
|
|||||||
|
|
||||||
Sheepdog Usage: collie vdi list -r -a address -p port image
|
Sheepdog Usage: collie vdi list -r -a address -p port image
|
||||||
"""
|
"""
|
||||||
out = self._run_command("list -r", None)
|
out = self._run_command(["list", "-r"], None)
|
||||||
return long(out.split(' ')[3])
|
return long(out.split(' ')[3])
|
||||||
|
|
||||||
def read(self, offset, count):
|
def read(self, offset, count):
|
||||||
@ -93,7 +90,7 @@ class SheepdogImage:
|
|||||||
|
|
||||||
Sheepdog Usage: collie vdi read -a address -p port image offset len
|
Sheepdog Usage: collie vdi read -a address -p port image offset len
|
||||||
"""
|
"""
|
||||||
return self._run_command("read", None, str(offset), str(count))
|
return self._run_command(["read"], None, str(offset), str(count))
|
||||||
|
|
||||||
def write(self, data, offset, count):
|
def write(self, data, offset, count):
|
||||||
"""
|
"""
|
||||||
@ -102,7 +99,7 @@ class SheepdogImage:
|
|||||||
|
|
||||||
Sheepdog Usage: collie vdi write -a address -p port image offset len
|
Sheepdog Usage: collie vdi write -a address -p port image offset len
|
||||||
"""
|
"""
|
||||||
self._run_command("write", data, str(offset), str(count))
|
self._run_command(["write"], data, str(offset), str(count))
|
||||||
|
|
||||||
def create(self, size):
|
def create(self, size):
|
||||||
"""
|
"""
|
||||||
@ -110,7 +107,7 @@ class SheepdogImage:
|
|||||||
|
|
||||||
Sheepdog Usage: collie vdi create -a address -p port image size
|
Sheepdog Usage: collie vdi create -a address -p port image size
|
||||||
"""
|
"""
|
||||||
self._run_command("create", None, str(size))
|
self._run_command(["create"], None, str(size))
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
"""
|
"""
|
||||||
@ -118,7 +115,7 @@ class SheepdogImage:
|
|||||||
|
|
||||||
Sheepdog Usage: collie vdi delete -a address -p port image
|
Sheepdog Usage: collie vdi delete -a address -p port image
|
||||||
"""
|
"""
|
||||||
self._run_command("delete", None)
|
self._run_command(["delete"], None)
|
||||||
|
|
||||||
def exist(self):
|
def exist(self):
|
||||||
"""
|
"""
|
||||||
@ -126,7 +123,7 @@ class SheepdogImage:
|
|||||||
|
|
||||||
Sheepdog Usage: collie vdi list -r -a address -p port image
|
Sheepdog Usage: collie vdi list -r -a address -p port image
|
||||||
"""
|
"""
|
||||||
out = self._run_command("list -r", None)
|
out = self._run_command(["list", "-r"], None)
|
||||||
if not out:
|
if not out:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
@ -137,7 +134,7 @@ class StoreLocation(glance.store.location.StoreLocation):
|
|||||||
"""
|
"""
|
||||||
Class describing a Sheepdog URI. This is of the form:
|
Class describing a Sheepdog URI. This is of the form:
|
||||||
|
|
||||||
sheepdog://image
|
sheepdog://image-id
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -148,10 +145,14 @@ class StoreLocation(glance.store.location.StoreLocation):
|
|||||||
return "sheepdog://%s" % self.image
|
return "sheepdog://%s" % self.image
|
||||||
|
|
||||||
def parse_uri(self, uri):
|
def parse_uri(self, uri):
|
||||||
if not uri.startswith('sheepdog://'):
|
valid_schema = 'sheepdog://'
|
||||||
raise exception.BadStoreUri(uri, "URI must start with %s://" %
|
if not uri.startswith(valid_schema):
|
||||||
'sheepdog')
|
raise exception.BadStoreUri(_("URI must start with %s://") %
|
||||||
self.image = uri[11:]
|
valid_schema)
|
||||||
|
self.image = uri[len(valid_schema):]
|
||||||
|
if not utils.is_uuid_like(self.image):
|
||||||
|
raise exception.BadStoreUri(_("URI must contains well-formated "
|
||||||
|
"image id"))
|
||||||
|
|
||||||
|
|
||||||
class ImageIterator(object):
|
class ImageIterator(object):
|
||||||
@ -191,7 +192,7 @@ class Store(glance.store.base.Store):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self.chunk_size = CONF.sheepdog_store_chunk_size * units.Mi
|
self.chunk_size = CONF.sheepdog_store_chunk_size * units.Mi
|
||||||
self.addr = CONF.sheepdog_store_address
|
self.addr = CONF.sheepdog_store_address.strip()
|
||||||
self.port = CONF.sheepdog_store_port
|
self.port = CONF.sheepdog_store_port
|
||||||
except cfg.ConfigFileValueError as e:
|
except cfg.ConfigFileValueError as e:
|
||||||
reason = _("Error in store configuration: %s") % e
|
reason = _("Error in store configuration: %s") % e
|
||||||
@ -199,10 +200,18 @@ class Store(glance.store.base.Store):
|
|||||||
raise exception.BadStoreConfiguration(store_name='sheepdog',
|
raise exception.BadStoreConfiguration(store_name='sheepdog',
|
||||||
reason=reason)
|
reason=reason)
|
||||||
|
|
||||||
|
if ' ' in self.addr:
|
||||||
|
reason = (_("Invalid address configuration of sheepdog store: %s")
|
||||||
|
% self.addr)
|
||||||
|
LOG.error(reason)
|
||||||
|
raise exception.BadStoreConfiguration(store_name='sheepdog',
|
||||||
|
reason=reason)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
processutils.execute("collie", shell=True)
|
cmd = ["collie", "vdi", "list", "-a", self.addr, "-p", self.port]
|
||||||
except processutils.ProcessExecutionError as exc:
|
processutils.execute(*cmd)
|
||||||
reason = _("Error in store configuration: %s") % exc
|
except Exception as e:
|
||||||
|
reason = _("Error in store configuration: %s") % e
|
||||||
LOG.error(reason)
|
LOG.error(reason)
|
||||||
raise exception.BadStoreConfiguration(store_name='sheepdog',
|
raise exception.BadStoreConfiguration(store_name='sheepdog',
|
||||||
reason=reason)
|
reason=reason)
|
||||||
|
@ -56,4 +56,5 @@ class TestStore(base.StoreClearingUnitTest):
|
|||||||
'fake_image_id',
|
'fake_image_id',
|
||||||
utils.LimitingReader(six.StringIO('xx'), 1),
|
utils.LimitingReader(six.StringIO('xx'), 1),
|
||||||
2)
|
2)
|
||||||
self.assertEqual(called_commands, ['list -r', 'create', 'delete'])
|
self.assertEqual([['list', '-r'], ['create'], ['delete']],
|
||||||
|
called_commands)
|
||||||
|
@ -66,7 +66,7 @@ class TestStoreLocation(base.StoreClearingUnitTest):
|
|||||||
'rbd://imagename',
|
'rbd://imagename',
|
||||||
'rbd://fsid/pool/image/snap',
|
'rbd://fsid/pool/image/snap',
|
||||||
'rbd://%2F/%2F/%2F/%2F',
|
'rbd://%2F/%2F/%2F/%2F',
|
||||||
'sheepdog://imagename',
|
'sheepdog://244e75f1-9c69-4167-9db7-1aa7d1973f6c',
|
||||||
'cinder://12345678-9012-3455-6789-012345678901',
|
'cinder://12345678-9012-3455-6789-012345678901',
|
||||||
'vsphere://ip/folder/openstack_glance/2332298?dcPath=dc&dsName=ds',
|
'vsphere://ip/folder/openstack_glance/2332298?dcPath=dc&dsName=ds',
|
||||||
]
|
]
|
||||||
@ -382,15 +382,18 @@ class TestStoreLocation(base.StoreClearingUnitTest):
|
|||||||
"""
|
"""
|
||||||
Test the specific StoreLocation for the Sheepdog store
|
Test the specific StoreLocation for the Sheepdog store
|
||||||
"""
|
"""
|
||||||
uri = 'sheepdog://imagename'
|
uri = 'sheepdog://244e75f1-9c69-4167-9db7-1aa7d1973f6c'
|
||||||
loc = glance.store.sheepdog.StoreLocation({})
|
loc = glance.store.sheepdog.StoreLocation({})
|
||||||
loc.parse_uri(uri)
|
loc.parse_uri(uri)
|
||||||
self.assertEqual('imagename', loc.image)
|
self.assertEqual('244e75f1-9c69-4167-9db7-1aa7d1973f6c', loc.image)
|
||||||
|
|
||||||
bad_uri = 'sheepdog:/image'
|
bad_uri = 'sheepdog:/244e75f1-9c69-4167-9db7-1aa7d1973f6c'
|
||||||
self.assertRaises(exception.BadStoreUri, loc.parse_uri, bad_uri)
|
self.assertRaises(exception.BadStoreUri, loc.parse_uri, bad_uri)
|
||||||
|
|
||||||
bad_uri = 'http://image'
|
bad_uri = 'http://244e75f1-9c69-4167-9db7-1aa7d1973f6c'
|
||||||
|
self.assertRaises(exception.BadStoreUri, loc.parse_uri, bad_uri)
|
||||||
|
|
||||||
|
bad_uri = 'image; name'
|
||||||
self.assertRaises(exception.BadStoreUri, loc.parse_uri, bad_uri)
|
self.assertRaises(exception.BadStoreUri, loc.parse_uri, bad_uri)
|
||||||
|
|
||||||
def test_vmware_store_location(self):
|
def test_vmware_store_location(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user