openstack-ansible-os_octavia/tasks/octavia_certs.yml
Vadim Kuznetsov 833b58da2c Octavia certificate distribution
Current copy certificates task works only if octavia_cert_setup_host is
localhost, because it copies from local path. See bug 1842117

To fix this issue certs are slurped and registered after they are
created.
If octavia_cert_setup_host is 'localhost' cert variables are
registered to task_vars scope.
If octavia_cert_setup_host is one of the octavia containers or utility
containers, i.e. setup host exists in inventory cert variables are
registered to hostvars[octavia_cert_setup_host] i.e hostvars scope.
Certs facts are set according to octavia_cert_setup_host value.
Certs distribution play copies certs from certs facts to each octavia
conatainer.

Change-Id: I0906c7cf80c3345fb993a71fe190fa2f6baa55e4
Closes-Bug: 1842117
2019-09-20 16:55:48 +03:00

174 lines
6.4 KiB
YAML

---
# Copyright 2018, 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.
# We set the python interpreter to the ansible runtime venv if
# the delegation is to localhost so that we get access to the
# appropriate python libraries in that venv. If the delegation
# is to another host, we assume that it is accessible by the
# system python instead.
- name: Prepare octavia_cert_setup_host for certificate generation
delegate_to: "{{ octavia_cert_setup_host }}"
vars:
ansible_python_interpreter: >-
{{ (octavia_cert_setup_host == 'localhost') | ternary(ansible_playbook_python, ansible_python['executable']) }}
block:
- name: Create certificate directories
file:
path: "{{ item.path }}"
state: directory
mode: "{{ item.mode }}"
owner: "{{ octavia_cert_dir_owner }}"
with_items:
- { path: "{{ octavia_cert_dir }}", mode: '0750' }
- { path: "{{ octavia_cert_dir }}/newcerts", mode: '0750'}
- { path: "{{ octavia_cert_dir }}/private", mode: '0750'}
# ansible's openssl_certificate can't create X509 extensions
# but you need CA: true in Basic Constraints to have a CA cert
# set up openssl for use
- name: Touch index.txt
file:
path: "{{ octavia_cert_dir }}/index.txt"
state: touch
mode: 0755
- name: Init serial
copy:
content: "01"
dest: "{{ octavia_cert_dir }}/serial"
force: no
- name: Generate openssl.conf
template:
src: "templates/openssl.conf.j2"
dest: "{{ octavia_cert_dir }}/openssl.cnf"
mode: 0440
- name: Create the server CA private key
openssl_privatekey:
path: "{{ octavia_ca_private_key }}"
passphrase: "{{ octavia_ca_private_key_passphrase }}"
cipher: "{{ octavia_cert_cipher_server }}"
size: "{{ octavia_cert_key_length_server }}"
- name: Create server CA certificate
command: >
openssl req -x509 -passin pass:'{{ octavia_ca_private_key_passphrase }}' -new -nodes -key {{ octavia_ca_private_key }} \
-config {{ octavia_cert_dir }}/openssl.cnf \
-subj "{{ octavia_cert_server_ca_subject }}" \
-days {{ octavia_cert_validity_days }} \
-out {{ octavia_ca_certificate }}
args:
chdir: "{{ octavia_cert_dir }}"
creates: "{{ octavia_ca_certificate }}"
- name: Store octavia ca private key
slurp:
src: "{{ octavia_ca_private_key }}"
register: _octavia_ca_private_key
changed_when: false
- name: Store octavia ca cert
slurp:
src: "{{ octavia_ca_certificate }}"
register: _octavia_ca_certificate
changed_when: false
# same as octavia ca cert
- name: Store octavia server ca
slurp:
src: "{{ octavia_server_ca }}"
register: _octavia_server_ca
changed_when: false
# These are run at the very first installation of Octavia
# While Octavia acts as a CA for the server certificates,
# for the amphora it only needs a client certificate and
# the (public) certificate authority certificate.
# Generating the secret key here and storing it
# on the deploy host allows us to rotate the client
# certificate without recycling the amphora since
# we can keep the same CA.
- name: Generate keys/certificates on octavia_cert_setup_host
delegate_to: "{{ octavia_cert_setup_host }}"
vars:
ansible_python_interpreter: >-
{{ (octavia_cert_setup_host == 'localhost') | ternary(ansible_playbook_python, ansible_python['executable']) }}
when: octavia_generate_client_cert | bool
block:
- name: Create the client CAs private key
openssl_privatekey:
path: "{{ octavia_client_ca_key }}"
passphrase: "{{ octavia_cert_client_password }}"
cipher: "{{ octavia_cert_cipher_client }}"
size: "{{ octavia_cert_key_length_client }}"
- name: Create client CA certificate
command: >
openssl req -x509 -passin pass:'{{ octavia_cert_client_password }}' -new -nodes -key {{ octavia_client_ca_key }} \
-config {{ octavia_cert_dir }}/openssl.cnf \
-subj "{{ octavia_cert_client_ca_subject }}" \
-days {{ octavia_cert_validity_days }} \
-out {{ octavia_client_ca }}
args:
chdir: "{{ octavia_cert_dir }}"
creates: "{{ octavia_client_ca }}"
- name: Create the client cert private key
openssl_privatekey:
path: "{{ octavia_cert_dir }}/client.key"
size: "{{ octavia_cert_key_length_client }}"
- name: Create client cert CSR
openssl_csr:
path: "{{ octavia_cert_dir }}/client.csr"
common_name: "{{ octavia_cert_client_req_common_name }}"
country_name: "{{ octavia_cert_client_req_country_name }}"
state_or_province_name: "{{ octavia_cert_client_req_state_or_province_name }}"
locality_name: "{{ octavia_cert_client_req_locality_name }}"
organization_name: "{{ octavia_cert_client_req_organization_name }}"
privatekey_path: "{{ octavia_cert_dir }}/client.key"
- name: Create client certificate
command: >
openssl ca -passin pass:'{{ octavia_ca_private_key_passphrase }}' -config {{ octavia_cert_dir }}/openssl.cnf \
-in client.csr -days {{ octavia_cert_validity_days }} -out client-.pem -batch
args:
chdir: "{{ octavia_cert_dir }}"
creates: "{{ octavia_cert_dir }}/client-.pem"
# use cat to avoid mangling the certs
- name: Generate single pem client.pem
shell: "cat client-.pem client.key >{{ octavia_client_cert }}"
args:
chdir: "{{ octavia_cert_dir }}"
creates: "{{ octavia_client_cert }}"
tags:
- skip_ansible_lint
- name: Store octavia client ca
slurp:
src: "{{ octavia_client_ca }}"
register: _octavia_client_ca
changed_when: false
- name: Store octavia client cert
slurp:
src: "{{ octavia_client_cert }}"
register: _octavia_client_cert
changed_when: false