Merge "Implement nova memcache security strategy"
diff --git a/README.rst b/README.rst
index 673df92..98806c0 100644
--- a/README.rst
+++ b/README.rst
@@ -30,6 +30,7 @@
         workers: 8
         report_interval: 60
         dhcp_domain: novalocal
+        consoleauth_token_ttl: 600
         bind:
           public_address: 10.0.0.122
           public_name: openstack.domain.com
@@ -990,6 +991,32 @@
             key: (certificate content)
             cert: (certificate content)
 
+Controlling access by `tls_allowed_dn_list`.
+Enable an access control list of client certificate Distinguished Names (DNs)
+which can connect to the TLS port on this server. The default is that DNs are
+not checked. This list may contain wildcards such as
+"C=GB,ST=London,L=London,O=Libvirt Project,CN=*" See the POSIX fnmatch function
+for the format of the wildcards.
+Note that if this is an empty list, no client can connect.
+Note also that GnuTLS returns DNs without spaces after commas between
+the fields (and this is what we check against), but the openssl x509 tool
+shows spaces.
+
+.. code-block:: yaml
+
+  nova:
+    compute:
+      libvirt:
+        tls:
+          tls_allowed_dn_list:
+            host1:
+              enabled: true
+              value: 'C=foo,CN=cmp1'
+            host2:
+              enabled: true
+              value: 'C=foo,CN=cmp2'
+
+
 You can read more about live migration over TLS here:
 https://wiki.libvirt.org/page/TLSCreateServerCerts
 
diff --git a/nova/_ssl/mysql.sls b/nova/_ssl/mysql.sls
index 3d715e9..cc21c91 100644
--- a/nova/_ssl/mysql.sls
+++ b/nova/_ssl/mysql.sls
@@ -15,8 +15,8 @@
   file.managed:
     - name: {{ ca_file }}
     - contents_pillar: nova:controller:database:x509:cacert
-    - mode: 444
-    - user: nova
+    - mode: 644
+    - user: root
     - group: nova
     - makedirs: true
   {%- else %}
@@ -29,8 +29,8 @@
   file.managed:
     - name: {{ cert_file }}
     - contents_pillar: nova:controller:database:x509:cert
-    - mode: 440
-    - user: nova
+    - mode: 640
+    - user: root
     - group: nova
     - makedirs: true
   {%- else %}
@@ -43,8 +43,8 @@
   file.managed:
     - name: {{ key_file }}
     - contents_pillar: nova:controller:database:x509:key
-    - mode: 400
-    - user: nova
+    - mode: 640
+    - user: root
     - group: nova
     - makedirs: true
   {%- else %}
@@ -58,7 +58,7 @@
       - {{ ca_file }}
       - {{ cert_file }}
       - {{ key_file }}
-    - user: nova
+    - user: root
     - group: nova
 
   {% elif controller.database.get('ssl',{}).get('enabled',False) %}
@@ -67,11 +67,19 @@
   file.managed:
     - name: {{ controller.database.ssl.cacert_file }}
     - contents_pillar: nova:controller:database:ssl:cacert
-    - mode: 0444
+    - mode: 644
     - makedirs: true
+    - user: root
+    - group: nova
   {%- else %}
   file.exists:
     - name: {{ controller.database.ssl.get('cacert_file', controller.cacert_file) }}
   {%- endif %}
 
+mysql_nova_ssl_set_user_and_group:
+  file.managed:
+    - name: {{ controller.database.ssl.get('cacert_file', controller.cacert_file) }}
+    - user: root
+    - group: nova
+
 {%- endif %}
diff --git a/nova/_ssl/rabbitmq.sls b/nova/_ssl/rabbitmq.sls
index 0dc7c6e..6abb6f4 100644
--- a/nova/_ssl/rabbitmq.sls
+++ b/nova/_ssl/rabbitmq.sls
@@ -25,8 +25,8 @@
   file.managed:
     - name: {{ ca_file }}
     - contents_pillar: nova:{{ role }}:message_queue:x509:cacert
