---
- hosts: all
  vars:
    __sshd_test_backup_files:
      - /etc/ssh/sshd_config
      - /etc/ssh/ssh_host_rsa_key
      - /etc/ssh/ssh_host_rsa_key.pub
  tasks:
    - name: "Backup configuration files"
      ansible.builtin.include_tasks: tasks/backup.yml

    - name: Add configuration block to default configuration file
      ansible.builtin.include_role:
        name: ansible-sshd
      vars:
        sshd_config_file: /etc/ssh/sshd_config
        sshd_config_namespace: nm1
        sshd:
          PasswordAuthentication: yes
          PermitRootLogin: yes
          Match:
            Condition: user root
            AllowAgentForwarding: no

    - name: Add second configuration block to default configuration file
      ansible.builtin.include_role:
        name: ansible-sshd
      vars:
        sshd_config_file: /etc/ssh/sshd_config
        sshd_config_namespace: nm2
        sshd:
          PasswordAuthentication: no
          PermitRootLogin: no
          Match:
            Condition: Address 127.0.0.1
            AllowTcpForwarding: no

    - name: Verify the options are correctly set
      block:
        - name: Flush handlers
          ansible.builtin.meta: flush_handlers

        - name: Print current configuration file
          ansible.builtin.slurp:
            src: /etc/ssh/sshd_config
          register: config

        - name: List effective configuration using sshd -T (matching)
          ansible.builtin.shell: |
            set -eu
            if set -o | grep pipefail 2>&1 /dev/null ; then
              set -o pipefail
            fi
            if test ! -f /etc/ssh/ssh_host_rsa_key; then
              ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -C '' -N ''
            fi
            sshd -T -Cuser=root,host=localhost,addr=127.0.0.1
          register: runtime
          changed_when: false

        - name: List effective configuration using sshd -T (non-matching)
          ansible.builtin.command: sshd -T -Cuser=nobody,host=example.com,addr=127.0.0.2
          register: nonmatching
          changed_when: false

        - name: Check content of configuration file (blocks)
          ansible.builtin.assert:
            that:
              - "config.content | b64decode | regex_search('Match all\\s*PasswordAuthentication yes')"
              - "config.content | b64decode | regex_search('Match all\\s*PasswordAuthentication no')"
          when:
            - ansible_facts['os_family'] != 'RedHat' or ansible_facts['distribution_major_version'] != '6'

        - name: Check content of configuration file (blocks for RHEL 6)
          ansible.builtin.assert:
            that:
              - "config.content | b64decode | regex_search('Match address \\*\\s*PasswordAuthentication yes')"
              - "config.content | b64decode | regex_search('Match address \\*\\s*PasswordAuthentication no')"
          when:
            - ansible_facts['os_family'] == 'RedHat'
            - ansible_facts['distribution_major_version'] == '6'

        - name: Check content of configuration file
          ansible.builtin.assert:
            that:
              - "'PermitRootLogin yes' in config.content | b64decode"
              - "'PasswordAuthentication yes' in config.content | b64decode"
              - "'Match user root' in config.content | b64decode"
              - "'AllowAgentForwarding no' in config.content | b64decode"
              - "config.content | b64decode | regex_search('Match user root\\s*AllowAgentForwarding no')"
              - "'PermitRootLogin no' in config.content | b64decode"
              - "'PasswordAuthentication no' in config.content | b64decode"
              - "'Match Address 127.0.0.1' in config.content | b64decode"
              - "'AllowTcpForwarding no' in config.content | b64decode"
              - "config.content | b64decode | regex_search('Match Address 127.0.0.1\\s*AllowTcpForwarding no')"

        - name: Check the configuration values are effective
          # note, the options are in lower-case here
          ansible.builtin.assert:
            that:
              - "'permitrootlogin yes' in runtime.stdout"
              - "'allowagentforwarding no' in runtime.stdout"
              - "'allowtcpforwarding no' in runtime.stdout"
              - "'passwordauthentication yes' in runtime.stdout"

        - name: Check the configuration values are not effective for non-matching connection
          # note, the options are in lower-case here
          ansible.builtin.assert:
            that:
              - "'permitrootlogin yes' in runtime.stdout"
              - "'allowAgentforwarding no' not in nonmatching.stdout"
              - "'allowtcpforwarding no' not in nonmatching.stdout"
              - "'passwordauthentication yes' in nonmatching.stdout"
      tags: tests::verify

    - name: "Restore configuration files"
      ansible.builtin.include_tasks: tasks/restore.yml