Use ansible-role-pki to generate SSL certificates

Supports two scenarios:

1) variables defined in defaults/main.yml are sufficient to create
a root/intermediate CA certificate for mariadb when this role
is used outside openstack-ansible.

2) when:

openstack_pki_dir
openstack_pki_setup_host
openstack_pki_authorities
openstack_pki_service_intermediate_cert_name

are defined, an external CA already created on the deploy host
with a previous run of ansible-role-pki will be used as the CA.

Server certificates for the galera instances are created from the
data in galera_pki_certificates in both situations

Depends-On: https://review.opendev.org/c/openstack/ansible-role-pki/+/807771
Change-Id: I72738e4f8bd2233dedbed4428baafd4436de84b5
This commit is contained in:
Dmitriy Rabotyagov 2021-09-07 15:55:20 +03:00
parent 4b66580dad
commit 6bc6929d09
9 changed files with 143 additions and 257 deletions

View File

@ -164,7 +164,62 @@ galera_distro_package_pins:
# Galera Server SSL functionality.
# Storage location for SSL certificate authority
galera_pki_dir: "{{ openstack_pki_dir | default('/etc/pki/galera-ca') }}"
# Create a certificate authority if one does not already exist
galera_pki_create_ca: "{{ openstack_pki_authorities is not defined | bool }}"
galera_pki_regen_ca: ''
galera_pki_authorities:
- name: "MariaDBRoot"
country: "GB"
state_or_province_name: "England"
organization_name: "Example Corporation"
organizational_unit_name: "IT Security"
cn: "MariaDB Root CA"
provider: selfsigned
basic_constraints: "CA:TRUE"
key_usage:
- digitalSignature
- cRLSign
- keyCertSign
not_after: "+3650d"
- name: "MariaDBIntermediate"
country: "GB"
state_or_province_name: "England"
organization_name: "Example Corporation"
organizational_unit_name: "IT Security"
cn: "MariaDB Intermediate CA"
provider: ownca
basic_constraints: "CA:TRUE,pathlen:0"
key_usage:
- digitalSignature
- cRLSign
- keyCertSign
not_after: "+3650d"
signed_by: "MariaDBRoot"
# Installation details for certificate authorities
galera_pki_install_ca:
- name: "MariaDBRoot"
condition: "{{ galera_pki_create_ca }}"
# Galera server certificate
galera_pki_keys_path: "{{ galera_pki_dir ~ '/certs/private/' }}"
galera_pki_certs_path: "{{ galera_pki_dir ~ '/certs/certs/' }}"
galera_pki_intermediate_cert_name: "{{ openstack_pki_service_intermediate_cert_name | default('MariaDBIntermediate') }}"
galera_pki_intermediate_cert_path: "{{ galera_pki_dir ~ '/roots/' ~ galera_pki_intermediate_cert_name ~ '/certs/' ~ galera_pki_intermediate_cert_name ~ '.crt' }}"
galera_pki_regen_cert: ''
galera_pki_certificates:
- name: "galera_{{ ansible_facts['hostname'] }}"
provider: ownca
cn: "{{ ansible_facts['hostname'] }}"
san: "{{ 'DNS:' ~ ansible_facts['hostname'] ~ ',IP:' ~ galera_address }}"
signed_by: "{{ galera_pki_intermediate_cert_name }}"
galera_use_ssl: false
galera_ssl_verify: true
galera_ssl_cert: /etc/ssl/certs/galera.pem
galera_ssl_key: /etc/mysql/ssl/galera.key
galera_ssl_ca_cert: /etc/ssl/certs/galera-ca.pem
@ -174,17 +229,29 @@ galera_ssl_ca_cert: /etc/ssl/certs/galera-ca.pem
# galera_user_ssl_key: /etc/openstack_deploy/self_signed_certs/galera.key
# galera_user_ssl_ca_cert: /etc/openstack_deploy/self_signed_certs/galera-ca.pem
## Set galera_ssl_self_signed_regen to true if you want to generate a new
# SSL certificate for Galera when this playbook runs. You can also change
# the subject of the self-signed certificate here if you prefer.
galera_ssl_self_signed_regen: false
galera_ssl_self_signed_subject: "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ galera_address }}"
galera_ssl_ca_self_signed_subject: "/C=US/ST=Texas/L=San Antonio/O=IT"
# This option is used for creating the CA and overriding the Galera address on the clients side.
# Should be set to either public VIP of VIP FQDN, depending on what is currently used in the env.
galera_address: "{{ ansible_host }}"
# Installation details for SSL certificates
galera_pki_install_certificates:
- src: "{{ galera_user_ssl_cert | default(galera_pki_certs_path ~ 'galera_' ~ ansible_facts['hostname'] ~ '-chain.crt') }}"
dest: "{{ galera_ssl_cert }}"
owner: "root"
group: "root"
mode: "0644"
- src: "{{ galera_user_ssl_key | default(galera_pki_keys_path ~ 'galera_' ~ ansible_facts['hostname'] ~ '.key.pem') }}"
dest: "{{ galera_ssl_key }}"
owner: "mysql"
group: "root"
mode: "0600"
- src: "{{ galera_user_ssl_ca_cert | default(galera_pki_intermediate_cert_path) }}"
dest: "{{ galera_ssl_ca_cert }}"
owner: "root"
group: "root"
mode: "0644"
# MariaDB 10.1+ ships with 'PrivateDevices=True' in the systemd unit file. This
# provides some additional security, but it causes problems with systemd 219.
# While the security enhancements are helpful on bare metal hosts with multiple
@ -206,10 +273,8 @@ galera_client_package_state: "latest"
galera_client_drop_config_file: "true"
galera_client_my_cnf_overrides: {}
# This server is used when pulling an ssl cert onto a given host when a user
# defined key is not present. By default this will try and pull from the
# "galera_server" group and fall back to localhost.
galera_ssl_server: "{{ (galera_cluster_members | default(['localhost']))[0] }}"
# Delegated host for operating the certificate authority
galera_ssl_server: "{{ openstack_pki_setup_host | default('localhost') }}"
## Database info
galera_db_setup_host: "{{ openstack_db_setup_host | default(galera_cluster_members[0] | default('localhost')) }}"