-    - mode: 444
-    - user: nova
+    - mode: 644
+    - user: root
     - group: nova
     - makedirs: true
   {%- else %}
@@ -39,8 +39,8 @@
   file.managed:
     - name: {{ cert_file }}
     - contents_pillar: nova:{{ role }}:message_queue:x509:cert
-    - mode: 440
-    - user: nova
+    - mode: 640
+    - user: root
     - group: nova
     - makedirs: true
   {%- else %}
@@ -53,8 +53,8 @@
   file.managed:
     - name: {{ key_file }}
     - contents_pillar: nova:{{ role }}:message_queue:x509:key
-    - mode: 400
-    - user: nova
+    - mode: 640
+    - user: root
     - group: nova
     - makedirs: true
   {%- else %}
@@ -68,7 +68,7 @@
       - {{ ca_file }}
       - {{ cert_file }}
       - {{ key_file }}
-    - user: nova
+    - user: root
     - group: nova
 
   {% elif nova_msg.get('ssl',{}).get('enabled',False) %}
@@ -77,11 +77,16 @@
   file.managed:
     - name: {{ nova_msg.ssl.cacert_file }}
     - contents_pillar: nova:{{ role }}:message_queue:ssl:cacert
-    - mode: 0444
+    - mode: 644
     - makedirs: true
   {%- else %}
   file.exists:
     - name: {{ nova_msg.ssl.get('cacert_file', nova_cacert) }}
   {%- endif %}
 
+rabbitmq_nova_{{ role }}_ssl_set_user_and_group:
+  file.managed:
+    - name: {{ nova_msg.ssl.get('cacert_file', nova_cacert) }}
+    - user: root
+    - group: nova
 {%- endif %}
diff --git a/nova/client/init.sls b/nova/client/init.sls
new file mode 100644
index 0000000..e058d2d
--- /dev/null
+++ b/nova/client/init.sls
@@ -0,0 +1,2 @@
+include:
+- nova.client.resources
diff --git a/nova/client.sls b/nova/client/resources/init.sls
similarity index 93%
rename from nova/client.sls
rename to nova/client/resources/init.sls
index 87ae2cb..6dae528 100644
--- a/nova/client.sls
+++ b/nova/client/resources/init.sls
@@ -1,11 +1,14 @@
 {%- from "nova/map.jinja" import client with context %}
 {%- if client.enabled %}
 
+include:
+- nova.client.resources.v21
+
 nova_client_packages:
   pkg.installed:
   - names: {{ client.pkgs }}
 
-{%- for identity_name, identity in client.server.iteritems() %}
+{%- for identity_name, identity in client.get('server', {}).iteritems() %}
 
 {%- if identity.flavor is defined %}
 
@@ -75,3 +78,4 @@
 {%- endfor %}
 
 {%- endif %}
+
diff --git a/nova/client/resources/v21.sls b/nova/client/resources/v21.sls
new file mode 100644
index 0000000..448a94c
--- /dev/null
+++ b/nova/client/resources/v21.sls
@@ -0,0 +1,33 @@
+{%- from "nova/map.jinja" import client with context %}
+{%- if client.enabled %}
+
+{%- for identity_name, identity in client.get('resources', {}).get('v21', {}).iteritems() %}
+
+  {%- if identity.flavor is defined %}
+  {%- for flavor_name, flavor in identity.flavor.iteritems() %}
+
+novav21_openstack_flavor_{{ flavor_name }}:
+  novav21.flavor_present:
+    - name: {{ flavor_name }}
+    - cloud_name: {{ identity_name }}
+    {%- if flavor.flavor_id is defined %}
+    - flavor_id: {{ flavor.flavor_id }}
+    {%- endif %}
+    {%- if flavor.ram is defined %}
+    - ram: {{ flavor.ram }}
+    {%- endif %}
+    {%- if flavor.disk is defined %}
+    - disk: {{ flavor.disk }}
+    {%- endif %}
+    {%- if flavor.vcpus is defined %}
+    - vcpus: {{ flavor.vcpus }}
+    {%- endif %}
+    {%- if flavor.extra_specs is defined %}
+    - extra_specs: {{ flavor.extra_specs }}
+    {%- endif %}
+
+  {%- endfor %}
+  {%- endif %}
+
+{%- endfor %}
+{%- endif %}
diff --git a/nova/compute.sls b/nova/compute.sls
index c088ccf..b7a2131 100644
--- a/nova/compute.sls
+++ b/nova/compute.sls
@@ -255,7 +255,7 @@
     - contents_pillar: nova:compute:qemu:vnc:tls:cacert
     - mode: 644
     - user: root
