Scan existing controllers on update to pick up existing certs/private keys

Adds an octavia related role to pick up CA (cert and private key pairs)
and client certificate from controllers and modifies existing roles to
use them instead of generating new ones.

Depends-On: https://review.opendev.org/746911

Change-Id: I5c18a59bf11e3915ef5f88c1eb2af1b4713af35b
Co-Authored-By: Gregory Thiemonge <gthiemon@redhat.com>
Related-Bug: #1849548
Related-Bug: #1849550
(cherry picked from commit d3e7a42cdad6a12d63afd23906cffe081f036745)
(cherry picked from commit 2e5be7b96859d1eff7c2680c6780e3ac27c6dd63)
Note-Queens: cherry picked from tripleo-ansible stein
(cherry picked from commit b94fb8e9d85939e4942bc0d77222e2118552de71)
This commit is contained in:
Brent Eagles 2020-08-17 14:02:04 +02:00 committed by Gregory Thiemonge
parent a645db87aa
commit 6b14e3f6d3
7 changed files with 232 additions and 4 deletions

View File

@ -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 }}"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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: