This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
ansible:ansible_sandbox [2024/10/02 18:25] manu |
ansible:ansible_sandbox [2025/05/28 10:28] (current) manu [Test 4 insertafter using bash] |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Ansible sanbox ====== | ====== Ansible sanbox ====== | ||
| + | |||
| + | ===== Test 1 ===== | ||
| Script shell to start the playbook | Script shell to start the playbook | ||
| Line 40: | Line 42: | ||
| <code> | <code> | ||
| ansible.cfg | ansible.cfg | ||
| - | .vaultPwd.yml | + | .vaultPwd.yml --> password clear for vault |
| + | download_file.yml | ||
| </code> | </code> | ||
| + | |||
| + | |||
| + | |||
| + | |||
| <code> | <code> | ||
| # cat ansible.cfg | grep -v '^#' | sed '/^$/d' | # cat ansible.cfg | grep -v '^#' | sed '/^$/d' | ||
| Line 68: | Line 76: | ||
| linux02 | linux02 | ||
| </code> | </code> | ||
| + | |||
| + | ===== Test 2 with roles ===== | ||
| + | |||
| + | Execute only one role | ||
| + | ansible-playbook setup.yml -i inventory.ini --tags "common" | ||
| + | |||
| + | setup.yml | ||
| + | <code> | ||
| + | --- | ||
| + | - hosts: prod | ||
| + | vars_files: | ||
| + | - group_vars/all.yml | ||
| + | - group_vars/main.yml | ||
| + | - group_vars/docker.yml | ||
| + | - group_vars/monit.yml | ||
| + | - group_vars/networking.yml | ||
| + | - group_vars/vault.yml | ||
| + | user: "{{default_username}}" # run whole script with default user | ||
| + | become: yes | ||
| + | roles: # order is not random! | ||
| + | - role: nickjj.fail2ban | ||
| + | tags: fail2ban | ||
| + | - role: common | ||
| + | tags: common | ||
| + | - role: ufw | ||
| + | tags: ufw | ||
| + | - role: user | ||
| + | tags: user | ||
| + | - role: ssh | ||
| + | tags: ssh | ||
| + | - role: nickjj.docker | ||
| + | when: install_docker == true | ||
| + | tags: docker | ||
| + | - role: docker | ||
| + | when: install_docker == true | ||
| + | tags: docker | ||
| + | - role: jnv.debian-backports | ||
| + | tags: common | ||
| + | - role: ansible-monit | ||
| + | tags: common | ||
| + | - role: jnv.unattended-upgrades | ||
| + | tags: common | ||
| + | - role: networking | ||
| + | tags: networking | ||
| + | - role: reboot | ||
| + | tags: reboot | ||
| + | </code> | ||
| + | |||
| + | cat group_vars/main.yml | ||
| + | <code> | ||
| + | sshpub_location: SSH_PUBKEY_HERE #the full path to your SSH public key ( e.g. /Users/username/.ssh/id_ed25519.pub ) | ||
| + | root_pw: "PASSWORD_HERE" #root password that should be set | ||
| + | user_name: USERNAME_HERE #username for the created user | ||
| + | user_pw: "PASSWORD_HERE" #password for the new user | ||
| + | ssh_port: 55899 #port number for ssh | ||
| + | mail_to: mailto@example.com #the mail address where mails should be sent to | ||
| + | mail_from: mailfrom@example.com #the mail address where mails are sent from | ||
| + | mail_smtp_server: smtp.example.com #mail server, e.g. smtp.gmail.com | ||
| + | mail_pw: PASSWORD_HERE #password for the mail_from mail address | ||
| + | mail_port: 587 #the port where mails are sent to the mail server, e.g. 587 | ||
| + | </code> | ||
| + | |||
| + | cat group_vars/all.yml | ||
| + | <code> | ||
| + | --- | ||
| + | # general settings | ||
| + | default_username: debian | ||
| + | dot_forward_email: <YOUR_EMAIL_GOES_HERE> | ||
| + | private_key: .ssh/id_rsa | ||
| + | public_key: .ssh/id_rsa.pub | ||
| + | ntpserver: pool.ntp.org | ||
| + | timezone: Europe/Rome | ||
| + | |||
| + | # default sshd port | ||
| + | sshd_port: 22 | ||
| + | |||
| + | # generate random passwords for default user and root user | ||
| + | default_password: "{{lookup('password', '/dev/null length=15 chars=ascii_letters,digits,punctuation')}}" | ||
| + | root_password: "{{lookup('password', '/dev/null length=15 chars=ascii_letters,digits,punctuation')}}" | ||
| + | |||
| + | # unattended packages install configuration | ||
| + | unattended_mail: "{{dot_forward_email}}" | ||
| + | unattended_remove_unused_dependencies: true | ||
| + | unattended_automatic_reboot_time: "03:00" | ||
| + | unattended_update_days: "Sat" | ||
| + | unattended_clean_interval: 7 | ||
| + | |||
| + | # fail2ban | ||
| + | fail2ban_loglevel: INFO | ||
| + | fail2ban_services: | ||
| + | - name: ssh | ||
| + | port: ssh | ||
| + | filter: sshd | ||
| + | logpath: /var/log/auth.log | ||
| + | </code> | ||
| + | |||
| + | cat roles/ssh/tasks/main.yml | ||
| + | <code> | ||
| + | - name: secure ssh configuration | ||
| + | become: true | ||
| + | blockinfile: | ||
| + | path: /etc/ssh/sshd_config | ||
| + | block: | | ||
| + | ######################################################################################################## | ||
| + | # start settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01 | ||
| + | ######################################################################################################## | ||
| + | # Supported HostKey algorithms by order of preference. | ||
| + | HostKey /etc/ssh/ssh_host_ed25519_key | ||
| + | HostKey /etc/ssh/ssh_host_rsa_key | ||
| + | HostKey /etc/ssh/ssh_host_ecdsa_key | ||
| + | KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256 | ||
| + | Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr | ||
| + | MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com | ||
| + | # LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in. | ||
| + | LogLevel VERBOSE | ||
| + | # Use kernel sandbox mechanisms where possible in unprivileged processes | ||
| + | # Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere. | ||
| + | # Note: This setting is deprecated in OpenSSH 7.5 (https://www.openssh.com/txt/release-7.5) | ||
| + | # UsePrivilegeSeparation sandbox | ||
| + | ######################################################################################################## | ||
| + | # end settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01 | ||
| + | ######################################################################################################## | ||
| + | # don't let users set environment variables | ||
| + | PermitUserEnvironment no | ||
| + | # only use the newer, more secure protocol | ||
| + | Protocol 2 | ||
| + | # disable port forwarding | ||
| + | AllowTcpForwarding no | ||
| + | AllowStreamLocalForwarding no | ||
| + | GatewayPorts no | ||
| + | PermitTunnel no | ||
| + | # don't allow login if the account has an empty password | ||
| + | PermitEmptyPasswords no | ||
| + | # ignore .rhosts and .shosts | ||
| + | IgnoreRhosts yes | ||
| + | # verify hostname matches IP | ||
| + | UseDNS yes | ||
| + | Compression no | ||
| + | TCPKeepAlive no | ||
| + | AllowAgentForwarding no | ||
| + | # don't allow .rhosts or /etc/hosts.equiv | ||
| + | HostbasedAuthentication no | ||
| + | notify: restart ssh service | ||
| + | |||
| + | - name: secure ssh configuration part 2 | ||
| + | become: true | ||
| + | lineinfile: | ||
| + | dest: /etc/ssh/sshd_config | ||
| + | regexp: "{{ item.regexp }}" | ||
| + | line: "{{ item.line }}" | ||
| + | loop: | ||
| + | - { regexp: '^AllowGroups', line: 'AllowGroups sshusers' } | ||
| + | - { regexp: '^ClientAliveCountMax', line: 'ClientAliveCountMax 0'} | ||
| + | - { regexp: '^ClientAliveInterval', line: 'ClientAliveInterval 300'} | ||
| + | - { regexp: '^ListenAddress', line: 'ListenAddress 0.0.0.0'} | ||
| + | - { regexp: '^LoginGraceTime', line: 'LoginGraceTime 30'} | ||
| + | - { regexp: '^MaxAuthTries', line: 'MaxAuthTries 2'} | ||
| + | - { regexp: '^MaxSessions', line: 'MaxSessions 2'} | ||
| + | - { regexp: '^MaxStartups', line: 'MaxStartups 2'} | ||
| + | - { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no'} | ||
| + | - { regexp: '^Port', line: 'Port {{ ssh_port }}'} | ||
| + | - { regexp: '^PermitRootLogin', line: 'PermitRootLogin no'} | ||
| + | - { regexp: '^X11Forwarding', line: 'X11Forwarding no'} | ||
| + | - { regexp: '^Subsystem', line: 'Subsystem sftp internal-sftp -f AUTHPRIV -l INFO'} | ||
| + | notify: restart ssh service | ||
| + | |||
| + | - name: remove short diffie diffie-hellman | ||
| + | become: true | ||
| + | shell: | | ||
| + | awk '$5 >= 3071' /etc/ssh/moduli | sudo tee /etc/ssh/moduli.tmp | ||
| + | mv /etc/ssh/moduli.tmp /etc/ssh/moduli | ||
| + | notify: restart ssh service | ||
| + | </code> | ||
| + | |||
| + | cat roles/ssh/handlers/main.yml | ||
| + | <code> | ||
| + | - name: restart ssh service | ||
| + | become: yes | ||
| + | service: | ||
| + | name: ssh | ||
| + | state: restarted | ||
| + | </code> | ||
| + | |||
| + | cat roles/others/tasks/main.yml | ||
| + | <code> | ||
| + | - name: include Debian.yml | ||
| + | include_tasks: Debian.yml | ||
| + | when: ansible_os_family == 'Debian' | ||
| + | - name: include RedHat.yml | ||
| + | include_tasks: RedHat.yml | ||
| + | when: ansible_os_family == 'RedHat' | ||
| + | </code> | ||
| + | |||
| + | cat roles/others/tasks/Debian.yml | ||
| + | <code> | ||
| + | - name: install others | ||
| + | apt: | ||
| + | name: ['bash-completion', 'htop', 'rsync', 'tmux', 'nmap', 'netcat-openbsd', 'gawk'] | ||
| + | state: present | ||
| + | when: ansible_os_family == 'Debian' | ||
| + | </code> | ||
| + | |||
| + | cat roles/others/tasks/Redhat.yml | ||
| + | <code> | ||
| + | - name: install others | ||
| + | yum: name={{ item }} state=present | ||
| + | when: ansible_os_family == 'Redhat' | ||
| + | with_items: | ||
| + | - bash-completion | ||
| + | - tig | ||
| + | - wget | ||
| + | - htop | ||
| + | - rsync | ||
| + | - tmux | ||
| + | - nmap | ||
| + | - nmap-ncat | ||
| + | </code> | ||
| + | |||
| + | ===== Test 3 backup file ===== | ||
| + | |||
| + | |||
| + | | ||
| + | File is backuped with format **2025-02-23T14:30:00Z** | ||
| + | <cli prompt='#'> | ||
| + | --- | ||
| + | - name: Backup file if it exists | ||
| + | hosts: localhost | ||
| + | tasks: | ||
| + | - name: Check if the file exists | ||
| + | stat: | ||
| + | path: /path/to/your/file | ||
| + | register: file_stat | ||
| + | |||
| + | - name: Create a backup if the file exists | ||
| + | copy: | ||
| + | src: /path/to/your/file | ||
| + | dest: "/path/to/backup/file_{{ ansible_date_time.iso8601 }}.bak" | ||
| + | remote_src: yes | ||
| + | when: file_stat.stat.exists | ||
| + | </cli> | ||
| + | |||
| + | Backup only if modified | ||
| + | <cli prompt='#'> | ||
| + | --- | ||
| + | - name: Backup file if it is different | ||
| + | hosts: localhost | ||
| + | tasks: | ||
| + | - name: Get the checksum of the current file | ||
| + | stat: | ||
| + | path: /path/to/your/file | ||
| + | register: file_stat | ||
| + | |||
| + | - name: Get the checksum of the last backup (if exists) | ||
| + | stat: | ||
| + | path: "/path/to/backup/file_last.bak" | ||
| + | register: backup_stat | ||
| + | ignore_errors: yes | ||
| + | |||
| + | - name: Compare the current file checksum with the backup checksum | ||
| + | command: "sha256sum /path/to/your/file | awk '{ print $1 }'" | ||
| + | register: current_checksum | ||
| + | when: file_stat.stat.exists | ||
| + | |||
| + | - name: Compare the backup checksum (if backup exists) | ||
| + | command: "sha256sum /path/to/backup/file_last.bak | awk '{ print $1 }'" | ||
| + | register: backup_checksum | ||
| + | when: backup_stat.stat.exists | ||
| + | |||
| + | - name: Backup the file if checksums are different | ||
| + | copy: | ||
| + | src: /path/to/your/file | ||
| + | dest: "/path/to/backup/file_{{ ansible_date_time.iso8601 }}.bak" | ||
| + | remote_src: yes | ||
| + | when: | ||
| + | - file_stat.stat.exists | ||
| + | - (backup_stat.stat.exists == false or current_checksum.stdout != backup_checksum.stdout) | ||
| + | </cli> | ||
| + | |||
| + | ===== Test 4 insertafter using bash ===== | ||
| + | |||
| + | <cli> | ||
| + | --- | ||
| + | - name: Insert line after pattern using bash | ||
| + | hosts: all | ||
| + | become: true | ||
| + | tasks: | ||
| + | - name: Insert line after pattern using sed | ||
| + | shell: | | ||
| + | if ! grep -q '^new_config_line=value$' /etc/example.conf; then | ||
| + | sed -i '/# INSERT HERE/a new_config_line=value' /etc/example.conf | ||
| + | fi | ||
| + | args: | ||
| + | executable: /bin/bash | ||
| + | </cli> | ||
| + | |||
| + | https://stackoverflow.com/questions/70162334/in-ansible-how-do-i-add-a-line-without-delete-comment | ||
| + | |||
| + | https://www.theunixschool.com/2012/06/insert-line-before-or-after-pattern.html | ||
| + | |||
| + | |||