Browse code

nova: add support for TLS between novnc proxy & compute nodes

Nova is gaining the ability to run TLS over the connection between the
novnc proxy service and the QEMU/KVM compute node VNC server.

This adds a new config param - 'NOVA_CONSOLE_PROXY_COMPUTE_TLS=True' -
which instructs devstack to configure libvirt/QEMU to enable TLS for the
VNC server, and to configure the novncproxy to use TLS when connecting.
NB this use of TLS is distinct from use of TLS for the public facing API
controlled by USE_SSL, they can be enabled independently.

This is done in a generic manner so that it is easy to extend to cover
use of TLS with the SPICE and serial console proxy services too.

Change-Id: Ib29d3f5f18533115b9c51e27b373e92fc0a28d1a
Depends-on: I9cc9a380500715e60bd05aa5c29ee46bc6f8d6c2
Implements bp: websocket-proxy-to-host-security

Daniel P. Berrange authored on 2016/11/10 22:03:32
Showing 3 changed files
... ...
@@ -82,6 +82,10 @@ if is_service_enabled tls-proxy; then
82 82
     NOVA_SERVICE_PROTOCOL="https"
83 83
 fi
84 84
 
85
+# Whether to use TLS for comms between the VNC/SPICE/serial proxy
86
+# services and the compute node
87
+NOVA_CONSOLE_PROXY_COMPUTE_TLS=${NOVA_CONSOLE_PROXY_COMPUTE_TLS:-False}
88
+
85 89
 # Public facing bits
86 90
 NOVA_SERVICE_HOST=${NOVA_SERVICE_HOST:-$SERVICE_HOST}
87 91
 NOVA_SERVICE_PORT=${NOVA_SERVICE_PORT:-8774}
... ...
@@ -197,6 +201,13 @@ function is_n-cell_enabled {
197 197
     return 1
198 198
 }
199 199
 
200
+# is_nova_console_proxy_compute_tls_enabled() - Test if the Nova Console Proxy
201
+# service has TLS enabled
202
+function is_nova_console_proxy_compute_tls_enabled {
203
+    [[ ${NOVA_CONSOLE_PROXY_COMPUTE_TLS} = "True" ]] && return 0
204
+    return 1
205
+}
206
+
200 207
 # Helper to clean iptables rules
201 208
 function clean_iptables {
202 209
     # Delete rules
... ...
@@ -524,6 +535,17 @@ function create_nova_conf {
524 524
         iniset $NOVA_CONF vnc server_proxyclient_address "$VNCSERVER_PROXYCLIENT_ADDRESS"
525 525
         iniset $NOVA_CONF vnc novncproxy_host "$NOVA_SERVICE_LISTEN_ADDRESS"
526 526
         iniset $NOVA_CONF vnc xvpvncproxy_host "$NOVA_SERVICE_LISTEN_ADDRESS"
527
+
528
+        if is_nova_console_proxy_compute_tls_enabled ; then
529
+            iniset $NOVA_CONF vnc auth_schemes "vencrypt"
530
+            iniset $NOVA_CONF vnc vencrypt_client_key "/etc/pki/nova-novnc/client-key.pem"
531
+            iniset $NOVA_CONF vnc vencrypt_client_cert "/etc/pki/nova-novnc/client-cert.pem"
532
+            iniset $NOVA_CONF vnc vencrypt_ca_certs "/etc/pki/nova-novnc/ca-cert.pem"
533
+
534
+            sudo mkdir -p /etc/pki/nova-novnc
535
+            deploy_int_CA /etc/pki/nova-novnc/ca-cert.pem
536
+            deploy_int_cert /etc/pki/nova-novnc/client-cert.pem /etc/pki/nova-novnc/client-key.pem
537
+        fi
527 538
     else
528 539
         iniset $NOVA_CONF vnc enabled false
529 540
     fi
... ...
@@ -147,6 +147,18 @@ EOF
147 147
         fi
148 148
     fi
149 149
 
150
+    if is_nova_console_proxy_compute_tls_enabled ; then
151
+        if is_service_enabled n-novnc ; then
152
+            echo "vnc_tls = 1" | sudo tee -a $QEMU_CONF
153
+            echo "vnc_tls_x509_verify = 1" | sudo tee -a $QEMU_CONF
154
+
155
+            sudo mkdir -p /etc/pki/libvirt-vnc
156
+            sudo chown libvirt-qemu:libvirt-qemu /etc/pki/libvirt-vnc
157
+            deploy_int_CA /etc/pki/libvirt-vnc/ca-cert.pem
158
+            deploy_int_cert /etc/pki/libvirt-vnc/server-cert.pem /etc/pki/libvirt-vnc/server-key.pem
159
+        fi
160
+    fi
161
+
150 162
     # Service needs to be started on redhat/fedora -- do a restart for
151 163
     # sanity after fiddling the config.
152 164
     restart_service $LIBVIRT_DAEMON
... ...
@@ -340,6 +340,24 @@ function make_root_CA {
340 340
     fi
341 341
 }
342 342
 
343
+# Deploy the service cert & key to a service specific
344
+# location
345
+function deploy_int_cert {
346
+    local cert_target_file=$1
347
+    local key_target_file=$2
348
+
349
+    sudo cp "$INT_CA_DIR/$DEVSTACK_CERT_NAME.crt" "$cert_target_file"
350
+    sudo cp "$INT_CA_DIR/private/$DEVSTACK_CERT_NAME.key" "$key_target_file"
351
+}
352
+
353
+# Deploy the intermediate CA cert bundle file to a service
354
+# specific location
355
+function deploy_int_CA {
356
+    local ca_target_file=$1
357
+
358
+    sudo cp "$INT_CA_DIR/ca-chain.pem" "$ca_target_file"
359
+}
360
+
343 361
 # If a non-system python-requests is installed then it will use the
344 362
 # built-in CA certificate store rather than the distro-specific
345 363
 # CA certificate store. Detect this and symlink to the correct