Merge "libvirt: Add config option to require secure SPICE."
This commit is contained in:
@@ -318,7 +318,6 @@ be told where to find them. This requires editing :file:`nova.conf` to set.
|
||||
vencrypt_client_cert=/etc/pki/nova-novncproxy/client-cert.pem
|
||||
vencrypt_ca_certs=/etc/pki/nova-novncproxy/ca-cert.pem
|
||||
|
||||
|
||||
.. _spice-console:
|
||||
|
||||
SPICE console
|
||||
@@ -403,6 +402,10 @@ for SPICE consoles.
|
||||
- :oslo.config:option:`spice.playback_compression`
|
||||
- :oslo.config:option:`spice.streaming_mode`
|
||||
|
||||
As well as the following option to require that connections be protected by TLS:
|
||||
|
||||
- :oslo.config:option:`spice.require_secure`
|
||||
|
||||
.. _serial-console:
|
||||
|
||||
Serial console
|
||||
|
||||
@@ -194,6 +194,23 @@ Related options:
|
||||
* This option depends on the ``server_listen`` option.
|
||||
The proxy client must be able to access the address specified in
|
||||
``server_listen`` using the value of this option.
|
||||
"""),
|
||||
cfg.BoolOpt('require_secure',
|
||||
default=False,
|
||||
help="""
|
||||
Whether to require secure TLS connections to SPICE consoles.
|
||||
|
||||
If you're providing direct access to SPICE consoles instead of using the HTML5
|
||||
proxy, you may wish those connections to be encrypted. If so, set this value to
|
||||
True.
|
||||
|
||||
Note that use of secure consoles requires that you setup TLS certificates on
|
||||
each hypervisor.
|
||||
|
||||
Possible values:
|
||||
|
||||
* False: console traffic is not encrypted.
|
||||
* True: console traffic is required to be protected by TLS.
|
||||
"""),
|
||||
]
|
||||
|
||||
|
||||
@@ -1715,9 +1715,9 @@ class LibvirtConfigGuestGraphicsTest(LibvirtConfigBaseTest):
|
||||
obj.listen = "127.0.0.1"
|
||||
|
||||
xml = obj.to_xml()
|
||||
self.assertXmlEqual(xml, """
|
||||
self.assertXmlEqual("""
|
||||
<graphics type="vnc" autoport="yes" keymap="en_US" listen="127.0.0.1"/>
|
||||
""")
|
||||
""", xml)
|
||||
|
||||
def test_config_graphics_spice(self):
|
||||
obj = config.LibvirtConfigGuestGraphics()
|
||||
@@ -1726,6 +1726,18 @@ class LibvirtConfigGuestGraphicsTest(LibvirtConfigBaseTest):
|
||||
obj.keymap = "en_US"
|
||||
obj.listen = "127.0.0.1"
|
||||
|
||||
xml = obj.to_xml()
|
||||
self.assertXmlEqual("""
|
||||
<graphics type="spice" autoport="no" keymap="en_US" listen="127.0.0.1"/>
|
||||
""", xml)
|
||||
|
||||
def test_config_graphics_spice_compression(self):
|
||||
obj = config.LibvirtConfigGuestGraphics()
|
||||
obj.type = "spice"
|
||||
obj.autoport = False
|
||||
obj.keymap = "en_US"
|
||||
obj.listen = "127.0.0.1"
|
||||
|
||||
obj.image_compression = "auto_glz"
|
||||
obj.jpeg_compression = "auto"
|
||||
obj.zlib_compression = "always"
|
||||
@@ -1733,7 +1745,7 @@ class LibvirtConfigGuestGraphicsTest(LibvirtConfigBaseTest):
|
||||
obj.streaming_mode = "filter"
|
||||
|
||||
xml = obj.to_xml()
|
||||
self.assertXmlEqual(xml, """
|
||||
self.assertXmlEqual("""
|
||||
<graphics type="spice" autoport="no" keymap="en_US" listen="127.0.0.1">
|
||||
<image compression="auto_glz"/>
|
||||
<jpeg compression="auto"/>
|
||||
@@ -1741,7 +1753,64 @@ class LibvirtConfigGuestGraphicsTest(LibvirtConfigBaseTest):
|
||||
<playback compression="on"/>
|
||||
<streaming mode="filter"/>
|
||||
</graphics>
|
||||
""")
|
||||
""", xml)
|
||||
|
||||
def test_config_graphics_spice_secure(self):
|
||||
obj = config.LibvirtConfigGuestGraphics()
|
||||
obj.type = "spice"
|
||||
obj.autoport = False
|
||||
obj.keymap = "en_US"
|
||||
obj.listen = "127.0.0.1"
|
||||
|
||||
obj.secure = True
|
||||
|
||||
xml = obj.to_xml()
|
||||
self.assertXmlEqual("""
|
||||
<graphics type="spice" autoport="no" keymap="en_US" listen="127.0.0.1">
|
||||
<channel name="main" mode="secure"/>
|
||||
<channel name="display" mode="secure"/>
|
||||
<channel name="inputs" mode="secure"/>
|
||||
<channel name="cursor" mode="secure"/>
|
||||
<channel name="playback" mode="secure"/>
|
||||
<channel name="record" mode="secure"/>
|
||||
<channel name="smartcard" mode="secure"/>
|
||||
<channel name="usbredir" mode="secure"/>
|
||||
</graphics>
|
||||
""", xml)
|
||||
|
||||
def test_config_graphics_spice_secure_compression(self):
|
||||
obj = config.LibvirtConfigGuestGraphics()
|
||||
obj.type = "spice"
|
||||
obj.autoport = False
|
||||
obj.keymap = "en_US"
|
||||
obj.listen = "127.0.0.1"
|
||||
|
||||
obj.secure = True
|
||||
|
||||
obj.image_compression = "auto_glz"
|
||||
obj.jpeg_compression = "auto"
|
||||
obj.zlib_compression = "always"
|
||||
obj.playback_compression = True
|
||||
obj.streaming_mode = "filter"
|
||||
|
||||
xml = obj.to_xml()
|
||||
self.assertXmlEqual("""
|
||||
<graphics type="spice" autoport="no" keymap="en_US" listen="127.0.0.1">
|
||||
<image compression="auto_glz"/>
|
||||
<jpeg compression="auto"/>
|
||||
<zlib compression="always"/>
|
||||
<playback compression="on"/>
|
||||
<streaming mode="filter"/>
|
||||
<channel name="main" mode="secure"/>
|
||||
<channel name="display" mode="secure"/>
|
||||
<channel name="inputs" mode="secure"/>
|
||||
<channel name="cursor" mode="secure"/>
|
||||
<channel name="playback" mode="secure"/>
|
||||
<channel name="record" mode="secure"/>
|
||||
<channel name="smartcard" mode="secure"/>
|
||||
<channel name="usbredir" mode="secure"/>
|
||||
</graphics>
|
||||
""", xml)
|
||||
|
||||
|
||||
class LibvirtConfigGuestHostdev(LibvirtConfigBaseTest):
|
||||
|
||||
@@ -5907,6 +5907,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
self.assertIsNone(cfg.devices[3].zlib_compression)
|
||||
self.assertIsNone(cfg.devices[3].playback_compression)
|
||||
self.assertIsNone(cfg.devices[3].streaming_mode)
|
||||
self.assertFalse(cfg.devices[3].secure)
|
||||
|
||||
def test_get_guest_config_with_vnc_and_tablet(self):
|
||||
self.flags(enabled=True, group='vnc')
|
||||
@@ -5942,6 +5943,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
self.assertIsNone(cfg.devices[3].zlib_compression)
|
||||
self.assertIsNone(cfg.devices[3].playback_compression)
|
||||
self.assertIsNone(cfg.devices[3].streaming_mode)
|
||||
self.assertFalse(cfg.devices[3].secure)
|
||||
self.assertEqual(cfg.devices[5].type, 'tablet')
|
||||
|
||||
def test_get_guest_config_with_spice_and_tablet(self):
|
||||
@@ -5983,6 +5985,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
self.assertIsNone(cfg.devices[3].zlib_compression)
|
||||
self.assertIsNone(cfg.devices[3].playback_compression)
|
||||
self.assertIsNone(cfg.devices[3].streaming_mode)
|
||||
self.assertFalse(cfg.devices[3].secure)
|
||||
self.assertEqual(cfg.devices[5].type, 'tablet')
|
||||
|
||||
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
|
||||
@@ -6047,6 +6050,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
self.assertIsNone(cfg.devices[4].zlib_compression)
|
||||
self.assertIsNone(cfg.devices[4].playback_compression)
|
||||
self.assertIsNone(cfg.devices[4].streaming_mode)
|
||||
self.assertFalse(cfg.devices[4].secure)
|
||||
self.assertEqual(cfg.devices[5].type, video_type)
|
||||
|
||||
def test_get_guest_config_with_spice_compression(self):
|
||||
@@ -6092,6 +6096,43 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
self.assertEqual(cfg.devices[3].zlib_compression, 'always')
|
||||
self.assertFalse(cfg.devices[3].playback_compression)
|
||||
self.assertEqual(cfg.devices[3].streaming_mode, 'all')
|
||||
self.assertFalse(cfg.devices[3].secure)
|
||||
|
||||
def test_get_guest_config_with_spice_secure(self):
|
||||
self.flags(enabled=False, group='vnc')
|
||||
self.flags(virt_type='kvm', group='libvirt')
|
||||
self.flags(enabled=True,
|
||||
agent_enabled=False,
|
||||
require_secure=True,
|
||||
server_listen='10.0.0.1',
|
||||
group='spice')
|
||||
self.flags(pointer_model='usbtablet')
|
||||
|
||||
cfg = self._get_guest_config_with_graphics()
|
||||
|
||||
self.assertEqual(len(cfg.devices), 9)
|
||||
self.assertIsInstance(cfg.devices[0],
|
||||
vconfig.LibvirtConfigGuestDisk)
|
||||
self.assertIsInstance(cfg.devices[1],
|
||||
vconfig.LibvirtConfigGuestDisk)
|
||||
self.assertIsInstance(cfg.devices[2],
|
||||
vconfig.LibvirtConfigGuestSerial)
|
||||
self.assertIsInstance(cfg.devices[3],
|
||||
vconfig.LibvirtConfigGuestGraphics)
|
||||
self.assertIsInstance(cfg.devices[4],
|
||||
vconfig.LibvirtConfigGuestVideo)
|
||||
self.assertIsInstance(cfg.devices[5],
|
||||
vconfig.LibvirtConfigGuestInput)
|
||||
self.assertIsInstance(cfg.devices[6],
|
||||
vconfig.LibvirtConfigGuestRng)
|
||||
self.assertIsInstance(cfg.devices[7],
|
||||
vconfig.LibvirtConfigGuestUSBHostController)
|
||||
self.assertIsInstance(cfg.devices[8],
|
||||
vconfig.LibvirtConfigMemoryBalloon)
|
||||
|
||||
self.assertEqual(cfg.devices[3].type, 'spice')
|
||||
self.assertEqual(cfg.devices[3].listen, '10.0.0.1')
|
||||
self.assertTrue(cfg.devices[3].secure)
|
||||
|
||||
@mock.patch.object(host.Host, 'get_guest')
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver,
|
||||
|
||||
@@ -2188,6 +2188,7 @@ class LibvirtConfigGuestGraphics(LibvirtConfigGuestDevice):
|
||||
self.autoport = True
|
||||
self.keymap = None
|
||||
self.listen = None
|
||||
self.secure = None
|
||||
|
||||
self.image_compression = None
|
||||
self.jpeg_compression = None
|
||||
@@ -2222,6 +2223,11 @@ class LibvirtConfigGuestGraphics(LibvirtConfigGuestDevice):
|
||||
if self.streaming_mode is not None:
|
||||
dev.append(etree.Element(
|
||||
'streaming', mode=self.streaming_mode))
|
||||
if self.secure:
|
||||
for channel in ['main', 'display', 'inputs', 'cursor',
|
||||
'playback', 'record', 'smartcard', 'usbredir']:
|
||||
dev.append(etree.Element('channel', name=channel,
|
||||
mode='secure'))
|
||||
|
||||
return dev
|
||||
|
||||
|
||||
@@ -7711,6 +7711,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
graphics.zlib_compression = CONF.spice.zlib_compression
|
||||
graphics.playback_compression = CONF.spice.playback_compression
|
||||
graphics.streaming_mode = CONF.spice.streaming_mode
|
||||
graphics.secure = CONF.spice.require_secure
|
||||
guest.add_device(graphics)
|
||||
add_video_driver = True
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
This release adds a new config option require_secure to the spice
|
||||
configuration group. Defaulting to false to match the previous
|
||||
behavior, if set to true the SPICE consoles will require TLS
|
||||
protected connections. Unencrypted connections will be gracefully
|
||||
redirected to the TLS port via the SPICE protocol.
|
||||
Reference in New Issue
Block a user