View File

@ -25,7 +25,9 @@
failed_when: false
changed_when: true
register: node_status
listen: Restart all mysql
listen:
- Restart all mysql
- cert installed
notify:
- Bootstrap cluster
- Restart mysql (All)

View File

@ -0,0 +1,34 @@
---
features:
- |
Galera role now leverages PKI role for creation and distribution of the
certificates and certificate authorities.
This introduces bunch of new variables which controls CA and certificates
generation details.
If user SSL certificates are provided - they would be used instead of
the generated ones.
The following new variables were introduced:
- galera_ssl_verify
- galera_pki_dir
- galera_pki_create_ca
- galera_pki_regen_ca
- galera_pki_certificates
- galera_pki_regen_cert
- galera_pki_authorities
- galera_pki_install_ca
- galera_pki_keys_path
- galera_pki_certs_path
- galera_pki_intermediate_cert_name
- galera_pki_intermediate_cert_path
- galera_pki_install_certificates
deprecations:
- |
Following variables were removed in favor of PKI ones
and have no effect anymore:
- galera_ssl_self_signed_regen
- galera_ssl_self_signed_subject
- galera_ssl_ca_self_signed_subject

View File

@ -23,6 +23,13 @@
- include_tasks: galera_client_post_install.yml
- include_tasks: galera_client_ssl.yml
when:
- name: Create and install SSL certificates
include_role:
name: pki
tasks_from: "main_certs.yml"
vars:
pki_setup_host: "{{ galera_ssl_server }}"
pki_dir: "{{ galera_pki_dir }}"
pki_install_ca: "{{ galera_pki_install_ca }}"
when:
- galera_use_ssl | bool

View File