-    - group: libvirt-qemu
+    - group: nova
     - makedirs: true
     - require:
       - user: user_libvirt-qemu
@@ -271,7 +271,7 @@
     - contents_pillar: nova:compute:qemu:vnc:tls:cert
     - mode: 640
     - user: root
-    - group: libvirt-qemu
+    - group: nova
     - makedirs: true
     - require:
       - user: user_libvirt-qemu
@@ -287,7 +287,7 @@
     - contents_pillar: nova:compute:qemu:vnc:tls:key
     - mode: 640
     - user: root
-    - group: libvirt-qemu
+    - group: nova
     - makedirs: true
     - require:
       - user: user_libvirt-qemu
@@ -303,7 +303,7 @@
       - {{ cert_file }}
       - {{ key_file }}
     - user: root
-    - group: libvirt-qemu
+    - group: nova
     - require:
       - user: user_libvirt-qemu
 
diff --git a/nova/controller.sls b/nova/controller.sls
index f1819fb..b67926e 100644
--- a/nova/controller.sls
+++ b/nova/controller.sls
@@ -75,8 +75,10 @@
   file.managed:
     - name: {{ ca_file }}
     - contents_pillar: nova:controller:novncproxy:vencrypt:tls:cacert
-    - mode: 444
+    - mode: 644
     - makedirs: true
+    - user: root
+    - group: nova
     - watch_in:
       - service: nova_controller_services
 {%- else %}
@@ -89,7 +91,9 @@
   file.managed:
     - name: {{ cert_file }}
     - contents_pillar: nova:controller:novncproxy:vencrypt:tls:cert
-    - mode: 440
+    - mode: 640
+    - user: root
+    - group: nova
     - makedirs: true
 {%- else %}
   file.exists:
@@ -101,12 +105,24 @@
   file.managed:
     - name: {{ key_file }}
     - contents_pillar: nova:controller:novncproxy:vencrypt:tls:key
-    - mode: 400
+    - mode: 640
+    - user: root
+    - group: nova
     - makedirs: true
 {%- else %}
   file.exists:
    - name: {{ key_file }}
 {%- endif %}
+
+novncproxy_vencrypt_set_user_and_group:
+  file.managed:
+    - names:
+      - {{ ca_file }}
+      - {{ cert_file }}
+      - {{ key_file }}
+    - user: root
+    - group: nova
+
 {%- endif %}
 {%- endif %}
 
@@ -119,8 +135,10 @@
   file.managed:
     - name: {{ cert_file }}
     - contents_pillar: nova:controller:novncproxy:tls:server:cert
-    - mode: 440
+    - mode: 644
     - makedirs: true
+    - user: root
+    - group: nova
     - watch_in:
       - service: nova_controller_services
 {%- else %}
@@ -133,12 +151,23 @@
   file.managed:
     - name: {{ key_file }}
     - contents_pillar: nova:controller:novncproxy:tls:server:key
-    - mode: 400
+    - mode: 640
+    - user: root
+    - group: nova
     - makedirs: true
 {%- else %}
   file.exists:
    - name: {{ key_file }}
 {%- endif %}
+
+novncproxy_server_set_user_and_group:
+  file.managed:
+    - names:
+      - {{ cert_file }}
+      - {{ key_file }}
+    - user: root
+    - group: nova
+
 {%- endif %}
 
 {%- if controller.get('networking', 'default') == "contrail" and controller.version == "juno" %}
