---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later

## PRIVATE KEY ################################################################################
- name: ({{ certgen_title }}) Create cert private key
  openssl_privatekey:
    path: "{{ remote_tmp_dir }}/{{ certificate_name }}.key"
    type: "{{ 'RSA' if key_type == 'rsa' else 'ECC' }}"
    size: "{{ rsa_bits if key_type == 'rsa' else omit }}"
    curve: >-
      {{ omit if key_type == 'rsa' else
         'secp256r1' if key_type == 'ec256' else
         'secp384r1' if key_type == 'ec384' else
         'secp521r1' if key_type == 'ec521' else
         'invalid value for key_type!' }}
    passphrase: "{{ certificate_passphrase | default(omit) | default(omit, true) }}"
    force: true
## CSR ########################################################################################
- name: ({{ certgen_title }}) Create cert CSR
  openssl_csr:
    path: "{{ remote_tmp_dir }}/{{ certificate_name }}.csr"
    privatekey_path: "{{ remote_tmp_dir }}/{{ certificate_name }}.key"
    privatekey_passphrase: "{{ certificate_passphrase | default(omit) | default(omit, true) }}"
    subject_alt_name: "{{ subject_alt_name }}"
    subject_alt_name_critical: "{{ subject_alt_name_critical }}"
    return_content: true
  register: csr_result
## ACME STEP 1 ################################################################################
- name: ({{ certgen_title }}) Obtain cert, step 1
  acme_certificate:
    select_crypto_backend: "{{ select_crypto_backend }}"
    acme_version: 2
    acme_directory: "{{ acme_directory_url }}"
    validate_certs: false
    account_key: "{{ (remote_tmp_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
    account_key_content: "{{ account_key_content | default(omit) }}"
    account_key_passphrase: "{{ account_key_passphrase | default(omit) | default(omit, true) }}"
    modify_account: "{{ modify_account }}"
    csr: "{{ omit if use_csr_content | default(false) else remote_tmp_dir ~ '/' ~ certificate_name ~ '.csr' }}"
    csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
    dest: "{{ remote_tmp_dir }}/{{ certificate_name }}.pem"
    fullchain_dest: "{{ remote_tmp_dir }}/{{ certificate_name }}-fullchain.pem"
    chain_dest: "{{ remote_tmp_dir }}/{{ certificate_name }}-chain.pem"
    challenge: "{{ challenge }}"
    deactivate_authzs: "{{ deactivate_authzs }}"
    force: "{{ force }}"
    remaining_days: "{{ remaining_days }}"
    terms_agreed: "{{ terms_agreed }}"
    account_email: "{{ account_email }}"
    profile: "{{ acme_certificate_profile | default(omit) }}"
    include_renewal_cert_id: "{{ acme_certificate_include_renewal_cert_id | default(omit) }}"
  register: challenge_data
- name: ({{ certgen_title }}) Print challenge data
  debug:
    var: challenge_data
- name: ({{ certgen_title }}) Create HTTP challenges
  uri:
    url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
    method: PUT
    body_format: raw
    body: "{{ item.value['http-01'].resource_value }}"
    headers:
      content-type: "application/octet-stream"
  with_dict: "{{ challenge_data.challenge_data }}"
  when: "challenge_data is changed and challenge == 'http-01'"
- name: ({{ certgen_title }}) Create DNS challenges
  uri:
    url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
    method: PUT
    body_format: json
    body: "{{ item.value }}"
  with_dict: "{{ challenge_data.challenge_data_dns }}"
  when: "challenge_data is changed and challenge == 'dns-01'"
- name: ({{ certgen_title }}) Create TLS ALPN challenges (acme_challenge_cert_helper)
  acme_challenge_cert_helper:
    challenge: tls-alpn-01
    challenge_data: "{{ item.value['tls-alpn-01'] }}"
    private_key_src: "{{ remote_tmp_dir }}/{{ certificate_name }}.key"
    private_key_passphrase: "{{ certificate_passphrase | default(omit) | default(omit, true) }}"
  with_dict: "{{ challenge_data.challenge_data if challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls | default('der-value-b64') == 'acme_challenge_cert_helper') else {} }}"
  register: tls_alpn_challenges
  when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls | default('der-value-b64') == 'acme_challenge_cert_helper')"
- name: ({{ certgen_title }}) Read private key
  slurp:
    src: '{{ remote_tmp_dir }}/{{ certificate_name }}.key'
  register: slurp
  when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls | default('der-value-b64') == 'acme_challenge_cert_helper')"
