This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
ansible:ansible_playbook_example [2024/11/05 21:51] manu |
ansible:ansible_playbook_example [2025/01/13 17:22] (current) manu [SSH config] |
||
---|---|---|---|
Line 73: | Line 73: | ||
===== Example with LPAR2RRD ===== | ===== Example with LPAR2RRD ===== | ||
+ | <cli> | ||
> my_project | > my_project | ||
> group_vars | > group_vars | ||
Line 188: | Line 188: | ||
roles: | roles: | ||
- lpar2rrd | - lpar2rrd | ||
- | + | </cli> | |
+ | |||
+ | ===== SSH config ===== | ||
+ | |||
+ | etc_ssh_sshd_config: /etc/ssh/sshd_config | ||
+ | <code> | ||
+ | - name: check if lpar2rrd exists | ||
+ | stat: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | register: __check_sshd_config_exist__ | ||
+ | |||
+ | - name: Set SSH KexAlgorithms | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | state: present | ||
+ | line: 'KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256' | ||
+ | |||
+ | - name: Set SSH Ciphers | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | state: present | ||
+ | line: 'Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr' | ||
+ | |||
+ | - name: Set SSH MACs | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | state: present | ||
+ | line: 'MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com' | ||
+ | |||
+ | - name: Set SSH loglevel to verbose | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | regexp: '^#LogLevel INFO' | ||
+ | line: 'LogLevel VERBOSE' | ||
+ | |||
+ | - name: Set log sftp level file access | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | regexp: '^Subsystem\s+sftp\s+/usr/lib/openssh/sftp-server' | ||
+ | line: 'Subsystem sftp /usr/lib/openssh/sftp-server -f AUTHPRIV -l INFO' | ||
+ | |||
+ | - name: Disable SSH root login | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | regexp: '^#PermitRootLogin' | ||
+ | line: 'PermitRootLogin no' | ||
+ | |||
+ | - name: Disable SSH password authentication | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | regexp: '^#PasswordAuthentication yes' | ||
+ | line: 'PasswordAuthentication no' | ||
+ | |||
+ | - name: Set SSH UsePrivilegeSeparation | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | state: present | ||
+ | line: 'UsePrivilegeSeparation sandbox' | ||
+ | |||
+ | - name: Set SSH AuthenticationMethods | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | state: present | ||
+ | line: 'AuthenticationMethods publickey' | ||
+ | |||
+ | # Here you should use your custom port! | ||
+ | - name: Setup alternate SSHd port | ||
+ | lineinfile: | ||
+ | dest: "{{ etc_ssh_sshd_config }}" | ||
+ | regexp: '^#Port' | ||
+ | line: 'Port 4242' | ||
+ | </code> | ||
+ | |||
+ | Using a loop: | ||
+ | <code> | ||
+ | - name: Configure sshd | ||
+ | lineinfile: | ||
+ | path: "{{ etc_ssh_sshd_config }}" | ||
+ | regex: "^(#)?{{item.key}}" | ||
+ | line: "{{item.key}} {{item.value}}" | ||
+ | state: present | ||
+ | loop: | ||
+ | - { key: "PermitRootLogin", value: "no" } | ||
+ | - { key: "PasswordAuthentication", value: "no" } | ||
+ | notify: | ||
+ | - restart sshd | ||
+ | </code> | ||
+ | |||
+ | <code> | ||
+ | - hosts: all | ||
+ | become: yes | ||
+ | become_user: root | ||
+ | become_method: sudo | ||
+ | remote_user: admin | ||
+ | |||
+ | vars: | ||
+ | syslog_facility: AUTHPRIV | ||
+ | log_level: INFO | ||
+ | |||
+ | tasks: | ||
+ | - name: Get the Active IP address | ||
+ | shell: hostname -I|cut -d " " -f1 | ||
+ | register: get_ip | ||
+ | |||
+ | - set_fact: | ||
+ | IP={{ get_ip.stdout }} | ||
+ | |||
+ | - name: Change SSH daemon configuration | ||
+ | lineinfile: | ||
+ | line: "{{ item.line }}" | ||
+ | regexp: "{{ item.regexp }}" | ||
+ | path: /etc/ssh/sshd_config | ||
+ | loop: | ||
+ | - line: 'AddressFamily inet' | ||
+ | regexp: '^(#)?AddressFamily' | ||
+ | |||
+ | - line: 'ListenAddress {{IP}}' | ||
+ | regexp: '^(#)?ListenAddress' | ||
+ | |||
+ | - line: 'SyslogFacility {{ syslog_facility }}' | ||
+ | regexp: '^(#)?SyslogFacility' | ||
+ | |||
+ | - line: 'LogLevel {{ log_level }}' | ||
+ | regexp: '^(#)?LogLevel' | ||
+ | |||
+ | - line: 'PermitRootLogin no' | ||
+ | regexp: '^(#)?PermitRootLogin' | ||
+ | |||
+ | - line: 'MaxAuthTries 3' | ||
+ | regexp: '^(#)?MaxAuthTries' | ||
+ | |||
+ | - line: 'HostbasedAuthentication no' | ||
+ | regexp: '^(#)?HostbasedAuthentication' | ||
+ | |||
+ | - line: 'IgnoreRhosts no' | ||
+ | regexp: '^(#)?IgnoreRhosts' | ||
+ | |||
+ | - line: 'PermitEmptyPasswords no' | ||
+ | regexp: '^(#)?PermitEmptyPasswords' | ||
+ | |||
+ | - line: 'PasswordAuthentication yes' | ||
+ | regexp: '^(#)?PasswordAuthentication' | ||
+ | |||
+ | - line: 'X11Forwarding no' | ||
+ | regexp: '^(#)?X11Forwarding' | ||
+ | |||
+ | - line: 'PermitUserEnvironment no' | ||
+ | regexp: '^(#)?PermitUserEnvironment' | ||
+ | |||
+ | - line: 'ClientAliveInterval 900' | ||
+ | regexp: '^(#)?ClientAliveInterval' | ||
+ | |||
+ | - line: 'ClientAliveCountMax 0' | ||
+ | regexp: '^(#)?ClientAliveCountMax' | ||
+ | |||
+ | - line: 'UseDNS no' | ||
+ | regexp: '^(#)?UseDNS' | ||
+ | |||
+ | - line: 'Banner /etc/issue.net' | ||
+ | regexp: '^(#)?Banner' | ||
+ | |||
+ | - line: 'Subsystem sftp /usr/libexec/openssh/sftp-server -f {{ syslog_facility }} -l {{ log_level }}' | ||
+ | regexp: '^(#)?Subsystem' | ||
+ | |||
+ | - name: Set secure HostKeyAlgorithms | ||
+ | lineinfile: | ||
+ | path: /etc/ssh/sshd_config | ||
+ | insertafter: '^#RekeyLimit default none' | ||
+ | line: 'HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256' | ||
+ | state: present | ||
+ | |||
+ | - name: Set secure KexAlgorithms | ||
+ | lineinfile: | ||
+ | path: /etc/ssh/sshd_config | ||
+ | insertafter: '^#RekeyLimit default none' | ||
+ | line: 'KexAlgorithms curve25519-sha256@libssh.org,curve25519-sha256,diffie-hellman-group18-sha512,diffie-hellman-group16-sha512,diffie-hellman-group14-sha256,diffie-hellman-group-exchange-sha256' | ||
+ | state: present | ||
+ | |||
+ | - name: Set secure Ciphers | ||
+ | lineinfile: | ||
+ | path: /etc/ssh/sshd_config | ||
+ | insertafter: '^#RekeyLimit default none' | ||
+ | line: 'Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr' | ||
+ | state: present | ||
+ | |||
+ | - name: Set secure MACs | ||
+ | lineinfile: | ||
+ | path: /etc/ssh/sshd_config | ||
+ | insertafter: '^#RekeyLimit default none' | ||
+ | line: 'MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com' | ||
+ | state: present | ||
+ | |||
+ | - name: Enable crypto policy on RHEL 7 | ||
+ | lineinfile: | ||
+ | path: /etc/sysconfig/sshd | ||
+ | regexp: '^' | ||
+ | insertafter: EOF | ||
+ | line: 'CRYPTO_POLICY=' | ||
+ | when: (ansible_facts['distribution'] == "RedHat" and ansible_facts['distribution_major_version'] == "7") | ||
+ | |||
+ | - name: Enable crypto policy on RHEL 8 | ||
+ | lineinfile: | ||
+ | path: /etc/sysconfig/sshd | ||
+ | regexp: '^(#)?CRYPTO_POLICY=' | ||
+ | line: 'CRYPTO_POLICY=' | ||
+ | state: present | ||
+ | when: (ansible_facts['distribution'] == "RedHat" and ansible_facts['distribution_major_version'] > "7") | ||
+ | |||
+ | - name: Create tmout.sh file | ||
+ | copy: | ||
+ | dest: /etc/profile.d/tmout.sh | ||
+ | content: | | ||
+ | TMOUT=900 | ||
+ | readonly TMOUT | ||
+ | export TMOUT | ||
+ | owner: root | ||
+ | group: root | ||
+ | mode: '0744' | ||
+ | |||
+ | - name: Update banner message | ||
+ | copy: | ||
+ | dest: /etc/issue.net | ||
+ | content: | | ||
+ | ################################################################# | ||
+ | * # | ||
+ | * This system is for the use of authorized users only. # | ||
+ | * Usage of this system monitored & recorded by system personnel.# | ||
+ | * # | ||
+ | ################################################################# | ||
+ | owner: root | ||
+ | group: root | ||
+ | mode: '0744' | ||
+ | |||
+ | - name: Restart SSHD service | ||
+ | service: | ||
+ | name: sshd | ||
+ | state: restarted | ||
+ | </code> | ||
+ | |||
+ | <code> | ||
+ | --- | ||
+ | - hosts: all | ||
+ | tasks: | ||
+ | - name: sshd configuration file update | ||
+ | blockinfile: | ||
+ | path: /etc/ssh/sshd_config | ||
+ | insertbefore: BOF # Beginning of the file | ||
+ | marker: "# {mark} ANSIBLE MANAGED BLOCK BY LINUX-ADMIN" | ||
+ | block: | | ||
+ | PermitRootLogin no | ||
+ | PubkeyAuthentication yes | ||
+ | AuthorizedKeysFile .ssh/authorized_keys | ||
+ | PasswordAuthentication no | ||
+ | backup: yes | ||
+ | validate: /usr/sbin/sshd -T -f %s | ||
+ | |||
+ | - name: Restart SSHD | ||
+ | service: | ||
+ | name: sshd | ||
+ | state: restarted | ||
+ | </code> | ||
+ | |||
+ | ===== SUDO config ===== | ||
+ | |||
+ | <code> | ||
+ | - name: Setup passwordless sudo | ||
+ | lineinfile: | ||
+ | path: /etc/sudoers | ||
+ | state: present | ||
+ | regexp: '^%sudo' | ||
+ | line: '%sudo ALL=(ALL) NOPASSWD: ALL' | ||
+ | validate: '/usr/sbin/visudo -cf %s' | ||
+ | |||
+ | - name: Create a new regular user with sudo privileges | ||
+ | user: | ||
+ | name: "{{ created_username }}" | ||
+ | state: present | ||
+ | groups: sudo | ||
+ | append: true | ||
+ | create_home: true | ||
+ | </code> | ||
+ | https://zakirpcs.medium.com/ssh-hardening-using-ansible-playbook-9717a2e3edfc |