diff --git a/nova/files/pike/libvirtd.conf.Debian b/nova/files/pike/libvirtd.conf.Debian
index d8836f9..fdbcf9e 100644
--- a/nova/files/pike/libvirtd.conf.Debian
+++ b/nova/files/pike/libvirtd.conf.Debian
@@ -26,8 +26,16 @@
 {%- set key_file = compute.libvirt.tls.key_file %}
 {%- set cert_file = compute.libvirt.tls.cert_file %}
 {%- set ca_file = compute.libvirt.tls.ca_file %}
-{%- set unix_sock_ro_perms = "0000" %}
-{%- set unix_sock_rw_perms = "0000" %}
+{%- set unix_sock_ro_perms = "0777" %}
+{%- set unix_sock_rw_perms = "0770" %}
+{%- if compute.libvirt.tls.allowed_dn_list is defined %}
+  {% set tls_allowed_dn_list = [] %}
+  {%- for _,item in compute.libvirt.tls.allowed_dn_list.iteritems() %}
+    {%- if item.enabled %}
+      {%- do tls_allowed_dn_list.append(item.value) %}
+    {%- endif %}
+  {%- endfor %}
+{%- endif %}
 {%- else %}
 {%- set listen_tls = 0 %}
 {%- set listen_tcp = 1 %}
@@ -250,6 +258,9 @@
 # By default, no DN's are checked
 #tls_allowed_dn_list = ["DN1", "DN2"]
 
+{%- if tls_allowed_dn_list is defined %}
+tls_allowed_dn_list = {{ tls_allowed_dn_list }}
+{%- endif %}
 
 # A whitelist of allowed SASL usernames. The format for usernames
 # depends on the SASL authentication mechanism. Kerberos usernames
diff --git a/nova/files/pike/nova-controller.conf.Debian b/nova/files/pike/nova-controller.conf.Debian
index 1ed3cc8..de8325b 100644
--- a/nova/files/pike/nova-controller.conf.Debian
+++ b/nova/files/pike/nova-controller.conf.Debian
@@ -4314,7 +4314,9 @@
 # Minimum value: 0
 # Deprecated group/name - [DEFAULT]/console_token_ttl
 #token_ttl=600
-
+{% if controller.consoleauth_token_ttl is defined %}
+token_ttl = {{ controller.consoleauth_token_ttl }}
+{% endif %}
 
 [cors]
 
diff --git a/nova/files/queens/libvirtd.conf.Debian b/nova/files/queens/libvirtd.conf.Debian
index d8836f9..fdbcf9e 100644
--- a/nova/files/queens/libvirtd.conf.Debian
+++ b/nova/files/queens/libvirtd.conf.Debian
@@ -26,8 +26,16 @@
 {%- set key_file = compute.libvirt.tls.key_file %}
 {%- set cert_file = compute.libvirt.tls.cert_file %}
 {%- set ca_file = compute.libvirt.tls.ca_file %}
-{%- set unix_sock_ro_perms = "0000" %}
-{%- set unix_sock_rw_perms = "0000" %}
+{%- set unix_sock_ro_perms = "0777" %}
+{%- set unix_sock_rw_perms = "0770" %}
+{%- if compute.libvirt.tls.allowed_dn_list is defined %}
+  {% set tls_allowed_dn_list = [] %}
+  {%- for _,item in compute.libvirt.tls.allowed_dn_list.iteritems() %}
+    {%- if item.enabled %}
+      {%- do tls_allowed_dn_list.append(item.value) %}
+    {%- endif %}
+  {%- endfor %}
+{%- endif %}
 {%- else %}
 {%- set listen_tls = 0 %}
 {%- set listen_tcp = 1 %}
@@ -250,6 +258,9 @@
 # By default, no DN's are checked
 #tls_allowed_dn_list = ["DN1", "DN2"]
 
+{%- if tls_allowed_dn_list is defined %}
+tls_allowed_dn_list = {{ tls_allowed_dn_list }}
+{%- endif %}
 
 # A whitelist of allowed SASL usernames. The format for usernames
 # depends on the SASL authentication mechanism. Kerberos usernames
