This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
ansible:ansible_playbook_example [2023/04/06 19:52] manu created |
ansible:ansible_playbook_example [2025/01/13 17:22] (current) manu [SSH config] |
||
---|---|---|---|
Line 4: | Line 4: | ||
Install linux LAMP | Install linux LAMP | ||
+ | |||
+ | **rhel-lamp.yaml** | ||
+ | <cli> | ||
+ | --- | ||
+ | - hosts: srv-web01 | ||
+ | handlers: | ||
+ | - name: restart httpd | ||
+ | service: | ||
+ | name: httpd | ||
+ | state: restarted | ||
+ | tasks: | ||
+ | - name: 0. MàJ système | ||
+ | dnf: | ||
+ | name: "*" | ||
+ | state: latest | ||
+ | - name: 1. Installation Apache | ||
+ | dnf: | ||
+ | name: httpd | ||
+ | state: latest | ||
+ | |||
+ | - name: 2. Installation PHP | ||
+ | dnf: | ||
+ | name: php | ||
+ | state: latest | ||
+ | - name: 3. Installation extensions PHP | ||
+ | dnf: | ||
+ | name : | ||
+ | - php-pdo | ||
+ | - php-soap | ||
+ | - php-gd | ||
+ | state: latest | ||
+ | - name: 4. Installation de MariaDB | ||
+ | dnf: | ||
+ | name: mariadb-server | ||
+ | state: latest | ||
+ | - name: 5. Démarrage Apache | ||
+ | service: | ||
+ | name: httpd | ||
+ | state: started | ||
+ | enabled: yes | ||
+ | - name: 6. Démarrage MariaDB | ||
+ | service: | ||
+ | name: mariadb | ||
+ | state: started | ||
+ | enabled: yes | ||
+ | - name: 7. Installation index | ||
+ | copy: | ||
+ | src: rhel-lamp.index.php | ||
+ | dest: /var/www/html/index.php | ||
+ | owner: apache | ||
+ | group: apache | ||
+ | mode: 0644 | ||
+ | |||
+ | - name: 8. Ajout de la regle de parefeu | ||
+ | ansible.posix.firewalld: | ||
+ | zone: public | ||
+ | service: "{{ item }}" | ||
+ | permanent: yes | ||
+ | state: enabled | ||
+ | immediate: yes | ||
+ | with_items: | ||
+ | - http | ||
+ | - https | ||
+ | </cli> | ||
+ | |||
+ | |||
+ | |||
+ | ===== Example with LPAR2RRD ===== | ||
+ | |||
+ | <cli> | ||
+ | > my_project | ||
+ | > group_vars | ||
+ | > host_vars | ||
+ | > roles | ||
+ | > lpar2rrd | ||
+ | > defaults | ||
+ | main.yml | ||
+ | --- | ||
+ | lpar2rrd_version: "7.90" | ||
+ | lpar2rrd_bin: /opt/lpar2rrd/bin/lpar2rrd | ||
+ | lpar2rrd_user: lpar2rrd | ||
+ | lpar2rrd_group: "{{ lpar2rrd_user }}" | ||
+ | lpar2rrd_path: /opt/lpar2rrd | ||
+ | lpar2rrd_src: https://master.dl.sourceforge.net/project/lpar2rrd/lpar2rrd-OSagent/7.90/lpar2rrd-agent-7.90-0.noarch.rpm | ||
+ | > files | ||
+ | > handlers | ||
+ | main.yml | ||
+ | --- | ||
+ | - name: reload_daemon_and_restart_lpar2rrd-agent | ||
+ | systemd: | ||
+ | name: lpar2rrd | ||
+ | state: restarted | ||
+ | daemon_reload: yes | ||
+ | enabled: yes | ||
+ | > meta | ||
+ | > tasks | ||
+ | main.yml | ||
+ | --- | ||
+ | - name: check if lpar2rrd exists | ||
+ | stat: | ||
+ | path: "{{ lpar2rrd_bin }}" | ||
+ | register: __check_lpar2rrd_exist | ||
+ | |||
+ | - name: create lpar2rrd user | ||
+ | user: | ||
+ | name: "{{ lpar2rrd_user }}" | ||
+ | append: true | ||
+ | shell: /usr/sbin/nologin | ||
+ | system: false | ||
+ | create_home: true | ||
+ | home: /home/lpar2rrd | ||
+ | - name: create lpar2rrd dir | ||
+ | file: | ||
+ | path: "{{ lpar2rrd_path }}" | ||
+ | state: directory | ||
+ | owner: "{{ lpar2rrd_user }}" | ||
+ | group: "{{ lpar2rrd_group }}" | ||
+ | - name: download and untar lpar2rrd agent | ||
+ | unarchive: | ||
+ | src: "{{ lpar2rrd_src }}" | ||
+ | dest: /tmp/ | ||
+ | remote_src: yes | ||
+ | validate_certs: false | ||
+ | - name: move binary lpar2rrd agent | ||
+ | copy: | ||
+ | src: "/tmp/{{ }}" | ||
+ | dest: "{{ lpar2rrd_path }}" | ||
+ | owner: "{{ lpar2rrd_user }}" | ||
+ | group: "{{ lpar2rrd_group }}" | ||
+ | mode: 0755 | ||
+ | remote_src: yes | ||
+ | when: __check_lpar2rrd_exist.stat.exists == false | ||
+ | - name: cleanup | ||
+ | file: | ||
+ | path: "/tmp/lpar2rrd*" | ||
+ | state: absent | ||
+ | - name: install template | ||
+ | template: | ||
+ | src: lpar2rrd-agent.service.j2 | ||
+ | dest: /etc/systemd/system/lpar2rrd-agent.service | ||
+ | owner: root | ||
+ | group: root | ||
+ | mode: 0755 | ||
+ | notify: reload_daemon_and_restart_lpar2rrd-agent | ||
+ | - meta: flush_handlers | ||
+ | | ||
+ | - name: service always start | ||
+ | systemd: | ||
+ | name: lpar2rrd | ||
+ | state: started | ||
+ | enabled: yes | ||
+ | | ||
+ | | ||
+ | > templates | ||
+ | lpar2rrd-agent.service.j2 | ||
+ | [Unit] | ||
+ | Description=lpar2rrd agent | ||
+ | After=network-online.target | ||
+ | | ||
+ | [Service] | ||
+ | User={{ lpar2rrd_user }} | ||
+ | Group={{ lpar2rrd_group }} | ||
+ | Type=simple | ||
+ | ExecStart={{ lpar2rrd_bin }} | ||
+ | | ||
+ | [Install] | ||
+ | WantedBy=multi-user.target | ||
+ | |||
+ | |||
+ | > tests | ||
+ | > vars | ||
+ | 00_inventory.yml | ||
+ | all: | ||
+ | vars: | ||
+ | ansible_python_interpreter: /usr/bin/python3.9 | ||
+ | hosts: | ||
+ | 10.10.10.1: | ||
+ | 10.10.10.2: | ||
+ | playbook.yml | ||
+ | - name: install lpar2rrd agent | ||
+ | hosts: all | ||
+ | become: yes | ||
+ | roles: | ||
+ | - 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 |