@ -1,53 +0,0 @@
---
# Copyright 2017, 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: Get Galera ssl CA cert contents
slurp:
src: "{{ galera_ssl_ca_cert }}"
register: galera_ca
failed_when: false
delegate_to: "{{ galera_ssl_server }}"
when:
- galera_user_ssl_ca_cert is not defined
- name: Check for Galera ssl CA cert get failure
debug:
msg: >
The cert retrieval task failed or no CA cert was found. Check the file
"{{ galera_ssl_ca_cert }}" on server "{{ galera_ssl_server }}" before
trying again.
when:
- galera_ca.content is not defined
- name: Distribute Galera ssl CA cert (SERVER)
copy:
content: "{{ galera_ca.content | b64decode }}"
dest: "{{ galera_ssl_ca_cert }}"
owner: "root"
group: "root"
mode: "0644"
when:
- galera_user_ssl_ca_cert is not defined
- galera_ca.content is defined
- name: Distribute Galera ssl CA cert (USER)
copy:
src: "{{ galera_user_ssl_ca_cert }}"
dest: "{{ galera_ssl_ca_cert }}"
owner: "root"
group: "root"
mode: "0644"
when:
- galera_user_ssl_ca_cert is defined

View File

@ -76,7 +76,21 @@
- { path: "/var/lib/mysql", owner: "mysql", mode: "02755" }
- { path: "/etc/mysql/conf.d" }
- include_tasks: galera_server_ssl.yml
- name: Create and install SSL certificates
include_role:
name: pki
tasks_from: "{{ galera_pki_create_ca | ternary('main.yml', 'main_certs.yml') }}"
vars:
pki_setup_host: "{{ galera_ssl_server }}"
pki_dir: "{{ galera_pki_dir }}"
pki_create_ca: "{{ galera_pki_create_ca }}"
pki_regen_ca: "{{ galera_pki_regen_ca }}"
pki_authorities: "{{ galera_pki_authorities }}"
pki_install_ca: "{{ galera_pki_install_ca }}"
pki_create_certificates: "{{ galera_user_ssl_cert is not defined and galera_user_ssl_key is not defined }}"
pki_regen_cert: "{{ galera_pki_regen_cert }}"
pki_certificates: "{{ galera_pki_certificates }}"
pki_install_certificates: "{{ galera_pki_install_certificates }}"
when:
- galera_use_ssl | bool

View File

@ -1,50 +0,0 @@
---
# Copyright 2015, Rackspace US, Inc., Mirantis 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: Create ssl directory
file:
path: "/etc/mysql/ssl"
state: "directory"
owner: "mysql"
group: "mysql"
mode: "0755"
- include_tasks: galera_server_ssl_self_signed.yml
when:
- not galera_user_ssl_cert is defined
- not galera_user_ssl_key is defined
- not galera_user_ssl_ca_cert is defined
- name: Copy CA cert and key (USER)
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "mysql"
group: "mysql"
mode: "{{ item.mode | default('0640') }}"
with_items:
- src: "{{ galera_user_ssl_ca_cert }}"
dest: "{{ galera_ssl_ca_cert }}"
mode: "0644"
- src: "{{ galera_user_ssl_cert }}"
dest: "{{ galera_ssl_cert }}"
- src: "{{ galera_user_ssl_key }}"
dest: "{{ galera_ssl_key }}"
mode: "0600"
when:
- galera_user_ssl_cert is defined
- galera_user_ssl_key is defined
- galera_user_ssl_ca_cert is defined
notify: Restart all mysql

View File