diff --git a/nova/files/queens/nova-compute.conf.Debian b/nova/files/queens/nova-compute.conf.Debian
index f7179e4..a18003b 100644
--- a/nova/files/queens/nova-compute.conf.Debian
+++ b/nova/files/queens/nova-compute.conf.Debian
@@ -4514,6 +4514,60 @@
 # Minimum value: 1
 #resource_provider_association_refresh = 300
 
+#
+# Determine if the source compute host should wait for a ``network-vif-plugged``
+# event from the (neutron) networking service before starting the actual
+# transfer
+# of the guest to the destination compute host.
+#
+# If you set this option the same on all of your compute hosts, which you should
+# do if you use the same networking backend universally, you do not have to
+# worry about this.
+#
+# Before starting the transfer of the guest, some setup occurs on the
+# destination
+# compute host, including plugging virtual interfaces. Depending on the
+# networking backend **on the destination host**, a ``network-vif-plugged``
+# event may be triggered and then received on the source compute host and the
+# source compute can wait for that event to ensure networking is set up on the
+# destination host before starting the guest transfer in the hypervisor.
+#
+# By default, this is False for two reasons:
+#
+# 1. Backward compatibility: deployments should test this out and ensure it
+# works
+#    for them before enabling it.
+#
+# 2. The compute service cannot reliably determine which types of virtual
+#    interfaces (``port.binding:vif_type``) will send ``network-vif-plugged``
+#    events without an accompanying port ``binding:host_id`` change.
+#    Open vSwitch and linuxbridge should be OK, but OpenDaylight is at least
+#    one known backend that will not currently work in this case, see bug
+#    https://launchpad.net/bugs/1755890 for more details.
+#
+# Possible values:
+#
+# * True: wait for ``network-vif-plugged`` events before starting guest transfer
+# * False: do not wait for ``network-vif-plugged`` events before starting guest
+#   transfer (this is how things have always worked before this option
+#   was introduced)
+#
+# Related options:
+#
+# * [DEFAULT]/vif_plugging_is_fatal: if ``live_migration_wait_for_vif_plug`` is
+#   True and ``vif_plugging_timeout`` is greater than 0, and a timeout is
+#   reached, the live migration process will fail with an error but the guest
+#   transfer will not have started to the destination host
+# * [DEFAULT]/vif_plugging_timeout: if ``live_migration_wait_for_vif_plug`` is
+#   True, this controls the amount of time to wait before timing out and either
+#   failing if ``vif_plugging_is_fatal`` is True, or simply continuing with the
+#   live migration
+#  (boolean value)
+#live_migration_wait_for_vif_plug = false
+{%- if pillar.get('neutron', {}).get('compute', {}).get('backend', {}).get('mechanism', {}).get('ovs', {}).get('driver', '') == 'openvswitch' %}
+live_migration_wait_for_vif_plug = true
+{%- endif %}
+
 
 [conductor]
 #
diff --git a/nova/files/queens/nova-controller.conf.Debian b/nova/files/queens/nova-controller.conf.Debian
index 9f8a624..66705ba 100644
--- a/nova/files/queens/nova-controller.conf.Debian
+++ b/nova/files/queens/nova-controller.conf.Debian
@@ -4533,6 +4533,9 @@
 # Minimum value: 0
 # Deprecated group/name - [DEFAULT]/console_token_ttl
 #token_ttl = 600
+{% if controller.consoleauth_token_ttl is defined %}
+token_ttl = {{ controller.consoleauth_token_ttl }}
+{% endif %}
 
 [cors]
 {%- if controller.cors is defined %}
diff --git a/tests/pillar/control_cluster.sls b/tests/pillar/control_cluster.sls
index f11a947..24fc414 100644
--- a/tests/pillar/control_cluster.sls
+++ b/tests/pillar/control_cluster.sls
@@ -11,6 +11,7 @@
     cpu_allocation_ratio: 16.0
     ram_allocation_ratio: 1.5
     disk_allocation_ratio: 1.0
+    consoleauth_token_ttl: 600
     workers: 8
     bind:
       private_address: 127.0.0.1