From c03b9af32525fda1831aef40482f1c005053349c Mon Sep 17 00:00:00 2001 From: Zolfa Date: Fri, 8 May 2020 00:03:01 +0200 Subject: [PATCH] roles/ca_cert: new role! New role to automate generation and issuing of certificate using a `ca_manager` server. Code is more sintentic and concise, and we avoid duplications. --- library/ssh_cert.py | 72 +++++++--- roles/ca_cert/defaults/main.yaml | 15 +++ roles/ca_cert/tasks/main.yaml | 156 ++++++++++++++++++++++ roles/ldap/defaults/main.yaml | 4 +- roles/ldap/tasks/4_setup_tls.yaml | 65 +++------ roles/openvpn/tasks/main.yaml | 51 ++----- roles/ssh_server/tasks/main.yaml | 106 ++++----------- roles/ssh_server/templates/user_ca.pub.j2 | 4 - tasks/ca-dialog.yaml | 11 +- tasks/ca-signing-request.yaml | 42 ------ 10 files changed, 283 insertions(+), 243 deletions(-) create mode 100644 roles/ca_cert/defaults/main.yaml create mode 100644 roles/ca_cert/tasks/main.yaml delete mode 100644 roles/ssh_server/templates/user_ca.pub.j2 delete mode 100644 tasks/ca-signing-request.yaml diff --git a/library/ssh_cert.py b/library/ssh_cert.py index 06807ac..b93ef49 100644 --- a/library/ssh_cert.py +++ b/library/ssh_cert.py @@ -4,7 +4,7 @@ from datetime import datetime import string import subprocess -from ansible.module_utils.basic import * +from ansible.module_utils.basic import AnsibleModule __doc__ = ''' module: ssh_cert @@ -29,20 +29,30 @@ def signin_ca(lines): # has changed, this should work for all versions: return l.split()[3] - +def principals(lines): + principals = [] + reading = False + for l in lines: + if l.startswith('Critical Options:'): + reading = False + if reading: + principals.append(l) + if l == 'Principals:': + reading = True + return principals def still_valid(cert_timestamps): - t = datetime.datetime.today() + t = datetime.today() return t < cert_timestamps['valid']['to'] and t > cert_timestamps['valid']['from'] def expired(cert_timestamps): - t = datetime.datetime.today() + t = datetime.today() return t > cert_timestamps['valid']['to'] def not_valid(cert_timestamps): - t = datetime.datetime.today() + t = datetime.today() return t < cert_timestamps['valid']['from'] @@ -55,27 +65,43 @@ def cert_type(lines): def valid_from(lines): for l in lines: if l.startswith('Valid'): - return datetime.datetime.strptime(l.split()[2], CERT_TIME_FORMAT) + return datetime.strptime(l.split()[2], CERT_TIME_FORMAT) def valid_to(lines): for l in lines: if l.startswith('Valid'): - return datetime.datetime.strptime(l.split()[4], CERT_TIME_FORMAT) + return datetime.strptime(l.split()[4], CERT_TIME_FORMAT) def main(): module = AnsibleModule( - argument_spec=dict(), - supports_check_mode=False, - ) + argument_spec=dict( + principals=dict( + required=True, + type='list', + ), + path=dict( + required=False, + type='str', + default='/etc/ssh/ssh_host_ed25519_key-cert.pub', + ), + ca_path=dict( + required=False, + type='str', + default='/etc/ssh/user_ca.pub', + ), + ), + supports_check_mode=False, + ) result = {} result['rc'] = 0 + result['msg'] = '' result['failed'] = False result['ca'] = {} - result['ca']['path'] = '/etc/ssh/user_ca.pub' + result['ca']['path'] = module.params.get('ca_path') result['certificate'] = {} - result['certificate']['path'] = '/etc/ssh/ssh_host_ed25519_key-cert.pub' + result['certificate']['path'] = module.params.get('path') ca_output = subprocess.check_output([ 'ssh-keygen', @@ -97,27 +123,37 @@ def main(): cert_lines = [line.strip() for line in cert_output.decode().split('\n')] result['certificate']['signin_ca'] = signin_ca(cert_lines) + result['certificate']['principals'] = principals(cert_lines) result['certificate']['valid'] = { 'from': valid_from(cert_lines), 'to': valid_to(cert_lines), + 'remaining_days': (valid_to(cert_lines)-datetime.now()).days } if not still_valid(result['certificate']): result['failed'] = True - result['msg'] = 'The certificate is not valid now' + result['msg'] += 'The certificate is not valid now. ' if not_valid(result['certificate']): - result['rc'] = 2 + result['rc'] += 2 if expired(result['certificate']): - result['rc'] = 3 + result['rc'] += 4 result['certificate']['serial'] = serial(cert_lines) result['certificate']['type'] = cert_type(cert_lines) if not result['certificate']['signin_ca'] == result['ca']['fingerprint']: result['failed'] = True - result['msg'] = 'The provided CA did not sign the certificate specified' - result['rc'] = 1 - + result['msg'] = 'The provided CA did not sign the certificate specified. ' + result['rc'] += 1 + + principal_mismatch = False + for principal in module.params.get('principals'): + if not principal in result['certificate']['principals']: + principal_mismatch = True + result['msg'] += 'Principal {} not found in cert. '.format(principal) + if principal_mismatch: + result['failed'] = True + result['rc'] += 8 module.exit_json(**result) diff --git a/roles/ca_cert/defaults/main.yaml b/roles/ca_cert/defaults/main.yaml new file mode 100644 index 0000000..e3b2f2d --- /dev/null +++ b/roles/ca_cert/defaults/main.yaml @@ -0,0 +1,15 @@ +--- +ca_cert_ca_manager_host: 'authorities_request' +ca_cert_common_name: '{{ host_fqdn }}' +ca_cert_proto: 'tls' +ca_cert_client: false +ca_cert_min_days_validity: 30 +ca_cert_renew_private_key: true +ca_cert_tls_subj: '{{ openssl_x509_prefix}}/OU=Server/CN={{ ca_cert_common_name }}' +ca_cert_tls_ca_path: '/etc/ssl/root_ca.crt' +ca_cert_tls_key_path: '/etc/ssl/{{ ca_cert_common_name }}.key' +ca_cert_tls_csr_path: '/etc/ssl/{{ ca_cert_common_name }}.csr' +ca_cert_tls_cert_path: '/etc/ssl/{{ ca_cert_common_name }}.crt' +ca_cert_ssh_ca_path: '/etc/ssh/user_ca.pub' +ca_cert_ssh_key_path: '/etc/ssh/ssh_host_ed25519_key' +... diff --git a/roles/ca_cert/tasks/main.yaml b/roles/ca_cert/tasks/main.yaml new file mode 100644 index 0000000..3060e89 --- /dev/null +++ b/roles/ca_cert/tasks/main.yaml @@ -0,0 +1,156 @@ +--- +- name: 'TLS | verify if cert is valid' + command: > + openssl verify + -CAfile {{ ca_cert_tls_ca_path }} + -verify_hostname {{ ca_cert_common_name }} + {{ ca_cert_tls_cert_path }} + register: ca_cert_tls_cert_is_valid + check_mode: false + changed_when: ca_cert_tls_cert_is_valid.rc != 0 + failed_when: false + when: ca_cert_proto == 'tls' + +- name: 'SSH | verify if cert is valid and get info' + ssh_cert: + path: '{{ ca_cert_ssh_key_path }}-cert.pub' + ca_path: '{{ ca_cert_ssh_ca_path }}' + principals: [ '{{ ca_cert_common_name }}' ] + register: ca_cert_ssh_cert_is_valid + changed_when: ca_cert_ssh_cert_is_valid.rc != 0 + ignore_errors: true + check_mode: false + when: ca_cert_proto == 'ssh' + +- name: 'TLS | get remaining validity' + shell: > + {% if ansible_distribution != 'OpenWrt' %} + echo $(( ($(date -d "$(openssl x509 -in {{ ca_cert_tls_cert_path }} -enddate -noout | sed "s/.*=\(.*\)/\1/")" +%s)-$(date -d now +%s))/86400 )) + {% else %} + echo $(( ($(date -D '%b %e %H:%M:%S %Y' -d "$(openssl x509 -in {{ ca_cert_tls_cert_path }} -enddate -noout | sed "s/.*=\(.*\)/\1/")" +%s)-$(date +%s))/86400 )) + {% endif %} + register: ca_cert_cert_remaining_days + changed_when: false + check_mode: false + when: ca_cert_proto == 'tls' and not ca_cert_tls_cert_is_valid.changed + +- name: 'set cert validity' + set_fact: + ca_cert_cert_is_valid: >- + {% if ca_cert_proto == 'tls' %}{{ ca_cert_tls_cert_is_valid }}{% + elif ca_cert_proto == 'ssh' %}{{ ca_cert_ssh_cert_is_valid }}{% endif %} + +- name: 'set remaning validity' + set_fact: + ca_cert_cert_remaining_days: >- + {% if ca_cert_proto == 'tls' %}{{ ca_cert_cert_remaining_days.stdout }}{% + elif ca_cert_proto == 'ssh' %}{{ ca_cert_cert_is_valid.certificate.valid.remaining_days }}{% endif %} + when: ca_cert_cert_is_valid.rc|d(1) == 0 + +- name: 'renew' + block: + - name: 'RENEW | backup existing private keys' + copy: + remote_src: true + src: '{{ item }}' + dest: '{{ item }}-backup' + failed_when: false + register: ca_cert_key_backup + loop: '{{ keypair[ca_cert_proto] }}' + vars: + keypair: + ssh: + - '{{ ca_cert_ssh_key_path }}' + - '{{ ca_cert_ssh_key_path }}.pub' + tls: + - '{{ ca_cert_tls_key_path }}' + + - name: 'RENEW | TLS | create private key (if not exists)' + command: > + openssl genpkey + -algorithm ed25519 + -out {{ ca_cert_tls_key_path }} + args: + creates: >- + {{ "" if ca_cert_renew_private_key else ca_cert_tls_key_path }} + when: ca_cert_proto == 'tls' + + - name: 'RENEW | SSH | create key pair' + openssh_keypair: + force: '{{ ca_cert_renew_private_key }}' + path: '{{ ca_cert_ssh_key_path }}' + type: 'ed25519' + when: ca_cert_proto == 'ssh' + + - name: 'RENEW | TLS | create cert signing request' + command: > + openssl req + -new + -subj '{{ ca_cert_tls_subj }}' + -key '{{ ca_cert_tls_key_path }}' + -out '{{ ca_cert_tls_csr_path }}' + when: ca_cert_proto == 'tls' + + - name: 'RENEW | CA_MANAGER | generate json signing request' + cert_request: + host: '{{ ca_cert_common_name }}' + path: >- + {% if ca_cert_proto == 'tls' %}{{ ca_cert_tls_csr_path }}{% + elif ca_cert_proto == 'ssh' %}{{ ca_cert_ssh_key_path+'.pub' }}{% endif %} + proto: '{{ "ssl" if ca_cert_proto == "tls" else ca_cert_proto }}' + client: '{{ ca_cert_client }}' + register: ca_cert_signing_request + + - name: 'RENEW | CA_MANAGER | send signing request' + raw: '{{ ca_cert_signing_request | to_json }}' + delegate_to: '{{ ca_cert_ca_manager_host }}' + delegate_facts: true + register: ca_cert_signing_request_results + failed_when: (ca_cert_signing_request_results.stdout|from_json).failed + + - name: 'RENEW | CA_MANAGER | set signing request id' + set_fact: + ca_cert_request_id: >- + {{ (ca_cert_signing_request_results.stdout|from_json).requestID }} + + - name: 'RENEW | CA_MANAGER | generate json get request' + set_fact: + ca_cert_get_request: + type: 'get_certificate' + requestID: '{{ ca_cert_request_id }}' + + - name: 'RENEW | CA_MANAGER | prompt for signature' + debug: + msg: >- + Please manually confirm sign request with id {{ ca_cert_request_id }}. + + - name: 'RENEW | CA_MANAGER | send get request' + raw: '{{ ca_cert_get_request | to_json }}' + delegate_to: '{{ ca_cert_ca_manager_host }}' + delegate_facts: true + register: ca_cert_get_request_results + failed_when: (ca_cert_get_request_results.stdout|from_json).failed + + - name: 'RENEW | store new certificate' + copy: + content: '{{ (ca_cert_get_request_results.stdout|from_json).result }}' + dest: >- + {% if ca_cert_proto == 'tls' %}{{ ca_cert_tls_cert_path }}{% + elif ca_cert_proto == 'ssh' %}{{ ca_cert_ssh_key_path }}-cert.pub{% endif %} + rescue: + - name: 'RENEW FAILED | restore backup' + copy: + remote_src: true + src: '{{ item.dest }}' + dest: '{{ item.src }}' + when: not item.failed + loop: '{{ ca_cert_key_backup.results }}' + always: + - name: 'RENEW | clean backup' + file: + path: '{{ item.dest }}' + state: 'absent' + when: not item.failed + loop: '{{ ca_cert_key_backup.results }}' + when: ca_cert_cert_is_valid.changed or ca_cert_cert_remaining_days|int < ca_cert_min_days_validity +... diff --git a/roles/ldap/defaults/main.yaml b/roles/ldap/defaults/main.yaml index 0aee74f..197ae42 100644 --- a/roles/ldap/defaults/main.yaml +++ b/roles/ldap/defaults/main.yaml @@ -6,8 +6,8 @@ ldap_organization: '{{ organization }}' ldap_check_tree: true ldap_tls_enabled: true -ldap_tls_server_ca: '{{ tls_root_ca }}' -ldap_tls_user_ca: '{{ tls_root_ca }}' +ldap_tls_server_ca: '{{ tls_intermediate_server_ca }}' +ldap_tls_user_ca: '{{ tls_intermediate_user_ca }}' ldap_server_accounts: - 'projects.dmz.{{ domain }}' diff --git a/roles/ldap/tasks/4_setup_tls.yaml b/roles/ldap/tasks/4_setup_tls.yaml index b38c6e7..c774eb1 100644 --- a/roles/ldap/tasks/4_setup_tls.yaml +++ b/roles/ldap/tasks/4_setup_tls.yaml @@ -1,3 +1,4 @@ +--- - name: 'install openssl' apt: pkg: 'openssl' @@ -7,68 +8,39 @@ tags: - 'packages' -- name: 'create slapd private key' - shell: - cmd: > - openssl genpkey - -algorithm ED25519 - -out /etc/ldap/slapd.key - creates: '/etc/ldap/slapd.key' - tags: - - 'tls_int' - -- name: 'set private key ownership' - file: - path: '/etc/ldap/slapd.key' - owner: 'openldap' - group: 'openldap' - mode: '600' - - name: 'update tls server ca' copy: - content: '{{ ldap_tls_server_ca }}' + content: '{{ ldap_tls_server_ca }}{{ tls_root_ca }}' dest: '/etc/ldap/server_ca.crt' tags: - 'tls_int' - name: 'update tls user ca' copy: - content: '{{ ldap_tls_user_ca }}' + content: '{{ ldap_tls_user_ca }}{{ tls_root_ca }}' dest: '/etc/ldap/user_ca.crt' - -- name: 'check slapd cert against server ca' - command: > - openssl verify - -CAfile /etc/ldap/server_ca.crt - -untrusted /etc/ldap/slapd.crt - /etc/ldap/slapd.crt - register: slapd_cert_is_valid - changed_when: false - failed_when: false - tags: - - 'tls_int' - -- name: 'create slapd cert request' - shell: - cmd: > - openssl req - -new - -subj '{{ openssl_x509_prefix }}/OU=Server/CN={{ host_fqdn }}' - -key /etc/ldap/slapd.key - -out /etc/ldap/slapd.csr - when: slapd_cert_is_valid.rc != 0 tags: - 'tls_int' -- import_tasks: 'ca-signing-request.yaml' +- name: 'generete and sign slapd tls certificate' + import_role: name='ca_cert' vars: - host: '{{ host_fqdn }}' - request_path: '/etc/ldap/slapd.csr' - output_path: '/etc/ldap/slapd.crt' - when: slapd_cert_is_valid.rc != 0 + ca_cert_common_name: '{{ host_fqdn }}' + ca_cert_proto: 'tls' + ca_cert_tls_ca_path: '/etc/ldap/server_ca.crt' + ca_cert_tls_key_path: '/etc/ldap/slapd.key' + ca_cert_tls_cert_path: '/etc/ldap/slapd.crt' + ca_cert_tls_csr_path: '/etc/ldap/slapd.csr' tags: - 'tls_int' +- name: 'set private key ownership' + file: + path: '/etc/ldap/slapd.key' + owner: 'openldap' + group: 'openldap' + mode: '600' + # !BUG! Fixed in Ansible dev using ldap_attrs instead of ldap_attr # Setting the parameters twice in a row fix the problem. # Ref: https://github.com/ansible/ansible/issues/25665 @@ -110,3 +82,4 @@ notify: 'restart slapd' tags: - 'tls_int' +... diff --git a/roles/openvpn/tasks/main.yaml b/roles/openvpn/tasks/main.yaml index 3b91740..f0c4d85 100644 --- a/roles/openvpn/tasks/main.yaml +++ b/roles/openvpn/tasks/main.yaml @@ -6,18 +6,6 @@ tags: - 'packages' -- name: 'create openvpn private key' - shell: - cmd: > - openssl genpkey - -algorithm ed25519 - -out /etc/openvpn/openvpn.key - args: - creates: '/etc/openvpn/openvpn.key' - notify: 'reload openvpn' - tags: - - 'tls_int' - # Shouldn't be required for TLSv1.3 # #- name: create openvpn dh2048 @@ -41,37 +29,15 @@ tags: - 'tls_int' -- name: 'check openvpn cert status' - command: >- - openssl verify - -CAfile /etc/openvpn/server_ca.crt - /etc/openvpn/openvpn.crt - register: openvpn_cert_is_valid - changed_when: false - failed_when: false - tags: - - 'tls_int' - -- name: 'create openvpn cert request' - shell: > - openssl req - -new - -subj "{{ openssl_x509_prefix }}/OU=Server/CN={{ host_fqdn }}" - -key /etc/openvpn/openvpn.key - -out /etc/openvpn/openvpn.csr - when: openvpn_cert_is_valid.rc != 0 - tags: - - 'tls_int' - -- import_tasks: 'ca-signing-request.yaml' +- name: 'generate and sign server certificate' + import_role: name='ca_cert' vars: - host: '{{ host_fqdn }}' - request_path: '/etc/openvpn/openvpn.csr' - output_path: '/etc/openvpn/openvpn.crt' - when: openvpn_cert_is_valid.rc != 0 - notify: 'reload openvpn' - tags: - - 'tls_int' + ca_cert_common_name: '{{ host_fqdn }}' + ca_cert_proto: 'tls' + ca_cert_tls_ca_path: '/etc/openvpn/server_ca.crt' + ca_cert_tls_key_path: '/etc/openvpn/openvpn.key' + ca_cert_tls_csr_path: '/etc/openvpn/openvpn.csr' + ca_cert_tls_cert_path: '/etc/openvpn/openvpn.crt' - name: 'write openvpn configuration' template: @@ -87,3 +53,4 @@ shell: 'uci commit openvpn' notify: 'reload openvpn' when: config_updated.changed +... diff --git a/roles/ssh_server/tasks/main.yaml b/roles/ssh_server/tasks/main.yaml index 40b80e5..3c97edc 100644 --- a/roles/ssh_server/tasks/main.yaml +++ b/roles/ssh_server/tasks/main.yaml @@ -1,108 +1,54 @@ --- -- include: 'roles/service/tasks/main.yaml' +- import_role: name='service' vars: service_name: 'ssh' service_packages: - 'openssh-server' - 'openssh-sftp-server' -- name: 'update user ca certs' - template: - src: 'user_ca.pub.j2' - dest: '/etc/ssh/user_ca.pub' +- name: 'upload user and server ca' + copy: + content: | + {% for ca in item.1 %} + {{ ca }} + {% endfor %} + dest: '/etc/ssh/{{ item.0 }}_ca.pub' + vars: + cas: '{{ item.1 }}' notify: 'restart ssh' + loop: + - [ 'user', '{{ ssh_user_ca }}' ] + - [ 'server', '{{ ssh_server_ca }}' ] tags: - - ssh_certs - -- name: 'validate ssh cert if present' - ssh_cert: - register: ssh_verification - ignore_errors: yes - tags: - - ssh_certs - -- debug: - var: ssh_verification - verbosity: 2 - tags: - - ssh_certs - -- block: - - name: 'generate host cert request' - cert_request: - host: '{{ host_fqdn }}' - path: '/etc/ssh/ssh_host_ed25519_key.pub' - proto: 'ssh' - register: ca_request - - - name: 'start sign request' - include: 'ca-dialog.yaml' - vars: - ansible_connection: 'ssh' - - - debug: - var: request_result - verbosity: 2 - - - set_fact: - request_output: '{{ request_result.stdout | from_json }}' + - 'ssh_certs' - - debug: - var: request_output - verbosity: 2 - - - name: 'generate get request' - set_fact: - ca_request: - type: 'get_certificate' - requestID: '{{ request_output.requestID }}' - - - debug: - var: ca_request - verbosity: 2 - - - debug: - msg: 'Please manualy confirm sign request with id {{ request_output.requestID }}' - - - name: 'wait for cert' - include: 'ca-dialog.yaml' - vars: - ansible_connection: 'ssh' - - - debug: - var: request_result - verbosity: 2 - - - set_fact: - cert_key: '{{ request_result.stdout | string | from_json }}' - - - name: 'write certificate to container' - copy: - content: '{{ cert_key.result }}' - dest: '/etc/ssh/ssh_host_ed25519_key-cert.pub' - register: set_pub_key - notify: 'restart ssh' - when: ssh_verification.failed +- name: 'generate and sign host certificate' + import_role: name='ca_cert' + vars: + ca_cert_common_name: '{{ host_fqdn }}' + ca_cert_proto: 'ssh' + ca_cert_ssh_ca_path: '/etc/ssh/server_ca.pub' + ca_cert_ssh_key_path: '/etc/ssh/ssh_host_ed25519_key' tags: - - ssh_certs + - 'ssh_certs' -- name: 'add certificate to sshd config' +- name: 'add host certificate to sshd config' lineinfile: line: 'HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub' dest: '/etc/ssh/sshd_config' regexp: '^HostCertificate *' notify: 'restart ssh' tags: - - ssh_certs + - 'ssh_certs' -- name: 'trust user ca key' +- name: 'add user ca to sshd config' lineinfile: line: 'TrustedUserCAKeys /etc/ssh/user_ca.pub' dest: '/etc/ssh/sshd_config' regexp: '^TrustedUserCAKeys *' notify: 'restart ssh' tags: - - ssh_certs + - 'ssh_certs' - name: 'permit root login only with certificate' lineinfile: diff --git a/roles/ssh_server/templates/user_ca.pub.j2 b/roles/ssh_server/templates/user_ca.pub.j2 deleted file mode 100644 index fe55c72..0000000 --- a/roles/ssh_server/templates/user_ca.pub.j2 +++ /dev/null @@ -1,4 +0,0 @@ -{% for key in ssh_user_ca %} -{{ key }} -{% endfor %} - diff --git a/tasks/ca-dialog.yaml b/tasks/ca-dialog.yaml index b7c7baf..2f95842 100644 --- a/tasks/ca-dialog.yaml +++ b/tasks/ca-dialog.yaml @@ -1,17 +1,10 @@ +### DEPRECATED -> import role `ca_cert` instead - debug: - msg: "Sending certificate request to {{ hostvars | ip_from_inventory('authorities_request') }}" - -- debug: - var: ca_request - verbosity: 2 + msg: "Warning, deprecated" - name: 'CA_MANAGER | sending request to ca...' raw: '{{ ca_request | to_json }}' delegate_to: 'authorities_request' delegate_facts: True register: request_result - -- debug: - var: request_result - verbosity: 2 failed_when: '( request_result.stdout | from_json ).failed' diff --git a/tasks/ca-signing-request.yaml b/tasks/ca-signing-request.yaml deleted file mode 100644 index 17f708d..0000000 --- a/tasks/ca-signing-request.yaml +++ /dev/null @@ -1,42 +0,0 @@ ---- -- name: 'CA_MANAGER | generating json signing request' - cert_request: - host: '{{ host }}' - path: '{{ request_path }}' - proto: 'ssl' - client: '{{ client | default(false) }}' - register: ca_request - -- name: 'CA_MANAGER | sending json signing request' - import_tasks: 'ca-dialog.yaml' - -- name: 'CA_MANAGER | read ca answer' - set_fact: - request_output: '{{ request_result.stdout | string | from_json }}' - -- debug: - var: request_result - -- name: 'CA_MANAGER | generating json get request' - set_fact: - ca_request: - type: 'get_certificate' - requestID: '{{ request_output.requestID }}' - -- name: 'CA_MANAGER | print request id' - debug: - msg: > - Please manually confirm sign request with id - {{ request_output.requestID }} - -- name: 'CA_MANAGER | waiting for certificate...' - include: 'ca-dialog.yaml' - -- name: 'CA MANAGER | read certificate' - set_fact: - cert_key: '{{ request_result.stdout | string | from_json }}' - -- name: 'CA_MANAGER | saving certificate' - copy: - content: '{{ cert_key.result }}' - dest: '{{ output_path }}'