- name: ({{ certgen_title }}) Set TLS ALPN challenges (acme_challenge_cert_helper)
  uri:
    url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.domain }}/{{ item.identifier }}/certificate-and-key"
    method: PUT
    body_format: raw
    body: "{{ item.challenge_certificate }}\n{{ slurp.content | b64decode }}"
    headers:
      content-type: "application/pem-certificate-chain"
  with_items: "{{ tls_alpn_challenges.results if challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls | default('der-value-b64') == 'acme_challenge_cert_helper') else [] }}"
  when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls | default('der-value-b64') == 'acme_challenge_cert_helper')"
- name: ({{ certgen_title }}) Create TLS ALPN challenges (der-value-b64)
  uri:
    url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}/{{ item.value['tls-alpn-01'].resource_original }}/der-value-b64"
    method: PUT
    body_format: raw
    body: "{{ item.value['tls-alpn-01'].resource_value }}"
    headers:
      content-type: "application/octet-stream"
  with_dict: "{{ challenge_data.challenge_data if challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls | default('der-value-b64') == 'der-value-b64') else {} }}"
  when: "challenge_data is changed and challenge == 'tls-alpn-01' and (challenge_alpn_tls | default('der-value-b64') == 'der-value-b64')"
## ACME STEP 2 ################################################################################
- name: ({{ certgen_title }}) Obtain cert, step 2
  acme_certificate:
    select_crypto_backend: "{{ select_crypto_backend }}"
    acme_version: 2
    acme_directory: "{{ acme_directory_url }}"
    validate_certs: false
    account_key: "{{ (remote_tmp_dir ~ '/' ~ account_key ~ '.pem') if account_key_content is not defined else omit }}"
    account_key_content: "{{ account_key_content | default(omit) }}"
    account_key_passphrase: "{{ account_key_passphrase | default(omit) | default(omit, true) }}"
    account_uri: "{{ challenge_data.account_uri }}"
    modify_account: "{{ modify_account }}"
    csr: "{{ omit if use_csr_content | default(false) else remote_tmp_dir ~ '/' ~ certificate_name ~ '.csr' }}"
    csr_content: "{{ csr_result.csr if use_csr_content | default(false) else omit }}"
    dest: "{{ remote_tmp_dir }}/{{ certificate_name }}.pem"
    fullchain_dest: "{{ remote_tmp_dir }}/{{ certificate_name }}-fullchain.pem"
    chain_dest: "{{ remote_tmp_dir }}/{{ certificate_name }}-chain.pem"
    challenge: "{{ challenge }}"
    deactivate_authzs: "{{ deactivate_authzs }}"
    force: "{{ force }}"
    remaining_days: "{{ remaining_days }}"
    terms_agreed: "{{ terms_agreed }}"
    account_email: "{{ account_email }}"
    data: "{{ challenge_data }}"
    retrieve_all_alternates: "{{ retrieve_all_alternates | default(omit) }}"
    select_chain: "{{ select_chain | default(omit) if select_crypto_backend == 'cryptography' else omit }}"
  register: certificate_obtain_result
  when: challenge_data is changed
- name: ({{ certgen_title }}) Deleting HTTP challenges
  uri:
    url: "http://{{ acme_host }}:5000/http/{{ item.key }}/{{ item.value['http-01'].resource[('.well-known/acme-challenge/'|length):] }}"
    method: DELETE
  with_dict: "{{ challenge_data.challenge_data }}"
  when: "challenge_data is changed and challenge == 'http-01'"
- name: ({{ certgen_title }}) Deleting DNS challenges
  uri:
    url: "http://{{ acme_host }}:5000/dns/{{ item.key }}"
    method: DELETE
  with_dict: "{{ challenge_data.challenge_data_dns }}"
  when: "challenge_data is changed and challenge == 'dns-01'"
- name: ({{ certgen_title }}) Deleting TLS ALPN challenges
  uri:
    url: "http://{{ acme_host }}:5000/tls-alpn/{{ item.value['tls-alpn-01'].resource }}"
    method: DELETE
  with_dict: "{{ challenge_data.challenge_data }}"
  when: "challenge_data is changed and challenge == 'tls-alpn-01'"
- name: ({{ certgen_title }}) Get root certificate
  get_url:
    url: "http://{{ acme_host }}:5000/root-certificate-for-ca/{{ acme_expected_root_number | default(0) if select_crypto_backend == 'cryptography' else 0 }}"
    dest: "{{ remote_tmp_dir }}/{{ certificate_name }}-root.pem"
###############################################################################################
