diff --git a/common.yml b/common.yml index 27db0eb..a567270 100644 --- a/common.yml +++ b/common.yml @@ -16,6 +16,51 @@ - name: Install python2.7 for Ansible raw: apt-get install -qq -y python2.7 + - name: Install Updates, Patches and Additional Security Software + apt: upgrade=dist update_cache=yes + + - name: Check if reboot is required + shell: > + if [[ $(readlink -f /vmlinuz) != /boot/vmlinuz-$(uname -r) ]]; then echo "required"; else echo "no"; fi + args: + executable: /bin/bash + register: reboot_required + + - name: Reboot + shell: sleep 2 && shutdown -r now "Ansible updates triggered" + async: 1 + poll: 0 + when: reboot_required is defined and reboot_required.stdout == 'required' + ignore_errors: true + + - name: Wait for shutdown + local_action: wait_for host={{ inventory_hostname }} port=22 state=stopped timeout=120 + when: reboot_required is defined and reboot_required.stdout == 'required' + + - name: Wait until SSH becomes ready... + local_action: wait_for host={{ inventory_hostname }} port=22 state=started timeout=120 + when: reboot_required is defined and reboot_required.stdout == 'required' + + # SSH fixes + + - name: SSH config + lineinfile: dest="{{ item.file }}" regexp="{{ item.regexp }}" line="{{ item.line }}" state=present + with_items: + - { regexp: '^PasswordAuthentication.*', line: 'PasswordAuthentication no', file: '/etc/ssh/sshd_config' } + - { regexp: '^PermitRootLogin.*', line: 'PermitRootLogin without-password', file: '/etc/ssh/sshd_config' } + - { regexp: '^UseDNS.*', line: 'UseDNS no', file: '/etc/ssh/sshd_config' } + - { regexp: '^Ciphers', line: 'Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes128-ctr', file: '/etc/ssh/sshd_config' } + - { regexp: '^MACs', 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,hmac-ripemd160', file: '/etc/ssh/sshd_config' } + - { regexp: '^KexAlgorithms', line: 'KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1', file: '/etc/ssh/sshd_config' } + notify: + - restart ssh + + - name: PAM config + replace: dest="{{ item.file }}" regexp="{{ item.regexp }}" replace="{{ item.line }}" + with_items: + - { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/login' } + - { regexp: '^session.*optional.*pam_motd.so.*', line: '# MOTD DISABLED', file: '/etc/pam.d/sshd' } + - name: Install tools apt: name="{{ item }}" state=latest with_items: @@ -27,59 +72,25 @@ - auditd - rsyslog - sendmail - - libpam-google-authenticator - - - name: Enable packet forwarding for IPv4 - sysctl: name=net.ipv4.ip_forward value=1 - - - name: Do not accept ICMP redirects (prevent MITM attacks) - sysctl: name=net.ipv4.conf.all.accept_redirects value=0 - - - name: Do not send ICMP redirects (we are not a router) - sysctl: name=net.ipv4.conf.all.send_redirects value=0 - - - # auditd - - - name: Collect Use of Privileged Commands - shell: > - /usr/bin/find {/usr/local/sbin,/usr/local/bin,/sbin,/bin,/usr/sbin,/usr/bin} -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=500 -F auid!=4294967295 -k privileged" }' - args: - executable: /bin/bash - register: privileged_programs - - - name: Auditd rules configured - template: src=audit.rules.j2 dest=/etc/audit/audit.rules - notify: - - restart auditd + - unattended-upgrades - - name: Auditd configured - template: src=auditd.conf.j2 dest=/etc/audit/auditd.conf - notify: - - restart auditd - - - name: Rsyslog configured - template: src=rsyslog.conf.j2 dest=/etc/rsyslog.conf - notify: - - restart rsyslog + - name: Unattended-upgrades configured + template: src=50unattended-upgrades.j2 dest=/etc/apt/apt.conf.d/50unattended-upgrades owner=root group=root mode=644 - - name: Rsyslog CIS configured - template: src=CIS.conf.j2 dest=/etc/rsyslog.d/CIS.conf owner=root group=root mode=0644 - notify: - - restart rsyslog - - - name: Enable services - service: name={{ item }} enabled=yes - with_items: - - auditd - - rsyslog - + - name: Periodic upgrades configured + template: src=10periodic.j2 dest=/etc/apt/apt.conf.d/10periodic owner=root group=root mode=644 handlers: - name: restart auditd service: name=auditd state=restarted - name: restart rsyslog - service: name=rsyslog state=restarted + service: name=rsyslog state=restarted + + - name: restart ssh + service: name=ssh state=restarted + + - name: flush routing cache + shell: echo 1 > /proc/sys/net/ipv4/route/flush \ No newline at end of file diff --git a/deploy.yml b/deploy.yml index c35b1b6..44a2bd5 100644 --- a/deploy.yml +++ b/deploy.yml @@ -2,4 +2,5 @@ - include: cloud.yml - include: common.yml +- include: security.yml - include: vpn.yml diff --git a/security.yml b/security.yml new file mode 100644 index 0000000..449645a --- /dev/null +++ b/security.yml @@ -0,0 +1,134 @@ +--- + +- name: Security fixes + hosts: vpn-host + remote_user: root + vars_files: + - config.cfg + + tasks: + # Using a two-pass approach for checking directories in order to support symlinks. + - name: Find directories for minimizing access + stat: + path: "{{ item }}" + register: minimize_access_directories + with_items: + - '/usr/local/sbin' + - '/usr/local/bin' + - '/usr/sbin' + - '/usr/bin' + - '/sbin' + - '/bin' + + - name: Minimize access + file: path='{{ item.stat.path }}' mode='go-w' recurse=yes + when: item.stat.isdir + with_items: "{{ minimize_access_directories.results }}" + no_log: True + + - name: Change shadow ownership to root and mode to 0600 + file: dest='/etc/shadow' owner=root group=root mode=0600 + + - name: change su-binary to only be accessible to user and group root + file: dest='/bin/su' owner=root group=root mode=0750 + + # auditd + + - name: Collect Use of Privileged Commands + shell: > + /usr/bin/find {/usr/local/sbin,/usr/local/bin,/sbin,/bin,/usr/sbin,/usr/bin} -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=500 -F auid!=4294967295 -k privileged" }' + args: + executable: /bin/bash + register: privileged_programs + + - name: Auditd rules configured + template: src=audit.rules.j2 dest=/etc/audit/audit.rules + notify: + - restart auditd + + - name: Auditd configured + template: src=auditd.conf.j2 dest=/etc/audit/auditd.conf + notify: + - restart auditd + + # Rsyslog + + - name: Rsyslog configured + template: src=rsyslog.conf.j2 dest=/etc/rsyslog.conf + notify: + - restart rsyslog + + - name: Rsyslog CIS configured + template: src=CIS.conf.j2 dest=/etc/rsyslog.d/CIS.conf owner=root group=root mode=0644 + notify: + - restart rsyslog + + - name: Enable services + service: name={{ item }} enabled=yes + with_items: + - auditd + - rsyslog + + # Core dumps + + - name: Restrict Core Dumps - using pam limits + lineinfile: dest=/etc/security/limits.conf line="* hard core 0" state=present + + - name: Restrict Core Dumps - using sysctl + sysctl: name=fs.suid_dumpable value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + + # Kernel fixes + + - name: Disable Source Routed Packet Acceptance + sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + with_items: + - net.ipv4.conf.all.accept_source_route + - net.ipv4.conf.default.accept_source_route + notify: + - flush routing cache + + - name: Disable ICMP Redirect Acceptance + sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + with_items: + - net.ipv4.conf.all.accept_redirects + - net.ipv4.conf.default.accept_redirects + + - name: Disable Secure ICMP Redirect Acceptance + sysctl: name="{{item}}" value=0 ignoreerrors=yes sysctl_set=yes reload=yes state=present + with_items: + - net.ipv4.conf.all.secure_redirects + - net.ipv4.conf.default.secure_redirects + notify: + - flush routing cache + + - name: Enable Bad Error Message Protection (Scored) + sysctl: name=net.ipv4.icmp_ignore_bogus_error_responses value=1 ignoreerrors=yes sysctl_set=yes reload=yes state=present + notify: + - flush routing cache + + - name: Enable RFC-recommended Source Route Validation (Scored) + sysctl: name="{{item}}" value=1 ignoreerrors=yes sysctl_set=yes reload=yes state=present + with_items: + - net.ipv4.conf.all.rp_filter + - net.ipv4.conf.default.rp_filter + notify: + - flush routing cache + + - name: Enable packet forwarding for IPv4 + sysctl: name=net.ipv4.ip_forward value=1 + + - name: Do not send ICMP redirects (we are not a router) + sysctl: name=net.ipv4.conf.all.send_redirects value=0 + + + handlers: + - name: restart auditd + service: name=auditd state=restarted + + - name: restart rsyslog + service: name=rsyslog state=restarted + + - name: flush routing cache + shell: echo 1 > /proc/sys/net/ipv4/route/flush + + \ No newline at end of file