From 271bf642398adf39f4701a19a7aec1f5c4ab832a Mon Sep 17 00:00:00 2001 From: Jesse Pretorius Date: Fri, 17 Jul 2015 11:38:00 +0100 Subject: [PATCH] Fix Horizon SSL certificate management and distribution This patch revises the SSL certificate management and distribution with something that is more consistent with how it's done everywhere else in the project. It also repairs the current user provided certificate distribution which was broken. * The server key/certificate (and optionally a CA cert) are distributed to all horizon containers. * Two new variables have been implemented for a user-provided server key and certificate: - horizon_user_ssl_cert: - horizon_user_ssl_key: If either of these is not defined, then the missing cert/key will be self generated on the first Horizon container and distributed to the other containers. * A new variable has been implemented for a user-provided CA certificate: - horizon_user_ssl_ca_cert: * A new variable called 'horizon_ssl_self_signed_subject' has been implemented to allow the user to override the self-signed certificate properties, such as the CN and subjectAltName. Upgrade notes: * The Apache configuration appropriately implements the 'SSLCACertificateFile' instead of the 'SSLCACertificatePath' directive in order to ensure that the appropriate signing certificate is provided to the browser. * The variable 'horizon_self_signed' (which defaulted to true) has been removed. The decision of whether to generate a self-signed certificate has been made based on whether a user provided key/cert pair has been provided. * The 'horizon_self_signed_regen' variable has been renamed to 'horizon_ssl_self_signed_regen'. * The default names for the deployed keys/certificates have been changed: - /etc/ssl/certs/apache.cert > /etc/ssl/certs/horizon.pem - /etc/ssl/private/apache.key > /etc/ssl/private/horizon.key DocImpact UpgradeImpact Closes-Bug: #1475578 Change-Id: I7089abbd81ce422b21ce65488e8bc32053ba32ca --- defaults/main.yml | 23 ++++++++++++++++------- tasks/horizon_ssl_key_create.yml | 12 ++++-------- tasks/horizon_ssl_key_distribute.yml | 6 ++---- tasks/horizon_ssl_key_store.yml | 6 ++---- tasks/horizon_ssl_user_provided.yml | 20 +++++++++++++++++--- tasks/main.yml | 7 ++----- templates/openstack_dashboard.conf.j2 | 5 +++-- 7 files changed, 46 insertions(+), 33 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 364ad611..d58d263e 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -50,8 +50,6 @@ horizon_endpoint_type: internalURL horizon_server_name: "horizon" horizon_log_level: info -horizon_self_signed: true -horizon_self_signed_regen: false horizon_dropdown_max_items: 30 horizon_time_zone: UTC horizon_enforce_password_check: False @@ -59,13 +57,18 @@ horizon_disable_password_reveal: False horizon_enable_password_retrieve: False ## Horizon SSL -### Set the cacert pem if you'd like horizon to verify it. -# horizon_cacert_pem: /path/to/cacert.pem -horizon_ssl_cert: /etc/ssl/certs/apache.cert -horizon_ssl_key: /etc/ssl/private/apache.key -horizon_ssl_cert_path: /etc/ssl/certs +horizon_ssl_cert: /etc/ssl/certs/horizon.pem +horizon_ssl_key: /etc/ssl/private/horizon.key +horizon_ssl_ca_cert: /etc/ssl/certs/horizon-ca.pem horizon_ssl_protocol: "{{ ssl_protocol }}" horizon_ssl_cipher_suite: "{{ ssl_cipher_suite }}" +# if using a self-signed certificate, set this to true to regenerate it +horizon_ssl_self_signed_regen: false +horizon_ssl_self_signed_subject: "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ horizon_server_name }}/subjectAltName=IP.1={{ external_lb_vip_address }}" +# Set these in user_variables to deploy custom certificates +#horizon_user_ssl_cert: +#horizon_user_ssl_key: +#horizon_user_ssl_ca_cert: # For multiple regions uncomment this configuration, and # add the extra endpoints below the first list item. @@ -73,6 +76,12 @@ horizon_ssl_cipher_suite: "{{ ssl_cipher_suite }}" # - { url: "{{ keystone_service_internalurl }}", name: "{{ keystone_service_region }}" } # - { url: "http://cluster1.example.com:5000/v2.0", name: "RegionTwo" } +### Set the cacert pem for Keystone if you'd like Horizon to verify it. +# horizon_cacert_pem: /path/to/cacert.pem + +## alternatively, you can set horizon to turn off ssl verification for Keystone +horizon_ssl_no_verify: "{{ (keystone_service_adminuri_insecure | bool or keystone_service_internaluri_insecure | bool) | default(false) }}" + ## Launch instance horizon_launch_instance_legacy: True horizon_launch_instance_ng: False diff --git a/tasks/horizon_ssl_key_create.yml b/tasks/horizon_ssl_key_create.yml index f400fa5a..0e36cfe7 100644 --- a/tasks/horizon_ssl_key_create.yml +++ b/tasks/horizon_ssl_key_create.yml @@ -17,23 +17,19 @@ file: dest: "{{ horizon_ssl_cert }}" state: "absent" - when: > - horizon_self_signed_regen == true or - horizon_self_signed_regen == "True" + when: horizon_ssl_self_signed_regen | bool + tags: + - horizon-ssl - name: Create self-signed ssl cert command: > openssl req -new -nodes -sha256 -x509 -subj - "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ horizon_server_name }}" + "{{ horizon_ssl_self_signed_subject }}" -days 3650 -keyout {{ horizon_ssl_key }} -out {{ horizon_ssl_cert }} -extensions v3_ca creates={{ horizon_ssl_cert }} - when: > - horizon_self_signed == true or - horizon_self_signed == "True" notify: Restart apache2 tags: - - horizon-apache-self-ssl - horizon-ssl diff --git a/tasks/horizon_ssl_key_distribute.yml b/tasks/horizon_ssl_key_distribute.yml index ba151a7c..25c13f60 100644 --- a/tasks/horizon_ssl_key_distribute.yml +++ b/tasks/horizon_ssl_key_distribute.yml @@ -23,14 +23,12 @@ server: "{{ memcached_servers }}" encrypt_string: "{{ memcached_encryption_key }}" with_items: - - { src: "{{ horizon_ssl_cert }}", name: "apache_cert", file_mode: "0640", dir_mode: "0750" } - - { src: "{{ horizon_ssl_key }}", name: "apache_key", file_mode: "0640", dir_mode: "0750" } + - { src: "{{ horizon_ssl_cert }}", name: "horizon_ssl_cert", file_mode: "0640", dir_mode: "0750" } + - { src: "{{ horizon_ssl_key }}", name: "horizon_ssl_key", file_mode: "0640", dir_mode: "0750" } register: memcache_keys until: memcache_keys|success retries: 5 delay: 2 notify: Restart apache2 tags: - - horizon-key - - horizon-key-distribute - horizon-ssl diff --git a/tasks/horizon_ssl_key_store.yml b/tasks/horizon_ssl_key_store.yml index bbf8a612..d06ab80b 100644 --- a/tasks/horizon_ssl_key_store.yml +++ b/tasks/horizon_ssl_key_store.yml @@ -21,13 +21,11 @@ server: "{{ memcached_servers }}" encrypt_string: "{{ memcached_encryption_key }}" with_items: - - { src: "{{ horizon_ssl_cert }}", name: "apache_cert" } - - { src: "{{ horizon_ssl_key }}", name: "apache_key" } + - { src: "{{ horizon_ssl_cert }}", name: "horizon_ssl_cert" } + - { src: "{{ horizon_ssl_key }}", name: "horizon_ssl_key" } register: memcache_keys until: memcache_keys|success retries: 5 delay: 2 tags: - - horizon-key - - horizon-key-store - horizon-ssl diff --git a/tasks/horizon_ssl_user_provided.yml b/tasks/horizon_ssl_user_provided.yml index e723abdc..b64607ac 100644 --- a/tasks/horizon_ssl_user_provided.yml +++ b/tasks/horizon_ssl_user_provided.yml @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -- name: Drop user provided ssl cert +- name: Drop user provided ssl cert and key copy: src: "{{ item.src }}" dest: "{{ item.dest }}" @@ -21,9 +21,23 @@ group: "root" mode: "{{ item.mode }}" with_items: - - { src: "/etc/ssl/certs/apache.cert", name: "apache.cert", mode: "0640" } - - { src: "/etc/ssl/private/apache.key", name: "apache.key", mode: "0640" } + - { src: "{{ horizon_user_ssl_cert }}", dest: "{{ horizon_ssl_cert }}", mode: "0644" } + - { src: "{{ horizon_user_ssl_key }}", dest: "{{ horizon_ssl_key }}", mode: "0640" } + when: horizon_user_ssl_cert is defined and horizon_user_ssl_key is defined notify: Restart apache2 tags: - horizon-configs - horizon-ssl + +- name: Drop user provided ssl CA cert + copy: + src: "{{ horizon_user_ssl_ca_cert }}" + dest: "{{ horizon_ssl_ca_cert }}" + owner: "root" + group: "root" + mode: "0644" + when: horizon_user_ssl_ca_cert is defined + notify: Restart apache2 + tags: + - keystone-configs + - keystone-ssl diff --git a/tasks/main.yml b/tasks/main.yml index 4de972d1..87b0a03b 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -23,13 +23,10 @@ - include: horizon_ssl_self_signed.yml when: > - horizon_self_signed == true or - horizon_self_signed == "True" + horizon_user_ssl_cert is not defined or + horizon_user_ssl_key is not defined - include: horizon_ssl_user_provided.yml - when: > - horizon_self_signed == false or - horizon_self_signed == "False" - include: horizon_apache.yml diff --git a/templates/openstack_dashboard.conf.j2 b/templates/openstack_dashboard.conf.j2 index 4a4dc9c5..201ed4d8 100644 --- a/templates/openstack_dashboard.conf.j2 +++ b/templates/openstack_dashboard.conf.j2 @@ -20,8 +20,9 @@ SSLEngine on SSLCertificateFile {{ horizon_ssl_cert }} SSLCertificateKeyFile {{ horizon_ssl_key }} - SSLCACertificatePath {{ horizon_ssl_cert_path }} - SSLCARevocationPath {{ horizon_ssl_cert_path }} + {% if horizon_user_ssl_ca_cert is defined -%} + SSLCACertificateFile {{ horizon_ssl_ca_cert }} + {% endif -%} SSLCompression Off SSLProtocol All -SSLv2 -SSLv3 SSLHonorCipherOrder On