From db7110d29788701a23ee8713a58c70e4e8e01ad2 Mon Sep 17 00:00:00 2001 From: Damian Dabrowski Date: Tue, 4 Apr 2023 23:20:27 +0200 Subject: [PATCH] Add PKI support to horizon backends Replace legacy SSL support with ansible-role-pki. It is used to generate required TLS certificates if needed. Depends-On: https://review.opendev.org/c/openstack/openstack-ansible/+/879085 Change-Id: Id2f9d6f911cee6e58c261c1a68c34a37ab9ced4f --- defaults/main.yml | 59 ++++++++++++++++--- handlers/main.yml | 1 + ...izon_ssl_self_signed-aea616a3e1259a6c.yaml | 6 ++ tasks/horizon_ssl_key_create.yml | 31 ---------- tasks/horizon_ssl_key_distribute.yml | 30 ---------- tasks/horizon_ssl_key_store.yml | 31 ---------- tasks/horizon_ssl_self_signed.yml | 23 -------- tasks/horizon_ssl_user_provided.yml | 44 -------------- tasks/main.yml | 42 +++++++------ 9 files changed, 77 insertions(+), 190 deletions(-) create mode 100644 releasenotes/notes/horizon_ssl_self_signed-aea616a3e1259a6c.yaml delete mode 100644 tasks/horizon_ssl_key_create.yml delete mode 100644 tasks/horizon_ssl_key_distribute.yml delete mode 100644 tasks/horizon_ssl_key_store.yml delete mode 100644 tasks/horizon_ssl_self_signed.yml delete mode 100644 tasks/horizon_ssl_user_provided.yml diff --git a/defaults/main.yml b/defaults/main.yml index 8ee5ba29..af9efe59 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -230,16 +230,9 @@ horizon_ssl_protocol: "{{ ssl_protocol | default('ALL -SSLv2 -SSLv3 -TLSv1 -TLSv horizon_ssl_cipher_suite_tls12: "{{ horizon_ssl_cipher_suite | default(ssl_cipher_suite | default('ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:ECDH+AES128:!aNULL:!SHA1:!AESCCM')) }}" # TLS v1.3 horizon_ssl_cipher_suite_tls13: "{{ ssl_cipher_suite_tls13 | default('TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256') }}" -# 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 variables to deploy custom certificates -# horizon_user_ssl_cert: -# horizon_user_ssl_key: -# horizon_user_ssl_ca_cert: - -# Toggle whether horizon should be served via SSL +# Define if communication between haproxy and service backends should be +# encrypted with TLS. # NOTE(damiandabrowski): Remove backward compatibility with horizon_enable_ssl in 2024.1 horizon_backend_ssl: "{{ horizon_enable_ssl | default(openstack_service_backend_ssl | default(False)) }}" @@ -532,3 +525,51 @@ horizon_websso_default_redirect: False horizon_websso_default_redirect_region: "{{ horizon_websso_keystone_url | default(horizon_keystone_endpoint) }}" horizon_websso_default_redirect_logout: "" horizon_websso_use_http_referer: True + +### +### Backend TLS +### + +# Storage location for SSL certificate authority +horizon_pki_dir: "{{ openstack_pki_dir | default('/etc/openstack_deploy/pki') }}" + +# Delegated host for operating the certificate authority +horizon_pki_setup_host: "{{ openstack_pki_setup_host | default('localhost') }}" + +# horizon server certificate +horizon_pki_keys_path: "{{ horizon_pki_dir ~ '/certs/private/' }}" +horizon_pki_certs_path: "{{ horizon_pki_dir ~ '/certs/certs/' }}" +horizon_pki_intermediate_cert_name: "{{ openstack_pki_service_intermediate_cert_name | default('ExampleCorpIntermediate') }}" +horizon_pki_intermediate_cert_path: "{{ horizon_pki_dir ~ '/roots/' ~ horizon_pki_intermediate_cert_name ~ '/certs/' ~ horizon_pki_intermediate_cert_name ~ '.crt' }}" +horizon_pki_regen_cert: '' +horizon_pki_san: "{{ openstack_pki_san | default('DNS:' ~ ansible_facts['hostname'] ~ ',IP:' ~ management_address) }}" +horizon_pki_certificates: + - name: "horizon_{{ ansible_facts['hostname'] }}" + provider: ownca + cn: "{{ ansible_facts['hostname'] }}" + san: "{{ horizon_pki_san }}" + signed_by: "{{ horizon_pki_intermediate_cert_name }}" + +# Installation details for SSL certificates +horizon_pki_install_certificates: + - src: "{{ horizon_user_ssl_cert | default(horizon_pki_certs_path ~ 'horizon_' ~ ansible_facts['hostname'] ~ '-chain.crt') }}" + dest: "{{ horizon_ssl_cert }}" + owner: "{{ horizon_system_user_name }}" + group: "{{ horizon_system_group_name }}" + mode: "0644" + - src: "{{ horizon_user_ssl_key | default(horizon_pki_keys_path ~ 'horizon_' ~ ansible_facts['hostname'] ~ '.key.pem') }}" + dest: "{{ horizon_ssl_key }}" + owner: "{{ horizon_system_user_name }}" + group: "{{ horizon_system_group_name }}" + mode: "0600" + - src: "{{ horizon_user_ssl_ca_cert | default(horizon_pki_intermediate_cert_path) }}" + dest: "{{ horizon_ssl_ca_cert }}" + owner: "{{ horizon_system_user_name }}" + group: "{{ horizon_system_group_name }}" + mode: "0644" + condition: "{{ horizon_user_ssl_ca_cert is defined }}" + +# Define user-provided SSL certificates +#horizon_user_ssl_cert: +#horizon_user_ssl_key: +#horizon_user_ssl_ca_cert: diff --git a/handlers/main.yml b/handlers/main.yml index 291fbf78..240d91c7 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -30,3 +30,4 @@ daemon_reload: "{{ (ansible_facts['service_mgr'] == 'systemd') | ternary('yes', omit) }}" listen: - "venv changed" + - "cert installed" diff --git a/releasenotes/notes/horizon_ssl_self_signed-aea616a3e1259a6c.yaml b/releasenotes/notes/horizon_ssl_self_signed-aea616a3e1259a6c.yaml new file mode 100644 index 00000000..e7e5c403 --- /dev/null +++ b/releasenotes/notes/horizon_ssl_self_signed-aea616a3e1259a6c.yaml @@ -0,0 +1,6 @@ +--- +deprecations: + - | + Variables ``horizon_ssl_self_signed_regen`` and + ``horizon_ssl_self_signed_subject`` are deprecated. Horizon role uses + ansible-role-pki now so they are no longer needed. diff --git a/tasks/horizon_ssl_key_create.yml b/tasks/horizon_ssl_key_create.yml deleted file mode 100644 index c02aee29..00000000 --- a/tasks/horizon_ssl_key_create.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -# Copyright 2014, Rackspace US, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -- name: Remove self signed cert for regen - file: - dest: "{{ horizon_ssl_cert }}" - state: "absent" - when: horizon_ssl_self_signed_regen | bool - -- name: Create self-signed ssl cert - command: > - openssl req -new -nodes -sha256 -x509 -subj - "{{ horizon_ssl_self_signed_subject }}" - -days 3650 - -keyout {{ horizon_ssl_key }} - -out {{ horizon_ssl_cert }} - -extensions v3_ca - creates={{ horizon_ssl_cert }} - notify: Restart wsgi process diff --git a/tasks/horizon_ssl_key_distribute.yml b/tasks/horizon_ssl_key_distribute.yml deleted file mode 100644 index 2e80b536..00000000 --- a/tasks/horizon_ssl_key_distribute.yml +++ /dev/null @@ -1,30 +0,0 @@ ---- -# Copyright 2014, Rackspace US, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -- name: Distribute self signed ssl key - copy: - dest: "{{ horizon_ssl_key }}" - content: "{{ hostvars[groups['horizon_all'][0]]['horizon_ssl_key_fact'] | b64decode }}" - owner: "{{ horizon_system_user_name }}" - group: "{{ horizon_system_group_name }}" - mode: "0640" - -- name: Distribute self signed ssl cert - copy: - dest: "{{ horizon_ssl_cert }}" - content: "{{ hostvars[groups['horizon_all'][0]]['horizon_ssl_cert_fact'] | b64decode }}" - owner: "{{ horizon_system_user_name }}" - group: "{{ horizon_system_group_name }}" - mode: "0640" diff --git a/tasks/horizon_ssl_key_store.yml b/tasks/horizon_ssl_key_store.yml deleted file mode 100644 index f7a103d2..00000000 --- a/tasks/horizon_ssl_key_store.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -# Copyright 2014, Rackspace US, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -- name: Store ssl cert - slurp: - src: "{{ horizon_ssl_cert }}" - register: _horizon_ssl_cert - changed_when: false - -- name: Store ssl key - slurp: - src: "{{ horizon_ssl_key }}" - register: _horizon_ssl_key - changed_when: false - -- name: Register a fact for the cert and key - set_fact: - horizon_ssl_cert_fact: "{{ _horizon_ssl_cert.content }}" - horizon_ssl_key_fact: "{{ _horizon_ssl_key.content }}" diff --git a/tasks/horizon_ssl_self_signed.yml b/tasks/horizon_ssl_self_signed.yml deleted file mode 100644 index a5fdad1d..00000000 --- a/tasks/horizon_ssl_self_signed.yml +++ /dev/null @@ -1,23 +0,0 @@ ---- -# Copyright 2014, Rackspace US, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -- include_tasks: horizon_ssl_key_create.yml - when: inventory_hostname == groups['horizon_all'][0] - -- include_tasks: horizon_ssl_key_store.yml - when: inventory_hostname == groups['horizon_all'][0] - -- include_tasks: horizon_ssl_key_distribute.yml - when: inventory_hostname != groups['horizon_all'][0] diff --git a/tasks/horizon_ssl_user_provided.yml b/tasks/horizon_ssl_user_provided.yml deleted file mode 100644 index 59151835..00000000 --- a/tasks/horizon_ssl_user_provided.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Copyright 2014, Rackspace US, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -- name: Drop user provided ssl cert - copy: - src: "{{ horizon_user_ssl_cert }}" - dest: "{{ horizon_ssl_cert }}" - owner: "root" - group: "root" - mode: "0644" - when: horizon_user_ssl_cert is defined - notify: Restart wsgi process - -- name: Drop user provided ssl key - copy: - src: "{{ horizon_user_ssl_key }}" - dest: "{{ horizon_ssl_key }}" - owner: "root" - group: "root" - mode: "0640" - when: horizon_user_ssl_key is defined - notify: Restart wsgi process - -- 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 wsgi process diff --git a/tasks/main.yml b/tasks/main.yml index 75c0a4e9..81e6b334 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -51,32 +51,30 @@ tags: - horizon-install +- name: Create and install SSL certificates + include_role: + name: pki + tasks_from: main_certs.yml + apply: + tags: + - horizon-config + - pki + vars: + pki_setup_host: "{{ horizon_pki_setup_host }}" + pki_dir: "{{ horizon_pki_dir }}" + pki_create_certificates: "{{ horizon_user_ssl_cert is not defined and horizon_user_ssl_key is not defined }}" + pki_regen_cert: "{{ horizon_pki_regen_cert }}" + pki_certificates: "{{ horizon_pki_certificates }}" + pki_install_certificates: "{{ horizon_pki_install_certificates }}" + when: + - horizon_backend_ssl + tags: + - always + - import_tasks: horizon_post_install.yml tags: - horizon-config -- import_tasks: horizon_ssl_self_signed.yml - when: - - horizon_backend_ssl | bool - - horizon_user_ssl_cert is not defined or horizon_user_ssl_key is not defined - tags: - - horizon-config - -- import_tasks: horizon_ssl_user_provided.yml - when: - - horizon_backend_ssl | bool - tags: - - horizon-config - -- name: Update the ca certificates - command: "update-ca-certificates -f" - when: - - horizon_backend_ssl | bool - - ansible_facts['pkg_mgr'] == 'apt' - tags: - - horizon-config - - horizon-ssl - - import_tasks: horizon_service_setup.yml when: - ('horizon_all' in group_names)