From 14a2bd072c8588a1f116727c1c394ce079c30cfc Mon Sep 17 00:00:00 2001 From: Jonathan Rosser Date: Mon, 21 Feb 2022 14:26:12 +0000 Subject: [PATCH] Migrate ssl certificate generation to the PKI role This is now common functionality in an ansible role, rather than being implemented directly in openstack-ansible service roles. This patch creates the apache server certificate and key using the pki role when keystone_ssl is true. A CA certificate and key are generated and installed when keystone is configured to be an IDP, triggered by keystone_idp.certfile being defined. Depends-On: https://review.opendev.org/c/openstack/ansible-role-pki/+/830794 Change-Id: Ie70aecc93b8acb7c1bbad02e98254b7c50c4c86f --- defaults/main.yml | 92 ++++++++++++++++++- ...eystone-use-pki-role-d0e905887a5f5bd1.yaml | 13 +++ tasks/keystone_idp_self_signed_create.yml | 45 --------- tasks/keystone_idp_self_signed_distribute.yml | 44 --------- tasks/keystone_idp_self_signed_store.yml | 29 ------ tasks/keystone_idp_setup.yml | 9 -- tasks/keystone_ssl.yml | 21 ----- tasks/keystone_ssl_key_create.yml | 46 ---------- tasks/keystone_ssl_key_distribute.yml | 48 ---------- tasks/keystone_ssl_key_store.yml | 31 ------- tasks/keystone_ssl_self_signed.yml | 23 ----- tasks/keystone_ssl_user_provided.yml | 50 ---------- tasks/main.yml | 16 +++- 13 files changed, 115 insertions(+), 352 deletions(-) create mode 100644 releasenotes/notes/keystone-use-pki-role-d0e905887a5f5bd1.yaml delete mode 100644 tasks/keystone_idp_self_signed_create.yml delete mode 100644 tasks/keystone_idp_self_signed_distribute.yml delete mode 100644 tasks/keystone_idp_self_signed_store.yml delete mode 100644 tasks/keystone_ssl.yml delete mode 100644 tasks/keystone_ssl_key_create.yml delete mode 100644 tasks/keystone_ssl_key_distribute.yml delete mode 100644 tasks/keystone_ssl_key_store.yml delete mode 100644 tasks/keystone_ssl_self_signed.yml delete mode 100644 tasks/keystone_ssl_user_provided.yml diff --git a/defaults/main.yml b/defaults/main.yml index 8f1662f1..4c5b28ed 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -235,20 +235,102 @@ keystone_default_uwsgi_overrides: socket: "127.0.0.1:{{ keystone_uwsgi_ports['keystone-wsgi-public']['socket'] }}" # set keystone_ssl to true to enable SSL configuration on the keystone containers -keystone_ssl: false +keystone_ssl: "{{ openstack_backend_service_https | default(False) }}" + +# The local address used for the keystone node +keystone_node_address: "{{ management_address | default('127.0.0.1') }}" + +# Storage location for SSL certificate authority +keystone_pki_dir: "{{ openstack_pki_dir }}" + +# Delegated host for operating the certificate authority +keystone_pki_setup_host: "{{ openstack_pki_setup_host | default('localhost') }}" + +keystone_pki_keys_path: "{{ keystone_pki_dir ~ '/certs/private/' }}" +keystone_pki_certs_path: "{{ keystone_pki_dir ~ '/certs/certs/' }}" +keystone_pki_intermediate_cert_name: "{{ openstack_pki_service_intermediate_cert_name }}" +keystone_pki_intermediate_cert_path: "{{ keystone_pki_dir ~ '/roots/' ~ keystone_pki_intermediate_cert_name ~ '/certs/' ~ keystone_pki_intermediate_cert_name ~ '.crt' }}" +keystone_pki_regen_cert: '' + +# By default, CA creation is controlled using the CA 'condition' field +keystone_pki_create_ca: True +# An optional private certificate authority for when Keystone is an IDP +keystone_idp_authority_name: "KeystoneIDPAuthority" +keystone_pki_authorities: + - name: "{{ keystone_idp_authority_name }}" + country: "GB" + state_or_province_name: "England" + organization_name: "Example Corporation" + organizational_unit_name: "IT Security" + cn: "Keystone IDP CA" + provider: selfsigned + basic_constraints: "CA:TRUE" + key_usage: + - digitalSignature + - keyCertSign + not_after: "+3650d" + condition: "{{ (keystone_idp['certfile'] is defined) and _keystone_is_first_play_host }}" + +# By default, certificate creation is controlled using the certificates 'condition' field +keystone_pki_create_certificates: True +# Server certificate for Apache +keystone_pki_certificates: + - name: "keystone_{{ ansible_facts['hostname'] }}" + provider: ownca + cn: "{{ ansible_facts['hostname'] }}" + san: "{{ 'DNS:' ~ ansible_facts['hostname'] ~ ',IP:' ~ keystone_node_address }}" + signed_by: "{{ keystone_pki_intermediate_cert_name }}" + condition: "{{ keystone_ssl }}" + +# Set to the value of keystone_idp_authority_name to regenerate the IDP CA +keystone_pki_regen_ca: '' + +# keystone destination files for Apache SSL certificates keystone_ssl_cert: /etc/ssl/certs/keystone.pem keystone_ssl_key: /etc/ssl/private/keystone.key keystone_ssl_ca_cert: /etc/ssl/certs/keystone-ca.pem + +# Installation details for SSL certificates +keystone_pki_install_certificates: + # Apache certificates + - src: "{{ keystone_user_ssl_cert | default(keystone_pki_certs_path ~ 'keystone_' ~ ansible_facts['hostname'] ~ '.crt') }}" + dest: "{{ keystone_ssl_cert }}" + owner: "keystone_system_user_name" + group: "keystone_system_group_name" + mode: "0644" + condition: "{{ keystone_ssl }}" + - src: "{{ keystone_user_ssl_key | default(keystone_pki_keys_path ~ 'keystone_' ~ ansible_facts['hostname'] ~ '.key.pem') }}" + dest: "{{ keystone_ssl_key }}" + owner: "keystone_system_user_name" + group: "keystone_system_group_name" + mode: "0600" + condition: "{{ keystone_ssl }}" + - src: "{{ keystone_user_ssl_ca_cert | default(keystone_pki_intermediate_cert_path) }}" + dest: "{{ keystone_ssl_ca_cert }}" + owner: "keystone_system_user_name" + group: "keystone_system_group_name" + mode: "0644" + condition: "{{ keystone_ssl }}" + # IDP certificates + - src: "{{ keystone_pki_dir ~ '/roots/' ~ keystone_idp_authority_name ~ '/certs/' ~ keystone_idp_authority_name ~ '.crt' }}" + dest: "{{ keystone_idp['certfile'] }}" + owner: "keystone_system_user_name" + group: "keystone_system_group_name" + mode: "0640" + condition: "{{ keystone_idp['certfile'] is defined | bool }}" + - src: "{{ keystone_pki_dir ~ '/roots/' ~ keystone_idp_authority_name ~ '/private/' ~ keystone_idp_authority_name ~ '.key.pem' }}" + dest: "{{ keystone_idp['keyfile'] }}" + owner: "keystone_system_user_name" + group: "keystone_system_group_name" + mode: "0640" + condition: "{{ keystone_idp['keyfile'] is defined | bool }}" + keystone_ssl_protocol: "{{ ssl_protocol | default('ALL -SSLv2 -SSLv3 -TLSv1 -TLSv1.1') }}" # TLS v1.2 and below keystone_ssl_cipher_suite_tls12: "{{ keystone_ssl_cipher_suite | default(ssl_cipher_suite_tls12 | default('ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS')) }}" # TLS v1.3 keystone_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 -keystone_ssl_self_signed_regen: false -keystone_ssl_self_signed_subject: "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ internal_lb_vip_address }}/subjectAltName=IP.1={{ external_lb_vip_address }}" - # Set these variables to deploy custom certificates #keystone_user_ssl_cert: #keystone_user_ssl_key: diff --git a/releasenotes/notes/keystone-use-pki-role-d0e905887a5f5bd1.yaml b/releasenotes/notes/keystone-use-pki-role-d0e905887a5f5bd1.yaml new file mode 100644 index 00000000..3253c7e8 --- /dev/null +++ b/releasenotes/notes/keystone-use-pki-role-d0e905887a5f5bd1.yaml @@ -0,0 +1,13 @@ +--- +upgrade: + - | + The keystone installation now uses ansible-role-pki to create and install + a server certificate for Apache when keystone_ssl is true. The same role + is also used to create a CA certificate and key for SAML federation when + keystone_idp is populated by the deployer. For an existing keystone SAML + setup the certificate and key will be re-created which may be undesirable, + unless the existing ones are first copied to the relevant directories in + ``/etc/openstack_deploy/pki/roots`` on the deploy host. The variables + ``keystone_ssl_self_signed_regen`` and ``keystone_ssl_self_signed_subject`` + are removed and are replaced with equivalent functionality via the new + ``keystone_pki_*`` variables. diff --git a/tasks/keystone_idp_self_signed_create.yml b/tasks/keystone_idp_self_signed_create.yml deleted file mode 100644 index 253b3c74..00000000 --- a/tasks/keystone_idp_self_signed_create.yml +++ /dev/null @@ -1,45 +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 IdP self-signed certificate for regen - file: - dest: "{{ keystone_idp.cerfile }}" - state: "absent" - when: - - keystone_idp.regen_cert | bool - -- name: Create IdP self-signed ssl cert - command: > - openssl req -new -nodes -sha256 -x509 -subj - "{{ keystone_idp.self_signed_cert_subject }}" - -days 3650 - -keyout {{ keystone_idp.keyfile }} - -out {{ keystone_idp.certfile }} - -extensions v3_ca - creates={{ keystone_idp.certfile }} - when: _keystone_is_first_play_host - notify: - - Manage LB - - Restart web server - -- name: Set appropriate file ownership on the IdP self-signed cert - file: - path: "{{ item }}" - owner: "{{ keystone_system_user_name }}" - group: "{{ keystone_system_group_name }}" - mode: "0640" - with_items: - - "{{ keystone_idp.keyfile }}" - - "{{ keystone_idp.certfile }}" diff --git a/tasks/keystone_idp_self_signed_distribute.yml b/tasks/keystone_idp_self_signed_distribute.yml deleted file mode 100644 index 38b18838..00000000 --- a/tasks/keystone_idp_self_signed_distribute.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: Distribute IdP self-signed certificate - openstack.osa.memcached: - name: "{{ item.name }}" - file_path: "{{ item.src }}" - state: "retrieve" - file_mode: "{{ item.file_mode }}" - dir_mode: "{{ item.dir_mode }}" - server: "{{ keystone_memcached_servers }}" - encrypt_string: "{{ memcached_encryption_key }}" - with_items: - - { src: "{{ keystone_idp.certfile }}", name: "keystone_idp_cert", file_mode: "0640", dir_mode: "0750" } - - { src: "{{ keystone_idp.keyfile }}", name: "keystone_idp_key", file_mode: "0640", dir_mode: "0750" } - register: memcache_keys - until: memcache_keys is success - retries: 5 - delay: 2 - notify: - - Manage LB - - Restart web server - -- name: Set appropriate file ownership on the IdP self-signed cert - file: - path: "{{ item }}" - owner: "{{ keystone_system_user_name }}" - group: "{{ keystone_system_group_name }}" - mode: "0640" - with_items: - - "{{ keystone_idp.keyfile }}" - - "{{ keystone_idp.certfile }}" diff --git a/tasks/keystone_idp_self_signed_store.yml b/tasks/keystone_idp_self_signed_store.yml deleted file mode 100644 index 0b236865..00000000 --- a/tasks/keystone_idp_self_signed_store.yml +++ /dev/null @@ -1,29 +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 IdP self-signed certificate - openstack.osa.memcached: - name: "{{ item.name }}" - file_path: "{{ item.src }}" - state: "present" - server: "{{ keystone_memcached_servers }}" - encrypt_string: "{{ memcached_encryption_key }}" - with_items: - - { src: "{{ keystone_idp.certfile }}", name: "keystone_idp_cert" } - - { src: "{{ keystone_idp.keyfile }}", name: "keystone_idp_key" } - register: memcache_keys - until: memcache_keys is success - retries: 5 - delay: 2 diff --git a/tasks/keystone_idp_setup.yml b/tasks/keystone_idp_setup.yml index de7e03a3..3fd1badc 100644 --- a/tasks/keystone_idp_setup.yml +++ b/tasks/keystone_idp_setup.yml @@ -13,15 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -- include_tasks: keystone_idp_self_signed_create.yml - when: _keystone_is_first_play_host - -- include_tasks: keystone_idp_self_signed_store.yml - when: _keystone_is_first_play_host - -- include_tasks: keystone_idp_self_signed_distribute.yml - when: not _keystone_is_first_play_host - - include_tasks: keystone_idp_metadata.yml - include_tasks: keystone_idp_sp_setup.yml diff --git a/tasks/keystone_ssl.yml b/tasks/keystone_ssl.yml deleted file mode 100644 index 3df4128d..00000000 --- a/tasks/keystone_ssl.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -# Copyright 2015, 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: keystone_ssl_self_signed.yml - when: - - keystone_ssl | bool - - keystone_user_ssl_cert is not defined or keystone_user_ssl_key is not defined - -- include_tasks: keystone_ssl_user_provided.yml diff --git a/tasks/keystone_ssl_key_create.yml b/tasks/keystone_ssl_key_create.yml deleted file mode 100644 index 88808d70..00000000 --- a/tasks/keystone_ssl_key_create.yml +++ /dev/null @@ -1,46 +0,0 @@ ---- -# Copyright 2015, 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: "{{ keystone_ssl_cert }}" - state: "absent" - when: keystone_ssl_self_signed_regen | bool - -- name: Create self-signed Apache ssl cert - command: > - openssl req -new -nodes -sha256 -x509 -subj - "{{ keystone_ssl_self_signed_subject }}" - -days 3650 - -keyout {{ keystone_ssl_key }} - -out {{ keystone_ssl_cert }} - -extensions v3_ca - creates={{ keystone_ssl_cert }} - notify: - - Manage LB - - Restart web server - -- name: Ensure keystone user owns the self-signed key and certificate - file: - path: "{{ item }}" - owner: "{{ keystone_system_user_name }}" - group: "{{ keystone_system_group_name }}" - mode: "0640" - with_items: - - "{{ keystone_ssl_key }}" - - "{{ keystone_ssl_cert }}" - notify: - - Manage LB - - Restart web server diff --git a/tasks/keystone_ssl_key_distribute.yml b/tasks/keystone_ssl_key_distribute.yml deleted file mode 100644 index 2ca8f526..00000000 --- a/tasks/keystone_ssl_key_distribute.yml +++ /dev/null @@ -1,48 +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: "{{ keystone_ssl_key }}" - content: "{{ hostvars[groups['keystone_all'][0]]['keystone_ssl_key_fact'] | b64decode }}" - owner: "{{ keystone_system_user_name }}" - group: "{{ keystone_system_group_name }}" - mode: "0640" - notify: - - Manage LB - - Restart web server - -- name: Distribute self signed ssl cert - copy: - dest: "{{ keystone_ssl_cert }}" - content: "{{ hostvars[groups['keystone_all'][0]]['keystone_ssl_cert_fact'] | b64decode }}" - owner: "{{ keystone_system_user_name }}" - group: "{{ keystone_system_group_name }}" - mode: "0640" - notify: - - Manage LB - - Restart web server - -- name: Ensure keystone user owns the self-signed key and certificate - file: - path: "{{ item }}" - owner: "{{ keystone_system_user_name }}" - group: "{{ keystone_system_group_name }}" - with_items: - - "{{ keystone_ssl_key }}" - - "{{ keystone_ssl_cert }}" - notify: - - Manage LB - - Restart web server diff --git a/tasks/keystone_ssl_key_store.yml b/tasks/keystone_ssl_key_store.yml deleted file mode 100644 index ee7f2c8c..00000000 --- a/tasks/keystone_ssl_key_store.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -# Copyright 2015, 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: "{{ keystone_ssl_cert }}" - register: _keystone_ssl_cert - changed_when: false - -- name: Store ssl key - slurp: - src: "{{ keystone_ssl_key }}" - register: _keystone_ssl_key - changed_when: false - -- name: Register a fact for the cert and key - set_fact: - keystone_ssl_cert_fact: "{{ _keystone_ssl_cert.content }}" - keystone_ssl_key_fact: "{{ _keystone_ssl_key.content }}" diff --git a/tasks/keystone_ssl_self_signed.yml b/tasks/keystone_ssl_self_signed.yml deleted file mode 100644 index ebf9a997..00000000 --- a/tasks/keystone_ssl_self_signed.yml +++ /dev/null @@ -1,23 +0,0 @@ ---- -# Copyright 2015, 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: keystone_ssl_key_create.yml - when: _keystone_is_first_play_host - -- include_tasks: keystone_ssl_key_store.yml - when: _keystone_is_first_play_host - -- include_tasks: keystone_ssl_key_distribute.yml - when: not _keystone_is_first_play_host diff --git a/tasks/keystone_ssl_user_provided.yml b/tasks/keystone_ssl_user_provided.yml deleted file mode 100644 index 1435094e..00000000 --- a/tasks/keystone_ssl_user_provided.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- -# Copyright 2015, 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: "{{ keystone_user_ssl_cert }}" - dest: "{{ keystone_ssl_cert }}" - owner: "root" - group: "root" - mode: "0644" - when: keystone_user_ssl_cert is defined - notify: - - Manage LB - - Restart web server - -- name: Drop user provided ssl key - copy: - src: "{{ keystone_user_ssl_key }}" - dest: "{{ keystone_ssl_key }}" - owner: "root" - group: "root" - mode: "0640" - when: keystone_user_ssl_key is defined - notify: - - Manage LB - - Restart web server - -- name: Drop user provided ssl CA cert - copy: - src: "{{ keystone_user_ssl_ca_cert }}" - dest: "{{ keystone_ssl_ca_cert }}" - owner: "root" - group: "root" - mode: "0644" - when: keystone_user_ssl_ca_cert is defined - notify: - - Manage LB - - Restart web server diff --git a/tasks/main.yml b/tasks/main.yml index 141c2f49..c6345167 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -161,7 +161,21 @@ tags: - keystone-config -- import_tasks: keystone_ssl.yml +- name: Create and install SSL certificates + include_role: + name: pki + tasks_from: main_certs.yml + vars: + pki_setup_host: "{{ keystone_pki_setup_host }}" + pki_create_ca: "{{ keystone_pki_create_ca }}" + pki_authorities: "{{ keystone_pki_ca_certificates }}" + pki_regen_ca: "{{ keystone_pki_regen_ca }}" + pki_create_certificates: "{{ keystone_pki_create_certificates }}" + pki_regen_cert: "{{ keystone_pki_regen_cert }}" + pki_certificates: "{{ keystone_pki_certificates }}" + pki_install_certificates: "{{ keystone_pki_install_certificates }}" + when: + - (keystone_ssl | bool) or (keystone_idp['certfile'] is defined) tags: - keystone-config