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