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

####################################################################
# WARNING: These are designed specifically for Ansible tests       #
# and should not be used as examples of how to write Ansible roles #
####################################################################

# Ensures no conflicts from previous test runs
- name: "({{ backend }}) Find old test artifacts"
  ansible.builtin.find:
    paths: "{{ remote_tmp_dir }}"
    patterns:
      - "regenerate*"
  register: old_test_artifacts

- name: "({{ backend }}) Cleanup Output Directory"
  ansible.builtin.file:
    path: "{{ item.path }}"
    state: absent
  loop: "{{ old_test_artifacts.files }}"

- name: "({{ backend }}) Regenerate - setup simple keys"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
    type: rsa
    size: 1024
    backend: "{{ backend }}"
    regenerate: "{{ item }}"
  loop: "{{ regenerate_values }}"
- name: "({{ backend }}) Regenerate - setup password protected keys"
  command: 'ssh-keygen -f {{ remote_tmp_dir }}/regenerate-b-{{ item }} -N {{ passphrase }}'
  loop: "{{ regenerate_values }}"

- name: "({{ backend }}) Regenerate - setup broken keys"
  copy:
    dest: '{{ remote_tmp_dir }}/regenerate-c-{{ item.0 }}{{ item.1 }}'
    content: 'broken key'
    mode: '0700'
  with_nested:
    - "{{ regenerate_values }}"
    - [ '', '.pub' ]

- name: "({{ backend }}) Regenerate - setup password protected keys for passphrse test"
  command: 'ssh-keygen -f {{ remote_tmp_dir }}/regenerate-d-{{ item }} -N {{ passphrase }}'
  loop: "{{ regenerate_values }}"

- name: "({{ backend }}) Regenerate - modify broken keys (check mode)"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-c-{{ item }}'
    type: rsa
    size: 1024
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  check_mode: true
  loop: "{{ regenerate_values }}"
  ignore_errors: true
  register: result
- assert:
    that:
      - result.results[0] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
      - result.results[1] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
      - result.results[2] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
      - result.results[3] is changed
      - result.results[4] is changed

- name: "({{ backend }}) Regenerate - modify broken keys"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-c-{{ item }}'
    type: rsa
    size: 1024
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  loop: "{{ regenerate_values }}"
  ignore_errors: true
  register: result
- assert:
    that:
      - result.results[0] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
      - result.results[1] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
      - result.results[2] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
      - result.results[3] is changed
      - result.results[4] is changed

- name: "({{ backend }}) Regenerate - modify password protected keys (check mode)"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-b-{{ item }}'
    type: rsa
    size: 1024
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  check_mode: true
  loop: "{{ regenerate_values }}"
  ignore_errors: true
  register: result
- assert:
    that:
      - result.results[0] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
      - result.results[1] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
      - result.results[2] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
      - result.results[3] is changed
      - result.results[4] is changed

- name: "({{ backend }}) Regenerate - modify password protected keys with passphrase (check mode)"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-b-{{ item }}'
    type: rsa
    size: 1024
    passphrase: "{{ passphrase }}"
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  check_mode: true
  loop: "{{ regenerate_values }}"
  ignore_errors: true
  register: result
  when: backend == 'cryptography'

- assert:
    that:
      - result.results[0] is success
      - result.results[1] is failed
      - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
      - result.results[2] is changed
      - result.results[3] is changed
      - result.results[4] is changed
  when: backend == 'cryptography'

- name: "({{ backend }}) Regenerate - modify password protected keys"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-b-{{ item }}'
    type: rsa
    size: 1024
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  loop: "{{ regenerate_values }}"
  ignore_errors: true
  register: result
- assert:
    that:
      - result.results[0] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[0].msg"
      - result.results[1] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[1].msg"
      - result.results[2] is failed
      - "'Unable to read the key. The key is protected with a passphrase or broken. Will not proceed.' in result.results[2].msg"
      - result.results[3] is changed
      - result.results[4] is changed

- name: "({{ backend }}) Regenerate - modify password protected keys with passphrase"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-d-{{ item }}'
    type: rsa
    size: 1024
    passphrase: "{{ passphrase }}"
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  loop: "{{ regenerate_values }}"
  ignore_errors: true
  register: result
  when: backend == 'cryptography'

- assert:
    that:
      - result.results[0] is success
      - result.results[1] is failed
      - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
      - result.results[2] is changed
      - result.results[3] is changed
      - result.results[4] is changed
  when: backend == 'cryptography'

- name: "({{ backend }}) Regenerate - not modify regular keys (check mode)"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
    type: rsa
    size: 1024
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  check_mode: true
  loop: "{{ regenerate_values }}"
  register: result
- assert:
    that:
      - result.results[0] is not changed
      - result.results[1] is not changed
      - result.results[2] is not changed
      - result.results[3] is not changed
      - result.results[4] is changed

