openstack-ansible-os_octavia/tasks/octavia_certs.yml
Jesse Pretorius 6c73550005 Make certificate generation host configurable
We do not necessarily always want to use the deployment
host for certificate generation. This patch allows the
deployer to set an alternative host to delegate these
tasks to in the same pattern as has been done for the
service registration tasks.

Additionally, due to the way this is done we can also:

1. Remove the task to install pyOpenSSL, because it is
   already in the Ansible runtime venv for both role
   tests and the integrated build. We have set the
   python interpreter correctly to ensure that we have
   access to it.

2. Consolidate the 'install' and 'config' tasks into
   a single task file. Given that most of the 'install'
   tasks were doing runtime configuration, it seems best
   to rather move them into a single file and use the
   'config' tag.

Change-Id: If2f1ab03ccd9400fe05e2948ddfe33c8796dbd97
2018-07-20 11:47:01 +00:00

143 lines
5.6 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
# 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 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: 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