---
- name: Ensure the directory containing the cert exist
  file:
    path: "{{ directory }}"
    state: directory

- name: Test if the key already exist
  stat:
    path: "{{ directory }}/{{ cname }}.key"
  register: key_file

- name: Test if the cert already exist
  stat:
    path: "{{ directory }}/{{ cname }}.crt"
  register: cert_file

- name: Test if we need to renew the certificate
  openssl_certificate_info:
    path: "{{ directory }}/{{ cname }}.crt"
    valid_at:
      renewal: "{{ time_before_expiration_for_renewal }}"
  register: validity
  when: cert_file.stat.exists

- name:  Generate the certificate
  block:
    - name: Generate private key
      become: false
      openssl_privatekey:
        path: "/tmp/ansible_hacky_pki_{{ cname }}.key"
        mode: u=rw,g=,o=
        size: "{{ key_size | default(omit) }}"
      delegate_to: localhost
    
    - name: Generate a Certificate Signing Request
      become: false
      openssl_csr:
        path: "/tmp/ansible_hacky_pki_{{ cname }}.csr"
        privatekey_path: "/tmp/ansible_hacky_pki_{{ cname }}.key"
        common_name: "{{ cname }}"
        country_name: "{{ country_name | default(omit) }}"
        locality_name: "{{ locality_name | default(omit) }}"
        state_or_province_name: "{{ state_or_province_name | default(omit) }}"
        organization_name: "{{ organization_name | default(omit) }}"
        organizational_unit_name: "{{ organizational_unit_name | default(omit) }}"
        email_address: "{{ email_address | default(omit) }}"
        basic_constraints:
          - CA:FALSE # syntax?
        basic_constraints_critical: yes
        key_usage: "{{ key_usage }}"
        key_usage_critical: yes
        subject_alt_name: "{{ subject_alt_name | default(omit) }}"
        crl_distribution_points: "{{ crl_distribution_points | default(omit) }}"
      delegate_to: localhost
    
    - name: Put the CA in a file
      become: false
      copy:
        content: "{{ ca_cert }}"
        dest: "/tmp/ansible_hacky_pki_ca.crt"
      delegate_to: localhost
    
    - name: Put the CA key in a file
      become: false
      copy:
        content: "{{ ca_key }}"
        dest: "/tmp/ansible_hacky_pki_ca.key"
        mode: u=rw,g=,o=
      delegate_to: localhost
      no_log: true
    
    - name: Sign the certificate
      become: false
      openssl_certificate:
        path: "/tmp/ansible_hacky_pki_{{ cname }}.crt"
        csr_path: "/tmp/ansible_hacky_pki_{{ cname }}.csr"
        ownca_not_after: "{{ validity_duration }}"
        ownca_path: /tmp/ansible_hacky_pki_ca.crt
        ownca_privatekey_passphrase: "{{ ca_passphrase }}"
        ownca_privatekey_path: /tmp/ansible_hacky_pki_ca.key
        provider: ownca
      delegate_to: localhost
    
    - name: Send private key to the server
      copy:
        src: "/tmp/ansible_hacky_pki_{{ cname }}.key"
        dest: "{{ directory }}/{{ cname }}.key"
        owner: "{{ owner | default('root') }}"
        group: "{{ group | default('root') }}"
        mode: "{{ key_mode | default('u=rw,g=,o=') }}"
      no_log: yes
    
    - name: Send certificate to the server
      copy:
        src: "/tmp/ansible_hacky_pki_{{ cname }}.crt"
        dest: "{{ directory }}/{{ cname }}.crt"
        owner: "{{ owner | default('root') }}"
        group: "{{ group | default('root') }}"
        mode: "{{ key_mode | default('u=rw,g=r,o=r') }}"
    
    # Clean up
    - name: Remove the local cert key
      become: false
      file:
        path: "/tmp/ansible_hacky_pki_{{ cname }}.key"
        state: absent
      delegate_to: localhost
    
    - name: Remove the CSR
      become: false
      file:
        path: "/tmp/ansible_hacky_pki_{{ cname }}.csr"
        state: absent
      delegate_to: localhost
    
    - name: Remove the local certificate
      become: false
      file:
        path: "/tmp/ansible_hacky_pki_{{ cname }}.crt"
        state: absent
      delegate_to: localhost
    
    - name: Remove the CA certificate
      become: false
      file:
        path: /tmp/ansible_hacky_pki_ca.crt
        state: absent
      delegate_to: localhost
    
    - name: Remove the CA key
      become: false
      file:
        path: /tmp/ansible_hacky_pki_ca.key
        state: absent
      delegate_to: localhost
  when: force_renewal or (not key_file.stat.exists) or (not cert_file.stat.exists) or (not validity.valid_at.renewal)