- name: "({{ backend }}) Regenerate - not modify regular keys"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
    type: rsa
    size: 1024
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  loop: "{{ regenerate_values }}"
  register: result
- assert:
    that:
      - result.results[0] is not changed
      - result.results[1] is not changed
      - result.results[2] is not changed
      - result.results[3] is not changed
      - result.results[4] is changed

- name: "({{ backend }}) Regenerate - adjust key size (check mode)"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
    type: rsa
    size: 1048
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  check_mode: true
  loop: "{{ regenerate_values }}"
  ignore_errors: true
  register: result
- assert:
    that:
      - result.results[0] is success and result.results[0] is not changed
      - result.results[1] is failed
      - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
      - result.results[2] is changed
      - result.results[3] is changed
      - result.results[4] is changed

- name: "({{ backend }}) Regenerate - adjust key size"
  openssh_keypair:
    path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
    type: rsa
    size: 1048
    regenerate: '{{ item }}'
    backend: "{{ backend }}"
  loop: "{{ regenerate_values }}"
  ignore_errors: true
  register: result
- assert:
    that:
      - result.results[0] is success and result.results[0] is not changed
      - result.results[1] is failed
      - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
      - result.results[2] is changed
      - result.results[3] is changed
      - result.results[4] is changed

- name: "({{ backend }}) Regenerate - redistribute keys"
  copy:
    src: '{{ remote_tmp_dir }}/regenerate-a-always{{ item.1 }}'
    dest: '{{ remote_tmp_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
    remote_src: true
  with_nested:
    - "{{ regenerate_values }}"
    - [ '', '.pub' ]
  when: "item.0 != 'always'"

- vars:
    ssh_type: '{{ "dsa" if openssh_supports_dsa else "ecdsa" }}'
    ssh_size: '{{ 1024 if openssh_supports_dsa else omit }}'

  block:
  - name: "({{ backend }}) Regenerate - adjust key type (check mode)"
    openssh_keypair:
      path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
      type: '{{ ssh_type }}'
      size: '{{ ssh_size }}'
      regenerate: '{{ item }}'
      backend: "{{ backend }}"
    check_mode: true
    loop: "{{ regenerate_values }}"
    ignore_errors: true
    register: result
  - assert:
      that:
        - result.results[0] is success and result.results[0] is not changed
        - result.results[1] is failed
        - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
        - result.results[2] is changed
        - result.results[3] is changed
        - result.results[4] is changed

  - name: "({{ backend }}) Regenerate - adjust key type"
    openssh_keypair:
      path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
      type: '{{ ssh_type }}'
      size: '{{ ssh_size }}'
      regenerate: '{{ item }}'
      backend: "{{ backend }}"
    loop: "{{ regenerate_values }}"
    ignore_errors: true
    register: result
  - assert:
      that:
        - result.results[0] is success and result.results[0] is not changed
        - result.results[1] is failed
        - "'Key has wrong type and/or size. Will not proceed.' in result.results[1].msg"
        - result.results[2] is changed
        - result.results[3] is changed
        - result.results[4] is changed

  - name: "({{ backend }}) Regenerate - redistribute keys"
    copy:
      src: '{{ remote_tmp_dir }}/regenerate-a-always{{ item.1 }}'
      dest: '{{ remote_tmp_dir }}/regenerate-a-{{ item.0 }}{{ item.1 }}'
      remote_src: true
    with_nested:
      - "{{ regenerate_values }}"
      - [ '', '.pub' ]
    when: "item.0 != 'always'"

  - name: "({{ backend }}) Regenerate - adjust comment (check mode)"
    openssh_keypair:
      path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
      type: '{{ ssh_type }}'
      size: '{{ ssh_size }}'
      comment: test comment
      regenerate: '{{ item }}'
      backend: "{{ backend }}"
    check_mode: true
    loop: "{{ regenerate_values }}"
    ignore_errors: true
    register: result
  - assert:
      that:
        - result is changed

  # Support for updating comments for key types other than rsa1 was added in OpenSSH 7.2
  - when: not (backend == 'opensshbin' and openssh_version is version('7.2', '<'))
    block:
    - name: "({{ backend }}) Regenerate - adjust comment"
      openssh_keypair:
        path: '{{ remote_tmp_dir }}/regenerate-a-{{ item }}'
        type: '{{ ssh_type }}'
        size: '{{ ssh_size }}'
        comment: test comment
        regenerate: '{{ item }}'
        backend: "{{ backend }}"
      loop: "{{ regenerate_values }}"
      register: result
    - assert:
        that:
          - result is changed
          # for all values but 'always', the key should not be regenerated.
          # verify this by comparing fingerprints:
          - result.results[0].fingerprint == result.results[1].fingerprint
          - result.results[0].fingerprint == result.results[2].fingerprint
          - result.results[0].fingerprint == result.results[3].fingerprint
          - result.results[0].fingerprint != result.results[4].fingerprint
