---
- name: Install and harden SSH server on Fedora
  hosts: all
  become: yes
  vars:
    ssh_port: 22
    ssh_permit_root_login: "no"
    ssh_password_authentication: "no"
    ssh_allowed_users: [devops]
    ssh_max_auth_tries: 3
    ssh_client_alive_interval: 300
    ssh_client_alive_count_max: 3

  tasks:
    - name: Install OpenSSH server
      dnf:
        name: openssh-server
        state: present

    - name: Ensure SSH service is enabled and started
      systemd:
        name: sshd
        enabled: yes
        state: started

    - name: Configure SSH server settings
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
        state: present
        backup: yes
      loop:
        - { regexp: '^Port\s', line: "Port {{ ssh_port }}" }
        - { regexp: '^PermitRootLogin\s', line: "PermitRootLogin {{ ssh_permit_root_login }}" }
        - { regexp: '^PasswordAuthentication\s', line: "PasswordAuthentication {{ ssh_password_authentication }}" }
        - { regexp: '^MaxAuthTries\s', line: "MaxAuthTries {{ ssh_max_auth_tries }}" }
        - { regexp: '^ClientAliveInterval\s', line: "ClientAliveInterval {{ ssh_client_alive_interval }}" }
        - { regexp: '^ClientAliveCountMax\s', line: "ClientAliveCountMax {{ ssh_client_alive_count_max }}" }
        - { regexp: '^Protocol\s', line: "Protocol 2" }
        - { regexp: '^LogLevel\s', line: "LogLevel INFO" }
        - { regexp: '^X11Forwarding\s', line: "X11Forwarding no" }
        - { regexp: '^MaxStartups\s', line: "MaxStartups 10:30:60" }
        - { regexp: '^PermitEmptyPasswords\s', line: "PermitEmptyPasswords no" }
        - { regexp: '^UseDNS\s', line: "UseDNS no" }
        - { regexp: '^AllowTcpForwarding\s', line: "AllowTcpForwarding no" }
        - { regexp: '^PermitUserEnvironment\s', line: "PermitUserEnvironment no" }
        - { regexp: '^Compression\s', line: "Compression no" }
        - { regexp: '^Ciphers\s', line: "Ciphers aes256-ctr,aes192-ctr,aes128-ctr" }
        - { regexp: '^MACs\s', line: "MACs hmac-sha2-512,hmac-sha2-256" }
        - { regexp: '^KexAlgorithms\s', line: "KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256" }

    - name: Configure allowed users for SSH access
      lineinfile:
        path: /etc/ssh/sshd_config
        line: "AllowUsers {{ ssh_allowed_users | join(' ') }}"
        state: present
        backup: yes
      when: ssh_allowed_users | length > 0

    - name: Ensure SSH configuration file has correct permissions
      file:
        path: /etc/ssh/sshd_config
        owner: root
        group: root
        mode: '0600'

    - name: Ensure SSH host keys have correct permissions
      file:
        path: "{{ item }}"
        owner: root
        group: root
        mode: '0600'
      loop:
        - /etc/ssh/ssh_host_ecdsa_key
        - /etc/ssh/ssh_host_ed25519_key
        - /etc/ssh/ssh_host_rsa_key

    - name: Ensure SSH host public keys have correct permissions
      file:
        path: "{{ item }}"
        owner: root
        group: root
        mode: '0644'
      loop:
        - /etc/ssh/ssh_host_ecdsa_key.pub
        - /etc/ssh/ssh_host_ed25519_key.pub
        - /etc/ssh/ssh_host_rsa_key.pub

    - name: Configure firewalld to allow SSH on specified port
      firewalld:
        port: "{{ ssh_port }}/tcp"
        permanent: yes
        state: enabled
        immediate: yes

    - name: Disable weak SSH host key algorithms
      command: sshd -T | grep -Ei 'hostkey.*(ecdsa-sha2-nistp256|rsa-sha2-256|rsa-sha2-512)'
      register: sshd_test
      changed_when: false
      failed_when: false

    - name: Reload SSH service to apply changes
      systemd:
        name: sshd
        state: reloaded

    - name: Ensure SELinux is enforcing
      command: setenforce 1
      when: ansible_selinux.status == "enabled"
      changed_when: false

    - name: Install fail2ban for brute-force protection
      dnf:
        name: fail2ban
        state: present

    - name: Configure fail2ban SSH jail
      copy:
        content: |
          [sshd]
          enabled = true
          port = {{ ssh_port }}
          maxretry = 5
          bantime = 3600
          findtime = 600
        dest: /etc/fail2ban/jail.d/sshd.conf
        owner: root
        group: root
        mode: '0644'

    - name: Ensure fail2ban service is enabled and started
      systemd:
        name: fail2ban
        enabled: yes
        state: started

  handlers:
    - name: Reload sshd
      systemd:
        name: sshd
        state: reloaded