@ -1,139 +0,0 @@
---
# Copyright 2015, Rackspace US, Inc., Mirantis 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: "{{ item }}"
state: "absent"
with_items:
- "{{ galera_ssl_ca_cert }}"
- "{{ galera_ssl_cert }}"
- "{{ galera_ssl_key }}"
- "{{ galera_ssl_ca_cert | dirname }}/galera-csr.pem"
when:
- galera_ssl_self_signed_regen | bool
- inventory_hostname == galera_server_bootstrap_node
- name: Create Galera CA cert
command: >
openssl req -new -nodes -x509 -subj
"{{ galera_ssl_ca_self_signed_subject }}"
-days 3650
-keyout {{ galera_ssl_key | dirname }}/galera-ca.key
-out {{ galera_ssl_ca_cert }}
creates={{ galera_ssl_ca_cert }}
when:
- inventory_hostname == galera_server_bootstrap_node
notify: Restart all mysql
- name: Get CA cert contents and store as var
slurp:
src: "{{ galera_ssl_ca_cert }}"
register: galera_ca
changed_when: false
when:
- inventory_hostname == galera_server_bootstrap_node
- name: Register a fact for the CA cert
set_fact:
galera_server_ca_cert: "{{ galera_ca.content }}"
when:
- inventory_hostname == galera_server_bootstrap_node
- name: Create Galera SSL CSR
command: >
openssl req -new -nodes -sha256 -subj
"{{ galera_ssl_self_signed_subject }}"
-days 3650
-keyout {{ galera_ssl_key }}
-out {{ galera_ssl_ca_cert | dirname }}/galera-csr.pem
-extensions v3_ca
creates={{ galera_ssl_ca_cert | dirname }}/galera-csr.pem
register: create_galera_ssl_request
when:
- inventory_hostname == galera_server_bootstrap_node
notify: Restart all mysql
- name: Convert generated SSL key to valid format for Galera
command: >
openssl rsa
-in {{ galera_ssl_key }}
-out {{ galera_ssl_key }}
when:
- create_galera_ssl_request is changed
- inventory_hostname == galera_server_bootstrap_node
notify: Restart all mysql
- name: Get CSR private key contents and store as var
slurp:
src: "{{ galera_ssl_key }}"
register: galera_private_key
changed_when: false
when:
- inventory_hostname == galera_server_bootstrap_node
- name: Register a fact for the CSR private key
set_fact:
galera_server_private_key: "{{ galera_private_key.content }}"
when:
- inventory_hostname == galera_server_bootstrap_node
- name: Create Galera SSL signed cert
command: >
openssl x509 -req
-days 3650
-in {{ galera_ssl_ca_cert | dirname }}/galera-csr.pem
-CA {{ galera_ssl_ca_cert }}
-CAkey {{ galera_ssl_key | dirname }}/galera-ca.key
-out {{ galera_ssl_cert }}
-set_serial 01
creates={{ galera_ssl_cert }}
when:
- inventory_hostname == galera_server_bootstrap_node
notify: Restart all mysql
- name: Get signed cert contents and store as var
slurp:
src: "{{ galera_ssl_cert }}"
register: galera_cert
changed_when: false
when:
- inventory_hostname == galera_server_bootstrap_node
- name: Register a fact for the signed cert contents
set_fact:
galera_server_cert: "{{ galera_cert.content }}"
when:
- inventory_hostname == galera_server_bootstrap_node
- name: Copy CA cert, private key, and signed cert (SELF)
copy:
content: "{{ hostvars[galera_server_bootstrap_node][item.key] | b64decode }}"
dest: "{{ item.dest }}"
owner: "mysql"
group: "mysql"
mode: "{{ item.mode | default('0640') }}"
with_items:
- key: "galera_server_ca_cert"
dest: "{{ galera_ssl_ca_cert }}"
mode: "0644"
- key: "galera_server_private_key"
dest: "{{ galera_ssl_key }}"
- key: "galera_server_cert"
dest: "{{ galera_ssl_cert }}"
mode: "0600"
when:
- inventory_hostname != galera_server_bootstrap_node
notify: Restart all mysql

View File

@ -8,3 +8,9 @@ localhost
{% endif %}
user={{ galera_root_user }}
password={{ galera_root_password }}
{% if galera_use_ssl %}
ssl
{% if galera_ssl_verify %}
ssl-verify-server-cert
{% endif %}
{% endif %}