![Dmitriy Rabotyagov](/assets/img/avatar_default.png)
With multinode Octavia setup self and octavia_generate_certs is True, role fails with distributing certificates. While correct approach would be to replace that with PKI role, right now we just patching current approach, by ensuring that facts are set for octavia_cert_setup_host so we could reliable gain them. Change-Id: I0dc2488b9e8e33847c9a2646032ac5f926d09133 Closes-Bug: #1936646
187 lines
7.0 KiB
YAML
187 lines
7.0 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 }}"
|
|
delegate_facts: true
|
|
vars:
|
|
ansible_python_interpreter: >-
|
|
{{ (octavia_cert_setup_host == 'localhost') | ternary(ansible_playbook_python, ansible_facts['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
|
|
|
|
- name: Register a fact for the CA cert and key
|
|
set_fact:
|
|
octavia_ca_private_key_fact: "{{ _octavia_ca_private_key['content'] | b64decode }}"
|
|
octavia_ca_certificate_fact: "{{ _octavia_ca_certificate['content'] | b64decode }}"
|
|
octavia_server_ca_fact: "{{ _octavia_server_ca['content'] | b64decode }}"
|
|
|
|
# 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 }}"
|
|
delegate_facts: true
|
|
vars:
|
|
ansible_python_interpreter: >-
|
|
{{ (octavia_cert_setup_host == 'localhost') | ternary(ansible_playbook_python, ansible_facts['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
|
|
|
|
- name: Register a fact for the cert and key
|
|
set_fact:
|
|
octavia_client_ca_fact: "{{ _octavia_client_ca['content'] | b64decode }}"
|
|
octavia_client_cert_fact: "{{ _octavia_client_cert['content'] | b64decode }}"
|