diff --git a/playbooks/octavia-files.yaml b/playbooks/octavia-files.yaml index 77be16d77..4b2a71009 100644 --- a/playbooks/octavia-files.yaml +++ b/playbooks/octavia-files.yaml @@ -26,6 +26,22 @@ roles: - octavia-undercloud +- hosts: octavia_nodes + gather_facts: true + vars: + generate_certs: "{{ generate_certs }}" + octavia_confd_prefix: "/var/lib/config-data/puppet-generated/octavia" + ca_cert_path: "{{ ca_cert_path }}" + ca_private_key_path: "{{ ca_private_key_path }}" + client_cert_path: "{{ client_cert_path }}" + stack_action: "{{ stack_action }}" + tasks: + - include_role: + name: octavia-controller-check + when: + - generate_certs | bool + - stack_action == 'UPDATE' + - hosts: octavia_nodes[0] gather_facts: True vars: @@ -64,6 +80,7 @@ private_key_content: "{{ hostvars[groups['octavia_nodes'][0]]['private_key_content'] | default('') }}" ca_cert_content: "{{ hostvars[groups['octavia_nodes'][0]]['ca_cert_content'] | default('') }}" service_pem_content: "{{ hostvars[groups['octavia_nodes'][0]]['service_pem_content'] | default('') }}" + update_certs: "{{ hostvars[groups['octavia_nodes'][0]]['update_certs'] | default(true) }}" generate_certs: "{{ generate_certs }}" ca_cert_path: "{{ ca_cert_path }}" ca_private_key_path: "{{ ca_private_key_path }}" diff --git a/playbooks/roles/octavia-controller-check/meta/main.yml b/playbooks/roles/octavia-controller-check/meta/main.yml new file mode 100644 index 000000000..6cece9bfd --- /dev/null +++ b/playbooks/roles/octavia-controller-check/meta/main.yml @@ -0,0 +1,43 @@ +--- +# Copyright 2019 Red Hat, Inc. +# All Rights Reserved. +# +# 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. + + +galaxy_info: + author: OpenStack + description: TripleO OpenStack Role -- octavia_controller_check + company: Red Hat + license: Apache-2.0 + min_ansible_version: 2.7 + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + platforms: + - name: CentOS + versions: + - 7 + - 8 + + galaxy_tags: + - tripleo + + +# List your role dependencies here, one per line. Be sure to remove the '[]' above, +# if you add dependencies to this list. +dependencies: + - common diff --git a/playbooks/roles/octavia-controller-check/tasks/main.yml b/playbooks/roles/octavia-controller-check/tasks/main.yml new file mode 100644 index 000000000..c86e29421 --- /dev/null +++ b/playbooks/roles/octavia-controller-check/tasks/main.yml @@ -0,0 +1,74 @@ +--- +# Copyright 2020 Red Hat, Inc. +# All Rights Reserved. +# +# 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: Check if octavia CA file exists on host + become: true + stat: + path: "{{ octavia_confd_prefix }}/{{ ca_cert_path }}" + register: ca_file_stat + +- name: Get and store CA data + block: + - name: Get CA file if exists + become: true + slurp: + src: "{{ octavia_confd_prefix }}/{{ ca_cert_path }}" + register: ca_file_data + - name: Store CA data + set_fact: + ca_cert: "{{ ca_file_data.content | b64decode }}" + when: + - ca_file_stat.stat.exists | bool + +- name: Check if octavia CA private key exists on host + become: true + stat: + path: "{{ octavia_confd_prefix }}/{{ ca_private_key_path }}" + register: ca_key_file_stat + +- name: Get and store CA private key + block: + - name: Get CA private key file if exists + become: true + slurp: + src: "{{ octavia_confd_prefix }}/{{ ca_private_key_path }}" + register: key_file_data + - name: Store CA data + set_fact: + ca_private_key: "{{ key_file_data.content | b64decode }}" + when: + - ca_key_file_stat.stat.exists | bool + +- name: Check if octavia client certificate exists on host + become: true + stat: + path: "{{ octavia_confd_prefix }}/{{ client_cert_path }}" + register: client_cert_file_stat + +# TODO(gthiemon) Remove those tasks when we support per-controller and +# per-process client certificates for Octavia. +- name: Get and store client certificate + block: + - name: Get client certificate file if exists + become: true + slurp: + src: "{{ octavia_confd_prefix }}/{{ client_cert_path }}" + register: client_file_data + - name: Store client certificate data + set_fact: + service_pem_content: "{{ client_file_data.content | b64decode }}" + when: + - client_cert_file_stat.stat.exists | bool diff --git a/playbooks/roles/octavia-controller-config/tasks/main.yml b/playbooks/roles/octavia-controller-config/tasks/main.yml index 93fa8cd97..ad57e91cf 100644 --- a/playbooks/roles/octavia-controller-config/tasks/main.yml +++ b/playbooks/roles/octavia-controller-config/tasks/main.yml @@ -1,4 +1,19 @@ --- +# Copyright 2020 Red Hat, Inc. +# All Rights Reserved. +# +# 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: gathering controller host name command: "hostname -f" register: hostname @@ -7,9 +22,8 @@ node_hostname: "{{ hostname.stdout }}" - include_tasks: certificate.yml when: - - private_key_content|length > 0 - - ca_cert_content|length > 0 - - service_pem_content|length > 0 + - generate_certs | bool + - update_certs | bool - include_tasks: netport.yml - include_tasks: netinterface.yml - name: making sure octavia common configuration directory exists diff --git a/playbooks/roles/octavia-overcloud-config/tasks/check_existing_certs.yml b/playbooks/roles/octavia-overcloud-config/tasks/check_existing_certs.yml new file mode 100644 index 000000000..93d3bfefc --- /dev/null +++ b/playbooks/roles/octavia-overcloud-config/tasks/check_existing_certs.yml @@ -0,0 +1,69 @@ +--- +# Copyright 2020 Red Hat, Inc. +# All Rights Reserved. +# +# 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. + +# TODO(gthiemon) remove service_pem when we support per-controller/per-process +# client certificates. +- name: gather all of the CAs + set_fact: + ca_certs: "{{ groups['octavia_nodes'] | map('extract', hostvars, 'ca_cert') | select('defined') | list }}" + private_keys: "{{ groups['octavia_nodes'] | map('extract', hostvars, 'ca_private_key') | select('defined') | list }}" + service_pems: "{{ groups['octavia_nodes'] | map('extract', hostvars, 'service_pem_content') | select('defined') | list }}" + generate_ca: true + update_certs: true + +- name: grab first values as long as they are unique + block: + - name: count unique CAs and keys + set_fact: + unique_ca_count: "{{ ca_certs | unique | length }}" + unique_pkey_count: "{{ private_keys | unique | length }}" + octavia_node_count: "{{ groups['octavia_nodes'] | list | length }}" + + - name: fail if CA or private key do not match in all Octavia nodes + fail: + msg: | + Inconsistent Octavia configuration detected: + Existing CAs and/or private keys do not match between all Octavia + nodes. To avoid further harm, the deployment will exit with error + now. + when: + - (unique_ca_count | int) > 1 or (unique_pkey_count | int) > 1 + + - name: fail if the number of CA and private key doesn't match + fail: + msg: | + Inconsistent Octavia configuration detected: + Mismatched count for CAs and private keys on controllers. + when: + - (unique_ca_count | int) != (unique_pkey_count | int) + + - name: record cert so others can use it + set_fact: + ca_cert_content: "{{ ca_certs | first }}" + private_key_content: "{{ private_keys | first }}" + service_pem_content: "{{ service_pems | first }}" + + - name: disable CA generation + set_fact: + generate_ca: false + + - name: don't update certificates if CA is present on all octavia nodes + set_fact: + update_certs: false + when: + - (octavia_node_count | int) == (ca_certs | length) + when: + - (ca_certs | length) > 0 diff --git a/playbooks/roles/octavia-overcloud-config/tasks/main.yml b/playbooks/roles/octavia-overcloud-config/tasks/main.yml index cafc7c32c..62acf3d14 100644 --- a/playbooks/roles/octavia-overcloud-config/tasks/main.yml +++ b/playbooks/roles/octavia-overcloud-config/tasks/main.yml @@ -2,5 +2,13 @@ # Previously was a stack in the overcloud - include_tasks: network.yml - include_tasks: quotas.yml + + - import_tasks: check_existing_certs.yml + when: + - stack_action == 'UPDATE' + - generate_certs | bool + - include_tasks: certs_gen.yml - when: generate_certs + when: + - generate_certs | bool + - (generate_ca | default(true)) | bool diff --git a/workbooks/octavia_post.yaml b/workbooks/octavia_post.yaml index f13c2864b..d906fac18 100644 --- a/workbooks/octavia_post.yaml +++ b/workbooks/octavia_post.yaml @@ -37,6 +37,7 @@ workflows: - overcloud_project - overcloud_pub_auth_uri - overcloud_int_auth_uri + - stack_action - ansible_extra_env_variables: ANSIBLE_HOST_KEY_CHECKING: 'False' ANSIBLE_SSH_RETRIES: '3' @@ -110,6 +111,7 @@ workflows: auth_username: <% $.auth_username %> auth_password: <% $.auth_password %> auth_project_name: <% $.auth_project_name %> + stack_action: <% $.stack_action %> execution_id: <% execution().id %> on-success: config_octavia @@ -151,6 +153,7 @@ workflows: generate_certs: <% $.generate_certs %> mgmt_port_dev: <% $.mgmt_port_dev %> auth_project_name: <% $.auth_project_name %> + stack_action: <% $.stack_action %> execution_id: <% execution().id %> on-complete: purge_local_temp_dir purge_local_temp_dir: