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

- set_fact:
    system_potentially_has_no_algorithm_support: "{{ ansible_os_family == 'FreeBSD' }}"

- name: "({{ select_crypto_backend }}) Read private key"
  slurp:
    src: '{{ remote_tmp_dir }}/privatekey1.pem'
  register: slurp

- name: "({{ select_crypto_backend }}) Validate privatekey1 idempotency and content returned"
  assert:
    that:
      - privatekey1_check is changed
      - privatekey1 is changed
      - privatekey1_idempotence_check is not changed
      - privatekey1_idempotence is not changed
      - privatekey1.privatekey == (slurp.content | b64decode)
      - privatekey1.privatekey == privatekey1_idempotence.privatekey


- name: "({{ select_crypto_backend }}) Validate privatekey1 (test - RSA key with size 4096 bits)"
  shell: "{{ openssl_binary }} rsa -noout -text -in {{ remote_tmp_dir }}/privatekey1.pem  | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
  register: privatekey1

- name: "({{ select_crypto_backend }}) Validate privatekey1 (assert - RSA key with size 4096 bits)"
  assert:
    that:
      - privatekey1.stdout == '4096'


- name: "({{ select_crypto_backend }}) Validate privatekey2 (test - RSA key with size 2048 bits)"
  shell: "{{ openssl_binary }} rsa -noout -text -in {{ remote_tmp_dir }}/privatekey2.pem  | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
  register: privatekey2

- name: "({{ select_crypto_backend }}) Validate privatekey2 (assert - RSA key with size 2048 bits)"
  assert:
    that:
      - privatekey2.stdout == '2048'


- name: "({{ select_crypto_backend }}) Validate privatekey3 (test - DSA key with size 3072 bits)"
  shell: "{{ openssl_binary }} dsa -noout -text -in {{ remote_tmp_dir }}/privatekey3.pem  | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
  register: privatekey3

- name: Validate privatekey3 (assert - DSA key with size 3072 bits)
  assert:
    that:
      - privatekey3.stdout == '3072'


- name: "({{ select_crypto_backend }}) Validate privatekey4 (test - Ensure key has been removed)"
  stat:
    path: '{{ remote_tmp_dir }}/privatekey4.pem'
  register: privatekey4

- name: "({{ select_crypto_backend }}) Validate privatekey4 (assert - Ensure key has been removed)"
  assert:
    that:
      - privatekey4.stat.exists == False

- name: "({{ select_crypto_backend }}) Validate privatekey4 removal behavior"
  assert:
    that:
      - privatekey4_delete is changed
      - privatekey4_delete.privatekey is none
      - privatekey4_delete_idempotence is not changed


- name: "({{ select_crypto_backend }}) Validate privatekey5 (test - Passphrase protected key + idempotence)"
  shell: "{{ openssl_binary }} rsa -noout -text -in {{ remote_tmp_dir }}/privatekey5.pem -passin pass:ansible  | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
  register: privatekey5
  # Current version of OS/X that runs in the CI (10.11) does not have an up to date version of the OpenSSL library
  # leading to this test to fail when run in the CI. However, this test has been run for 10.12 and has returned successfully.
  when: openssl_version.stdout is version('0.9.8zh', '>=')

- name: "({{ select_crypto_backend }}) Validate privatekey5 (assert - Passphrase protected key + idempotence)"
  assert:
    that:
      - privatekey5.stdout == (default_rsa_key_size | string)
  when: openssl_version.stdout is version('0.9.8zh', '>=')

- name: "({{ select_crypto_backend }}) Validate privatekey5 idempotence (assert - Passphrase protected key + idempotence)"
  assert:
    that:
      - privatekey5_idempotence is not changed


- name: "({{ select_crypto_backend }}) Validate privatekey6 (test - Passphrase protected key with non ascii character)"
  shell: "{{ openssl_binary }} rsa -noout -text -in {{ remote_tmp_dir }}/privatekey6.pem -passin pass:ànsïblé | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
  register: privatekey6
  when: openssl_version.stdout is version('0.9.8zh', '>=')

- name: "({{ select_crypto_backend }}) Validate privatekey6 (assert - Passphrase protected key with non ascii character)"
  assert:
    that:
      - privatekey6.stdout == (default_rsa_key_size | string)
  when: openssl_version.stdout is version('0.9.8zh', '>=')

- name: "({{ select_crypto_backend }}) Validate ECC generation (dump with OpenSSL)"
  shell: "{{ openssl_binary }} ec -in {{ remote_tmp_dir }}/privatekey-{{ item.item.curve }}.pem -noout -text | grep 'ASN1 OID: ' | sed 's/ASN1 OID: \\([^ ]*\\)/\\1/'"
  loop: "{{ privatekey_ecc_generate.results }}"
  register: privatekey_ecc_dump
  when: openssl_version.stdout is version('0.9.8zh', '>=') and 'skip_reason' not in item
  loop_control:
    label: "{{ item.item.curve }}"

