#
# [Configuration]
# remote inputs configuration containing tls tcp, plain tcp and udp connection
#
# [Test scenario]
# 0. Run logging role.
# 1. Check the rsyslog.conf size and the file count in /etc/rsyslog.d.
# 2. Check the configured ports are opened.
#
---
- name: "Test the server configuration containing tls tcp, plain tcp and udp connection"
  hosts: all
  tags:
  # certmonger does not work in container builds
    - tests::booted
  vars:
    __test_cert_name: logging_cert
    __test_ca_cert: "/etc/pki/tls/certs/{{ __test_cert_name }}.crt"
    __test_key: "/etc/pki/tls/private/{{ __test_cert_name }}.key"
    __test_cert: "/etc/pki/tls/certs/{{ __test_cert_name }}.crt"
    __test_server_ptcp: /etc/rsyslog.d/11-input-remote-remote_ptcp.conf
    __test_server_tcp: /etc/rsyslog.d/11-input-remote-remote_tcp.conf
    __test_server_udp: /etc/rsyslog.d/11-input-remote-remote_udp.conf
    __expected_error: "Error: remote_tcp_0 and remote_tcp_1 conflict."
    __default_system_log: /var/log/messages
  tasks:
  # TEST CASE 0
  # Note: Create a self-signed cert just for the "unit" test.
  #       In the real configuration, CA cert managed by IPA is required.
    - name: "TEST CASE 0; Test the server configuration containing tls tcp, plain tcp and udp connection"
      vars:
        logging_certificates:
          - name: logging_cert
            dns: ['localhost', 'www.example.com']
            ca: self-sign
        logging_pki_files:
          - ca_cert: "{{ __test_ca_cert }}"
            cert: "{{ __test_cert }}"
            private_key: "{{ __test_key }}"
        logging_inputs:
          - name: system_input
            type: basics
          - name: remote_tcp
            type: remote
            tcp_ports: [6514, 40000, 40001]
            tls: true
            pki_authmode: x509/name
            permitted_clients:
              - '*.client.com'
              - '*.example.com'
          - name: remote_ptcp
            type: remote
            tcp_ports: [514, 40010, 40011, 40012]
          - name: remote_udp
            type: remote
            udp_ports: [514, 40020]
        logging_outputs:
          - name: files_output
            type: files
        logging_flows:
          - name: flows
            inputs: [system_input, remote_tcp, remote_ptcp, remote_udp]
            outputs: [files_output]
      include_role:
        name: fedora.linux_system_roles.logging
        public: true

  # notify Restart rsyslogd is executed at the end of this test task.
  # thus we have to force to invoke handlers
    - name: "Force all notified handlers to run at this point, not waiting for normal sync points"
      meta: flush_handlers

    - name: Ensure config file size and counts
      vars:
        __conf_count: 11
        __conf_size: less
        __conf_files:
          - "{{ __test_server_ptcp }}"
          - "{{ __test_server_tcp }}"
          - "{{ __test_server_udp }}"
        __check_systemctl_status: true
      include_tasks: tasks/check_daemon_config_files.yml

    - name: Install lsof
      package:
        name: lsof
        state: present
        use: "{{ (__logging_is_ostree | d(false)) | ternary('ansible.posix.rhel_rpm_ostree', omit) }}"

    - name: Check lsof outputs for rsyslogd
      shell: |-
        set -o pipefail
        lsof -i -nP | grep rsyslogd
      register: __result
      changed_when: false

    - name: Show lsof output
      debug:
        msg: "lsof returned {{ __result.stdout }}"

    - name: Check port 514, 6514, 40010 and 40011 is open for TCP
      shell: |-
        set -o pipefail
        lsof -i -nP | grep rsyslogd | grep TCP | grep {{ item }}
      loop: [514, 6514, 40010, 40011]
      changed_when: false

    - name: Check port 514 and 40020 is open for UDP
      shell: |-
        set -o pipefail
        lsof -i -nP | grep rsyslogd | grep UDP | grep {{ item }}
      loop: [514, 40020]
      changed_when: false

    - name: Check ports managed by firewall and selinux
      include_tasks: tasks/check_firewall_selinux.yml

    - name: END TEST CASE 0; Clean up the deployed config
      vars:
        logging_purge_confs: true
        logging_inputs: []
        logging_outputs: []
        logging_flows: []
      include_role:
        name: fedora.linux_system_roles.logging
        public: true

  # notify Restart rsyslogd is executed at the end of this test task.
  # thus we have to force to invoke handlers
    - name: "Force all notified handlers to run at this point, not waiting for normal sync points"
      meta: flush_handlers

    - name: Check ports managed by firewall and selinux
      include_tasks: tasks/check_firewall_selinux.yml

    - name: Test case 1
      block:
      # TEST CASE 1
      # remote inputs - both remote_tcp_0 and remote_tcp_1 configure
      # the tls connection.
      # Note: Create a self-signed cert just for the "unit" test.
      #       In the real configuration, CA cert managed by IPA is required.
        - name: "TEST CASE 1; Test the server configuration containing conflicted tls inputs in the remote input"
          vars:
            logging_certificates:
              - name: logging_cert
                dns: ['localhost', 'www.example.com']
                ca: self-sign
            logging_pki_files:
              - ca_cert: "{{ __test_ca_cert }}"
                cert: "{{ __test_cert }}"
                private_key: "{{ __test_key }}"
            logging_inputs:
              - name: system_input
                type: basics
              - name: remote_tcp_0
                type: remote
                tcp_ports: [6514, 40000, 40001]
                tls: true
                pki_authmode: x509/name
                permitted_clients:
                  - '*.client.com'
                  - '*.example.com'
              - name: remote_tcp_1
                type: remote
                tcp_ports: [514, 40010, 40011]
                tls: true
              - name: remote_udp
                type: remote
                udp_ports: [514, 40020]
            logging_outputs:
              - name: files_output
                type: files
            logging_flows:
              - name: flows
                inputs: [system_input, remote_tcp_0, remote_tcp_1, remote_udp]
                outputs: [files_output]
          include_role:
            name: fedora.linux_system_roles.logging

        - name: Unreachable task
          fail:
            msg: UNREACH

      rescue:
        - name: Expected error
          debug:
            msg: "{{ ansible_failed_result }}"
        - name: Ensure the expected error message is issued
          assert:
            that: item.msg is not defined or item.msg is defined and item.msg == __expected_error
          loop: "{{ ansible_failed_result.results }}"

    - name: End test case 1
      block:
        - name: END TEST CASE 1; Clean up the deployed config
          vars:
            logging_purge_confs: true
            logging_inputs: []
            logging_outputs: []
            logging_flows: []
          include_role:
            name: fedora.linux_system_roles.logging

      rescue:
        - name: Check error
          debug:
            msg: Caught an expected error - {{ ansible_failed_result }}

    - name: Stop tracking certificate
      command: getcert stop-tracking -f {{ __test_ca_cert }}
      changed_when: false

    - name: Clean up pki files
      file:
        path: "{{ item }}"
        state: absent
      loop:
        - "{{ __test_ca_cert }}"
        - "{{ __test_key }}"
        - "{{ __test_cert }}"

    - name: Assert {{ __default_system_log }}
      include_tasks: tasks/assert_varlogmessages.yml
