---
- name: Validate assertions
  assert:
    that:
      - domains is iterable
      - host is string

- name: Gather facts
  ansible.builtin.setup:
    gather_subset:
      - date_time
  tags:
    - always

- name: Calculate the time 1 year ago (for regenerating long-term keys)
  ansible.builtin.set_fact:
    one_year_ago: |-
      {{ ansible_facts.date_time.epoch|int - (60*60*24*365) }}

- name: Get account key file stat
  ansible.builtin.stat:
    path: &account_key_src account.key
  register: account_key_stat
  tags:
    - always

- name: Generate account key
  community.crypto.openssl_privatekey:
    # yamllint disable rule:line-length
    force: |-
      {{ account_key_stat.stat.exists and account_key_stat.stat.mtime|int < one_year_ago }}
    # yamllint enable rule:line-length
    mode: 0o0600
    path: *account_key_src
    size: 4096
    state: present
    type: RSA
  tags:
    - always

- name: Register account
  community.crypto.acme_account:
    account_key_src: *account_key_src  # pragma: allowlist secret
    acme_directory: &acme_directory |-
      https://acme-v02.api.letsencrypt.org/directory
    # acme_directory: &acme_directory |-
    #   https://acme-staging-v02.api.letsencrypt.org/directory
    acme_version: &acme_version 2
    contact:
      - mailto:{{ email }}
    select_crypto_backend: &crypto_backend cryptography
    state: present
    terms_agreed: true
  vars:
    email: &email hostmaster@shore.co.il
  tags:
    - always

- name: Get host key file stat
  ansible.builtin.stat:
    path: &key_src |-
        {{ playbook_dir }}/{{ host }}.key
  register: host_key_stat

- name: Generate {{ host }} key
  community.crypto.openssl_privatekey:
    # yamllint disable rule:line-length
    force: |-
      {{  host_key_stat.stat.exists and host_key_stat.stat.mtime|int < one_year_ago }}
    # yamllint enable rule:line-length
    mode: &mode 0o0600
    path: *key_src
    size: &size 4096
    state: present
    type: &type RSA

- name: Generate {{ host }} certificate signing request
  community.crypto.openssl_csr:
    country_name: &country_name IL
    digest: &digest sha256
    email_address: *email
    locality_name: &locality_name Israel
    organization_name: &organization_name Shore technologies
    path: &csr_src '{{ host }}.csr'
    privatekey_path: *key_src
    state: present
    subject_alt_name: 'DNS:{{ domains|join(",DNS:") }}'
  register: acme_csr

- name: Create {{ host }} challenge
  community.crypto.acme_certificate:
    account_email: *email
    account_key_src: *account_key_src  # pragma: allowlist secret
    acme_directory: *acme_directory
    acme_version: *acme_version
    csr: *csr_src
    force: '{{ acme_csr is changed }}'
    fullchain_dest: &cert_src |-
        {{ playbook_dir }}/{{ host }}.crt
    modify_account: false
    remaining_days: 35
    select_crypto_backend: *crypto_backend
  register: acme_challenge

- name: Debug {{ host }} challenge
  debug:
    var: acme_challenge
    verbosity: 1

- name: Renew {{ host }} cert
  when: acme_challenge is changed
  block:

    - name: Create ACME challenge directory on {{ host }}
      delegate_to: &delegate_to '{{ delegate_host|default(host) }}'
      file:
        mode: 0o0755
        path: /var/www/www.shore.co.il/.well-known/acme-challenge
        state: directory

    - name: Copy http-01 {{ host }} challenge
      delegate_to: *delegate_to
      with_dict: |
          {{ acme_challenge['challenge_data'] }}
      copy:
        content: |-
            {{ item.value['http-01']['resource_value'] }}
        # yamllint disable-line rule:line-length
        dest: /var/www/www.shore.co.il/{{ item.value['http-01']['resource'] }}
        group: www-data
        mode: 0o0644
        owner: root

    - name: Validate {{ host }} challenge
      community.crypto.acme_certificate:
        account_email: *email
        account_key_src: *account_key_src  # pragma: allowlist secret
        acme_directory: *acme_directory
        acme_version: *acme_version
        challenge: http-01
        csr: *csr_src
        data: "{{ acme_challenge }}"
        force: true
        fullchain_dest: *cert_src
        modify_account: false
        remaining_days: 35
        select_crypto_backend: *crypto_backend

- name: Copy {{ host }} key and certificate to server
  delegate_to: *delegate_to
  with_items:
    - src: *key_src
      dest: /var/ssl/{{ filename|default('site') }}.key
      mode: 0o0444
    - src: *cert_src
      dest: /var/ssl/{{ filename|default('site') }}.crt
      mode: 0o0444
  copy:
    src: |-
        {{ item.src }}
    dest: |-
        {{ item.dest }}
    mode: |-
        {{ item.mode }}
    owner: root
    group: root
  notify: '{{ handlers|default([]) }}'

- name: Generate Diffie-Hellman parameters on {{ host }}
  tags:
    - dhparams
  delegate_to: *delegate_to
  block:
    - name: Gather facts
      ansible.builtin.setup:
        gather_subset:
          - date_time

    - name: Get dhparams file stat
      ansible.builtin.stat:
        path: &dhparams /var/ssl/dhparams
      register: dhparams_stat

    - name: Generate Diffie-Hellman parameters on {{ host }}
      community.crypto.openssl_dhparam:
        # yamllint disable rule:line-length
        force: |-
          {{ dhparams_stat.stat.exists and dhparams_stat.stat.mtime|int < one_year_ago }}
        # yamllint enable rule:line-length
        mode: 0o0644
        path: *dhparams
        # It takes a considerable amount of time to generate new DH parameters.
        # Try using the openssl backend instead of the Python Cryptography one
        # to speed it up.
        select_crypto_backend: openssl
        size: 4096
        state: present
      notify: '{{ handlers|default([]) }}'