- name: "({{ select_crypto_backend }}) Validate ECC generation"
  assert:
    that:
    - item is changed
  loop: "{{ privatekey_ecc_generate.results }}"
  when: "'skip_reason' not in item"
  loop_control:
    label: "{{ item.item.curve }}"

- name: "({{ select_crypto_backend }}) Validate ECC generation (curve type)"
  assert:
    that:
    - "'skip_reason' in item or item.item.item.openssl_name == item.stdout"
  loop: "{{ privatekey_ecc_dump.results }}"
  when: "'skip_reason' not in item"
  loop_control:
    label: "{{ item.item.item }} - {{ item.stdout if 'stdout' in item else '<unsupported>' }}"

- name: "({{ select_crypto_backend }}) Validate ECC generation idempotency"
  assert:
    that:
    - item is not changed
  loop: "{{ privatekey_ecc_idempotency.results }}"
  when: "'skip_reason' not in item"
  loop_control:
    label: "{{ item.item.curve }}"

- name: "({{ select_crypto_backend }}) Validate other type generation (just check changed)"
  assert:
    that:
    - (item is succeeded and item is changed) or
      (item is failed and 'Cryptography backend does not support the algorithm required for ' in item.msg and system_potentially_has_no_algorithm_support)
  loop: "{{ privatekey_t1_generate.results }}"
  when: "'skip_reason' not in item"
  loop_control:
    label: "{{ item.item.type }}"

- name: "({{ select_crypto_backend }}) Validate other type generation idempotency"
  assert:
    that:
    - (item is succeeded and item is not changed) or
      (item is failed and 'Cryptography backend does not support the algorithm required for ' in item.msg and system_potentially_has_no_algorithm_support)
  loop: "{{ privatekey_t1_idempotency.results }}"
  when: "'skip_reason' not in item"
  loop_control:
    label: "{{ item.item.type }}"

- name: "({{ select_crypto_backend }}) Validate passphrase changing"
  assert:
    that:
      - passphrase_1 is changed
      - passphrase_2 is not changed
      - passphrase_3 is changed
      - passphrase_4 is not changed
      - passphrase_5 is changed
      - passphrase_1.backup_file is undefined
      - passphrase_2.backup_file is undefined
      - passphrase_3.backup_file is string
      - passphrase_4.backup_file is undefined
      - passphrase_5.backup_file is string

- name: "({{ select_crypto_backend }}) Verify that broken key will be regenerated"
  assert:
    that:
      - output_broken is changed

- name: "({{ select_crypto_backend }}) Validate remove"
  assert:
    that:
      - remove_1 is changed
      - remove_2 is not changed
      - remove_1.backup_file is string
      - remove_2.backup_file is undefined

- name: "({{ select_crypto_backend }}) Validate mode"
  assert:
    that:
      - privatekey_mode_1 is changed
      - privatekey_mode_1_stat.stat.mode == '0400'
      - privatekey_mode_2 is not changed
      - privatekey_mode_3 is changed
      - privatekey_mode_3_stat.stat.mode == '0400'
      - privatekey_mode_3_file_change is changed

- name: "({{ select_crypto_backend }}) Validate format 1"
  assert:
    that:
      - privatekey_fmt_1_step_1 is changed
      - privatekey_fmt_1_step_2 is not changed
      - privatekey_fmt_1_step_3 is not changed
      - privatekey_fmt_1_step_4 is changed
      - privatekey_fmt_1_step_5 is not changed
      - privatekey_fmt_1_step_6 is not changed
      - privatekey_fmt_1_step_7 is changed
      - privatekey_fmt_1_step_8 is failed
      - privatekey_fmt_1_step_9 is changed
      - privatekey_fmt_1_step_9_before.public_key == privatekey_fmt_1_step_9_after.public_key
  when: 'select_crypto_backend == "cryptography"'

- name: "({{ select_crypto_backend }}) Validate format 2 (failed)"
  assert:
    that:
      - system_potentially_has_no_algorithm_support
      - privatekey_fmt_2_step_1 is failed
      - "'Cryptography backend does not support the algorithm required for ' in privatekey_fmt_2_step_1.msg"
  when: 'select_crypto_backend == "cryptography" and cryptography_version.stdout is version("2.6", ">=") and privatekey_fmt_2_step_1 is failed'

- name: "({{ select_crypto_backend }}) Validate format 2"
  assert:
    that:
      - privatekey_fmt_2_step_1 is succeeded and privatekey_fmt_2_step_1 is changed
      - privatekey_fmt_2_step_2 is succeeded and privatekey_fmt_2_step_2 is not changed
      - privatekey_fmt_2_step_3 is succeeded and privatekey_fmt_2_step_3 is changed
      - privatekey_fmt_2_step_4 is succeeded and privatekey_fmt_2_step_4 is not changed
      - privatekey_fmt_2_step_5 is succeeded and privatekey_fmt_2_step_5 is not changed
      - privatekey_fmt_2_step_6 is succeeded and privatekey_fmt_2_step_6 is changed
  when: 'select_crypto_backend == "cryptography" and cryptography_version.stdout is version("2.6", ">=") and privatekey_fmt_2_step_1 is not failed'
