diff options
Diffstat (limited to 'roles/common/tasks')
-rw-r--r-- | roles/common/tasks/apt.yml | 12 | ||||
-rw-r--r-- | roles/common/tasks/bacula.yml | 92 | ||||
-rw-r--r-- | roles/common/tasks/clamav.yml | 26 | ||||
-rw-r--r-- | roles/common/tasks/fail2ban.yml | 49 | ||||
-rw-r--r-- | roles/common/tasks/firewall.yml | 49 | ||||
-rw-r--r-- | roles/common/tasks/haveged.yml | 5 | ||||
-rw-r--r-- | roles/common/tasks/ipsec.yml | 93 | ||||
-rw-r--r-- | roles/common/tasks/logging.yml | 13 | ||||
-rw-r--r-- | roles/common/tasks/mail.yml | 107 | ||||
-rw-r--r-- | roles/common/tasks/main.yml | 114 | ||||
-rw-r--r-- | roles/common/tasks/munin-node.yml | 121 | ||||
-rw-r--r-- | roles/common/tasks/ntp.yml | 32 | ||||
-rw-r--r-- | roles/common/tasks/resolved.yml | 36 | ||||
-rw-r--r-- | roles/common/tasks/rkhunter.yml | 5 | ||||
-rw-r--r-- | roles/common/tasks/samhain.yml | 26 | ||||
-rw-r--r-- | roles/common/tasks/smart.yml | 7 | ||||
-rw-r--r-- | roles/common/tasks/stunnel.yml | 16 | ||||
-rw-r--r-- | roles/common/tasks/sysctl.yml | 19 | ||||
-rw-r--r-- | roles/common/tasks/unbound.yml | 21 |
19 files changed, 452 insertions, 391 deletions
diff --git a/roles/common/tasks/apt.yml b/roles/common/tasks/apt.yml index f444315..8df3e8f 100644 --- a/roles/common/tasks/apt.yml +++ b/roles/common/tasks/apt.yml @@ -1,49 +1,43 @@ - name: Install various APT tools - apt: pkg={{ item }} - with_items: + apt: pkg={{ packages }} + vars: + packages: - apt - apt-listchanges - apt-show-versions - debian-archive-keyring - debian-goodies - needrestart - unattended-upgrades - debfoster - deborphan - - debsecan - debsums - name: Configure APT (1) template: src=etc/apt/{{ item }}.j2 dest=/etc/apt/{{ item }} owner=root group=root mode=0644 with_items: - sources.list - preferences notify: - apt-get update - name: Configure APT (2) copy: src=etc/apt/{{ item }} dest=/etc/apt/{{ item }} owner=root group=root mode=0644 with_items: - listchanges.conf - apt.conf.d/10periodic - apt.conf.d/50unattended-upgrades -- name: Configure the Debian Security Analyzer - template: src=etc/default/debsecan.j2 - dest=/etc/default/debsecan - owner=root group=root - mode=0644 - - name: Start cron service: name=cron state=started tags: - cron # We should run 'apt-get update' before proceeding to any other task. - meta: flush_handlers diff --git a/roles/common/tasks/bacula.yml b/roles/common/tasks/bacula.yml index 248d47d..308e358 100644 --- a/roles/common/tasks/bacula.yml +++ b/roles/common/tasks/bacula.yml @@ -1,111 +1,33 @@ -- name: Install stunnel - apt: pkg=stunnel4 - -- name: Auto-enable stunnel - lineinfile: dest=/etc/default/stunnel4 - regexp='^(\s*#)?\s*ENABLED=' - line='ENABLED=1' - owner=root group=root - mode=0644 - -- name: Create /etc/stunnel/certs - file: path=/etc/stunnel/certs - state=directory - owner=root group=root - mode=0755 - -- name: Generate a private key and a X.509 certificate for Bacula FD - command: genkeypair.sh x509 - --pubkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-fd.pem - --privkey=/etc/stunnel/certs/{{ inventory_hostname_short }}-fd.key - --ou=BaculaFD --cn={{ inventory_hostname }} --dns={{ inventory_hostname }} - -t rsa -b 4096 -h sha512 - register: r1 - changed_when: r1.rc == 0 - failed_when: r1.rc > 1 - notify: - - Restart stunnel - tags: - - genkey - -- name: Fetch Bacula FD X.509 certificate - # Ensure we don't fetch private data - sudo: False - fetch: src=/etc/stunnel/certs/{{ inventory_hostname_short }}-fd.pem - dest=certs/bacula/ - fail_on_missing=yes - flat=yes - tags: - - genkey - -- name: Copy Bacula Dir X.509 certificates - assemble: src=certs/bacula regexp="-dir\.pem$" remote_src=no - dest=/etc/stunnel/certs/bacula-dirs.pem - owner=root group=root - mode=0644 - register: r2 - when: "'bacula-dir' not in group_names" - notify: - - Restart stunnel - -- name: Copy Bacula SD X.509 certificates - copy: src=certs/bacula/{{ hostvars[item].inventory_hostname_short }}-sd.pem - dest=/etc/stunnel/certs/ - owner=root group=root - mode=0644 - register: r3 - with_items: groups['bacula-sd'] | difference([inventory_hostname]) - notify: - - Restart stunnel - -- name: Configure stunnel - template: src=etc/stunnel/bacula-fd.conf.j2 - dest=/etc/stunnel/bacula-fd.conf - owner=root group=root - mode=0644 - register: r4 - when: "'bacula-dir' not in group_names or 'bacula-sd' not in group_names" - notify: - - Restart stunnel - -- name: Start stunnel - service: name=stunnel4 pattern=/usr/bin/stunnel4 state=started - when: not (r1.changed or r2.changed or r3.changed or r4.changed) - -- meta: flush_handlers - - - - name: Install bacula-fd apt: pkg=bacula-fd - name: Create /var/lib/bacula/tmp file: path=/var/lib/bacula/tmp state=directory owner=root group=root mode=0700 - name: Delete /etc/bacula/common_default_passwords file: path=/etc/bacula/common_default_passwords state=absent -# Create with: +# Populate with: # echo $director-dir $(pwgen -sn 64 1) | sudo tee -a /etc/bacula/passwords-fd - name: Ensure /etc/bacula/passwords-fd exists file: path=/etc/bacula/passwords-fd state=file owner=root group=root mode=0600 - name: Configure bacula template: src=etc/bacula/bacula-fd.conf.j2 dest=/etc/bacula/bacula-fd.conf owner=root group=root mode=0644 notify: - Restart bacula-fd - name: Create /etc/bacula/ssl file: path=/etc/bacula/ssl state=directory owner=root group=root mode=0755 @@ -115,36 +37,42 @@ --pubkey=/etc/bacula/ssl/{{ inventory_hostname_short }}.pem --privkey=/etc/bacula/ssl/{{ inventory_hostname_short }}.pem --ou=BaculaFD --cn={{ inventory_hostname }} --dns={{ inventory_hostname }} -t rsa -b 4096 -h sha512 register: r changed_when: r.rc == 0 failed_when: r.rc > 1 notify: - Restart bacula-fd tags: - genkey - name: Copy the master public key for data encryption copy: src=certs/bacula/data-master.pem dest=/etc/bacula/ssl/master.pem owner=root group=root mode=0644 tags: - genkey -- name: Copy bacula-fd.service - copy: src=lib/systemd/system/bacula-fd.service - dest=/lib/systemd/system/bacula-fd.service +- name: Create /etc/systemd/system/bacula-fd.service.d + file: path=/etc/systemd/system/bacula-fd.service.d + state=directory + owner=root group=root + mode=0755 + +- name: Copy bacula-fd.service override + copy: src=etc/systemd/system/bacula-fd.service.d/override.conf + dest=/etc/systemd/system/bacula-fd.service.d/override.conf owner=root group=root mode=0644 notify: - systemctl daemon-reload - Restart bacula-fd - meta: flush_handlers - name: Enable bacula-fd service: name=bacula-fd enabled=yes - name: Start bacula-fd service: name=bacula-fd state=started diff --git a/roles/common/tasks/clamav.yml b/roles/common/tasks/clamav.yml index e1ece0d..437387b 100644 --- a/roles/common/tasks/clamav.yml +++ b/roles/common/tasks/clamav.yml @@ -1,22 +1,32 @@ - name: Install ClamAV - apt: pkg={{ item }} - with_items: + apt: pkg={{ packages }} + vars: + packages: - clamav - clamav-daemon - clamav-freshclam - name: Configure FreshClam - lineinfile: "dest=/etc/clamav/freshclam.conf - line='DatabaseMirror {{ item }}'" - with_items: - - db.local.clamav.net - - database.clamav.net - - db.other.clamav.net + template: src=etc/clamav/freshclam.conf.j2 + dest=/etc/clamav/freshclam.conf + owner=clamav group=adm + mode=0444 + tags: freshclam notify: - Restart freshclam - name: Start ClamAV service: name={{ item }} state=started with_items: - clamav-daemon - clamav-freshclam + +- name: Add a 'clamav' alias + lineinfile: dest=/etc/aliases create=yes + regexp="^clamav{{':'}} " + line="clamav{{':'}} root" + +- name: Compile the static local Postfix database + postmap: cmd=postalias src=/etc/aliases db=lmdb + owner=root group=root + mode=0644 diff --git a/roles/common/tasks/fail2ban.yml b/roles/common/tasks/fail2ban.yml index be26c79..563075f 100644 --- a/roles/common/tasks/fail2ban.yml +++ b/roles/common/tasks/fail2ban.yml @@ -1,28 +1,63 @@ - name: Install fail2ban apt: pkg=fail2ban -- name: Add addititional filters - copy: src=etc/fail2ban/filter.d/{{ item }} - dest=/etc/fail2ban/filter.d/{{ item }} +- name: Configure fail2ban (fail2ban.local) + copy: src=etc/fail2ban/fail2ban.local + dest=/etc/fail2ban/fail2ban.local owner=root group=root mode=0644 register: r1 - with_items: - - roundcube.conf notify: - Restart fail2ban -- name: Configure fail2ban +- name: Configure fail2ban (jail.local) template: src=etc/fail2ban/jail.local.j2 dest=/etc/fail2ban/jail.local owner=root group=root mode=0644 register: r2 notify: - Restart fail2ban +- name: Configure fail2ban (action.d/nftables-allports.local) + copy: src=etc/fail2ban/action.d/nftables-allports.local + dest=/etc/fail2ban/action.d/nftables-allports.local + owner=root group=root + mode=0644 + register: r3 + notify: + - Restart fail2ban + +- name: Copy filters + copy: src=etc/fail2ban/filter.d/ + dest=/etc/fail2ban/filter.d/ + owner=root group=root + mode=0644 + register: r4 + notify: + - Restart fail2ban + +- name: Create directory /etc/systemd/system/fail2ban.service.d + file: path=/etc/systemd/system/fail2ban.service.d + state=directory + owner=root group=root + mode=0755 + +- name: Harden fail2ban.service + copy: src=etc/systemd/system/fail2ban.service.d/override.conf + dest=/etc/systemd/system/fail2ban.service.d/override.conf + owner=root group=root + mode=0644 + register: r5 + notify: + - systemctl daemon-reload + - Restart fail2ban + - name: Start fail2ban service: name=fail2ban state=started - when: not (r1.changed or r2.changed) + when: not (r1.changed or r2.changed or r3.changed or r4.changed or r5.changed) - meta: flush_handlers + +- name: Delete /var/lib/fail2ban/fail2ban.sqlite3 + file: path=/var/lib/fail2ban/fail2ban.sqlite3 state=absent diff --git a/roles/common/tasks/firewall.yml b/roles/common/tasks/firewall.yml index 29c0e2b..30f4fa9 100644 --- a/roles/common/tasks/firewall.yml +++ b/roles/common/tasks/firewall.yml @@ -1,40 +1,27 @@ -- name: Install some packages required for the firewall - apt: pkg={{ item }} - with_items: - - iptables - - netmask - - bsdutils +- name: Install nftables + apt: pkg=nftables -- name: Create directory /etc/iptables - file: path=/etc/iptables - state=directory - owner=root group=root +- name: Copy /usr/local/sbin/update-firewall + copy: src=usr/local/sbin/update-firewall + dest=/usr/local/sbin/update-firewall + owner=root group=staff mode=0755 -- name: Generate /etc/iptables/services - template: src=etc/iptables/services.j2 - dest=/etc/iptables/services +- name: Copy /etc/nftables.conf + template: src=etc/nftables.conf.j2 + dest=/etc/nftables.conf owner=root group=root - mode=0600 - -- name: Copy /usr/local/sbin/update-firewall.sh - copy: src=usr/local/sbin/update-firewall.sh - dest=/usr/local/sbin/update-firewall.sh - owner=root group=root - mode=0755 - -- name: Make the rulesets persistent - copy: src=etc/network/{{ item }} - dest=/etc/network/{{ item }} - owner=root group=root - mode=0755 - with_items: - - if-pre-up.d/iptables - - if-post-down.d/iptables + mode=0644 - name: Ensure the firewall is up to date - command: /usr/local/sbin/update-firewall.sh -c + command: /usr/local/sbin/update-firewall -c register: rv # A non-zero return value will make ansible stop and show stderr. This # is what we want. - changed_when: rv.rc + changed_when: rv.rc != 0 + +- name: Enable nftables.service + service: name=nftables enabled=yes + +- name: Start nftables.service + service: name=nftables state=started diff --git a/roles/common/tasks/haveged.yml b/roles/common/tasks/haveged.yml deleted file mode 100644 index 3f03a28..0000000 --- a/roles/common/tasks/haveged.yml +++ /dev/null @@ -1,5 +0,0 @@ -- name: Install haveged - apt: pkg=haveged - -- name: Start haveged - service: name=haveged state=started diff --git a/roles/common/tasks/ipsec.yml b/roles/common/tasks/ipsec.yml new file mode 100644 index 0000000..917c687 --- /dev/null +++ b/roles/common/tasks/ipsec.yml @@ -0,0 +1,93 @@ +- name: Install strongSwan + apt: pkg={{ packages }} + vars: + packages: + - strongswan-charon + - strongswan-starter + # for the GCM and openssl plugins + - libstrongswan-standard-plugins + notify: + - Update firewall + - Restart IPsec + +- name: Auto-create a dedicated virtual subnet for IPsec + template: src=etc/network/if-up.d/ipsec.j2 + dest=/etc/network/if-up.d/ipsec + owner=root group=root + mode=0755 + +- name: Auto-deactivate the dedicated virtual subnet for IPsec + file: src=../if-up.d/ipsec + dest=/etc/network/if-down.d/ipsec + owner=root group=root state=link force=yes + + +- name: Configure IPsec + template: src=etc/ipsec.conf.j2 + dest=/etc/ipsec.conf + owner=root group=root + mode=0644 + register: r1 + notify: + - Restart IPsec + +- name: Configure IPsec's secrets + template: src=etc/ipsec.secrets.j2 + dest=/etc/ipsec.secrets + owner=root group=root + mode=0600 + register: r2 + notify: + - Restart IPsec + +- name: Configure Charon + copy: src=etc/strongswan.d/{{ item }} + dest=/etc/strongswan.d/{{ item }} + owner=root group=root + mode=0644 + with_items: + - charon.conf + - charon/socket-default.conf + register: r3 + notify: + - Restart IPsec + +- name: Generate a key pair for IPsec public key authentication + command: genkeypair.sh keypair + --pubkey=/etc/ipsec.d/certs/{{ inventory_hostname_short }}.pem + --privkey=/etc/ipsec.d/private/{{ inventory_hostname_short }}.key + -t rsa -b 4096 + register: r4 + changed_when: r4.rc == 0 + failed_when: r4.rc > 1 + notify: + - Restart IPsec + tags: + - genkey + +- name: Fetch the public part of IPsec host key + # Ensure we don't fetch private data + become: False + fetch: src=/etc/ipsec.d/certs/{{ inventory_hostname_short }}.pem + dest=certs/ipsec/{{ inventory_hostname_short }}.pem + fail_on_missing=yes flat=yes + tags: + - genkey + +# Don't copy our pubkey due to a possible race condition. Only the +# remote machine has authority regarding its key. +- name: Copy the public part of IPsec peers' key + copy: src=certs/ipsec/{{ hostvars[item].inventory_hostname_short }}.pem + dest=/etc/ipsec.d/certs/{{ hostvars[item].inventory_hostname_short }}.pem + owner=root group=root + mode=0644 + with_items: "{{ groups.all | difference([inventory_hostname]) }}" + register: r5 + tags: + - genkey + notify: + - Restart IPsec + +- name: Start IPsec + service: name=ipsec state=started + when: not (r1.changed or r2.changed or r3.changed or r4.changed or r5.changed) diff --git a/roles/common/tasks/logging.yml b/roles/common/tasks/logging.yml index 3b86294..699c6e3 100644 --- a/roles/common/tasks/logging.yml +++ b/roles/common/tasks/logging.yml @@ -1,82 +1,83 @@ - name: Install logging server & utilities - apt: pkg={{ item }} - with_items: + apt: pkg={{ packages }} + vars: + packages: - rsyslog - - syslog-summary - logcheck - logcheck-database - logrotate - name: Configure rsyslog copy: src=etc/rsyslog.conf dest=/etc/rsyslog.conf owner=root group=root mode=0644 register: r1 notify: - Restart rsyslog tags: - syslog - name: Configure postfix's custom rsyslog rules template: src=etc/rsyslog.d/postfix.conf.j2 dest=/etc/rsyslog.d/postfix.conf owner=root group=root mode=0644 register: r2 notify: - Restart rsyslog tags: - syslog - name: Start rsyslog service: name=rsyslog state=started when: not (r1.changed or r2.changed) tags: - syslog - meta: flush_handlers - name: Configure logcheck (1) copy: src=etc/logcheck/{{ item }} dest=/etc/logcheck/{{ item }} - owner=root group=logcheck + owner=root group=root mode=0644 with_items: - logcheck.conf - ignore.d.server/common-local - ignore.d.server/dovecot-local - ignore.d.server/postfix-local + - ignore.d.server/strongswan-local # logcheck-sudo already exists, but changing the filename for our # local modifications would defeat the ruleset - violations.ignore.d/logcheck-sudo tags: - logcheck - name: Configure logcheck (2) lineinfile: dest=/etc/logcheck/logcheck.logfiles line={{ item }} state=present create=yes - owner=root group=logcheck - mode=0640 + owner=root group=root + mode=0644 with_items: - /var/log/syslog - /var/log/auth.log - /var/log/mail.log tags: - logcheck - name: Minimal logging policy (1) lineinfile: dest=/etc/logrotate.d/rsyslog regexp="^/var/log/mail\\.(log|info|sasl)$" state=absent owner=root group=root mode=0644 - name: Minimal logging policy (2) copy: src=etc/logrotate.d/fripost-mail dest=/etc/logrotate.d/fripost-mail owner=root group=root mode=0644 tags: diff --git a/roles/common/tasks/mail.yml b/roles/common/tasks/mail.yml index 1873928..139386f 100644 --- a/roles/common/tasks/mail.yml +++ b/roles/common/tasks/mail.yml @@ -1,114 +1,63 @@ - name: Install Postfix - apt: pkg={{ item }} - with_items: + apt: pkg={{ packages }} + vars: + packages: # That one is nicer than GNU mailutils' mailx(1) - - heirloom-mailx + - s-nail - postfix - - postfix-cdb + - postfix-lmdb - name: Create Postfix instances postmulti: instance={{ postfix_instance[item].name }} group={{ postfix_instance[item].group | default('') }} register: r1 - with_items: postfix_instance.keys() | intersect(group_names) | list + with_items: "{{ postfix_instance.keys() | intersect(group_names) | list }}" notify: - Restart Postfix -- name: Link the dynamic maps & master.cf of each children to the master's - # main.cf is specialized to each dedicated role, though - file: src=../postfix/{{ item.1 }} - dest=/etc/postfix-{{ postfix_instance[item.0].name }}/{{ item.1 }} +- name: Link the dynamic maps of each children to the master's + # main.cf and master.cf are specialized to each dedicated role, though + file: src=../postfix/dynamicmaps.cf + dest=/etc/postfix-{{ postfix_instance[item].name }}/dynamicmaps.cf owner=root group=root state=link force=yes register: r2 - with_nested: - - postfix_instance.keys() | intersect(group_names) | list - - [ 'dynamicmaps.cf', 'master.cf' ] - notify: - - Restart Postfix - -- name: Configure Postfix (1) - copy: src=etc/postfix/master.cf - dest=/etc/postfix/master.cf - owner=root group=root - mode=0644 - register: r3 + with_items: "{{ postfix_instance.keys() | intersect(group_names) | list }}" notify: - Restart Postfix -- name: Configure Postfix (2) - template: src=etc/postfix/main.cf.j2 - dest=/etc/postfix/main.cf +- name: Configure Postfix + template: src=etc/postfix/{{ item }}.j2 + dest=/etc/postfix/{{ item }} owner=root group=root mode=0644 + with_items: + - main.cf + - master.cf notify: - Reload Postfix -- name: Create directory /etc/postfix/ssl - file: path=/etc/postfix/ssl - state=directory - owner=root group=root - mode=0755 - tags: - - genkey - -- name: Generate a private key and a X.509 certificate for Postfix - command: genkeypair.sh x509 - --pubkey=/etc/postfix/ssl/{{ ansible_fqdn }}.pem - --privkey=/etc/postfix/ssl/{{ ansible_fqdn }}.key - --ou=Postfix --cn={{ ansible_fqdn }} - -t ecdsa -b secp384r1 -h sha512 - register: r4 - changed_when: r4.rc == 0 - failed_when: r4.rc > 1 - notify: - - Restart Postfix - tags: - - genkey - -- name: Fetch Postfix's X.509 certificate - # Ensure we don't fetch private data - sudo: False - fetch: src=/etc/postfix/ssl/{{ ansible_fqdn }}.pem - dest=certs/postfix/ - fail_on_missing=yes - flat=yes - tags: - - genkey - -- name: Add a 'root' alias +- name: Add some common aliases lineinfile: dest=/etc/aliases create=yes - regexp="^root:"" " - line="root:"" root@fripost.org" + regexp='^{{ item.src }}{{':'}} ' + line='{{ item.src }}{{':'}} {{ item.dst }}' + with_items: + - { src: mailer-daemon, dst: 'postmaster' } + - { src: postmaster, dst: 'root' } + - { src: nobody, dst: 'root' } + - { src: root, dst: 'root@fripost.org' } - name: Compile the static local Postfix database - postmap: cmd=postalias src=/etc/aliases db=cdb + postmap: cmd=postalias src=/etc/aliases db=lmdb owner=root group=root mode=0644 -# We're using CDB +# We're using LMDB - name: Delete /etc/aliases.db file: path=/etc/aliases.db state=absent -- name: Copy the Postfix TLS policy map - template: src=etc/postfix/tls_policy.j2 - dest=/etc/postfix/tls_policy - owner=root group=root - mode=0644 - when: "'out' not in group_names or 'MX' in group_names" - tags: - - tls_policy - -- name: Compile the Postfix TLS policy map - postmap: cmd=postmap src=/etc/postfix/tls_policy db=cdb - owner=root group=root - mode=0644 - when: "'out' not in group_names or 'MX' in group_names" - tags: - - tls_policy - - name: Start Postfix service: name=postfix state=started - when: not (r1.changed or r2.changed or r3.changed or r4.changed) + when: not (r1.changed or r2.changed) - meta: flush_handlers diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml index 470a6b2..293d22b 100644 --- a/roles/common/tasks/main.yml +++ b/roles/common/tasks/main.yml @@ -1,70 +1,102 @@ --- -- include: sysctl.yml tags=sysctl -- include: hosts.yml -- include: apt.yml tags=apt +- import_tasks: sysctl.yml + tags: sysctl +- import_tasks: hosts.yml +- import_tasks: apt.yml + tags: apt - name: Install intel-microcode apt: pkg=intel-microcode - when: "ansible_processor[0] | search('^(Genuine)?Intel.*') and not (ansible_virtualization_role == 'guest' and ansible_virtualization_type == 'xen')" + when: "ansible_processor[1] is search('^(Genuine)?Intel.*') and not ansible_virtualization_role == 'guest'" tags: intel -- include: firewall.yml tags=firewall,iptables -- include: samhain.yml tags=samhain -- include: auditd.yml tags=auditd -- include: rkhunter.yml tags=rkhunter -- include: clamav.yml tags=clamav -- include: fail2ban.yml tags=fail2ban -- include: smart.yml tags=smartmontools,smart - when: "not ((ansible_virtualization_role == 'guest' and ansible_virtualization_type == 'xen') or ansible_system_vendor == 'QEMU')" -- include: haveged.yml tags=haveged,entropy +- import_tasks: firewall.yml + tags: + - firewall + - iptables + - nftables + +- import_tasks: stunnel.yml + tags: stunnel + when: "'webmail' in group_names and 'LDAP_provider' not in group_names" +#- import_tasks: auditd.yml +# tags: auditd +- import_tasks: resolved.yml + tags: + - resolv + - resolved + - dns +- import_tasks: unbound.yml + tags: + - unbound + - dns + when: "ansible_processor[1] is search('^(Genuine)?Intel.*') and not ansible_virtualization_role == 'guest'" +- import_tasks: rkhunter.yml + tags: rkhunter +- import_tasks: clamav.yml + tags: clamav +- import_tasks: fail2ban.yml + tags: fail2ban +- import_tasks: smart.yml + tags: + - smartmontools + - smart + when: "not ansible_virtualization_role == 'guest'" - name: Copy genkeypair.sh and gendhparam.sh copy: src=usr/local/bin/{{ item }} dest=/usr/local/bin/{{ item }} - owner=root group=root + owner=root group=staff mode=0755 tags: genkey with_items: - genkeypair.sh - gendhparam.sh - name: Generate DH parameters - command: gendhparam.sh /etc/ssl/private/dhparams.pem creates=/etc/ssl/private/dhparams.pem + command: gendhparam.sh /etc/ssl/dhparams.pem 2048 + creates=/etc/ssl/dhparams.pem tags: genkey -- include: logging.yml tags=logging -- include: ntp.yml tags=ntp -- include: mail.yml tags=mail,postfix -- include: bacula.yml tags=bacula-fd,bacula -- include: munin-node.yml tags=munin-node,munin +- import_tasks: ipsec.yml + tags: + - strongswan + - ipsec + when: "groups.all | length > 1" +- import_tasks: logging.yml + tags: logging +- import_tasks: ntp.yml + tags: ntp +- import_tasks: mail.yml + tags: + - mail + - postfix +- import_tasks: bacula.yml + tags: + - bacula-fd + - bacula +- import_tasks: munin-node.yml + tags: + - munin-node + - munin - name: Install common packages - apt: pkg={{ item }} - with_items: + apt: pkg={{ packages }} + vars: + packages: - ca-certificates - etckeeper - ethtool - git - htop - molly-guard - rsync - screen - - telnet-ssl - -# XXX: this is a workaround the CAcert root CAs not being present in -# Jessie. In stretch, we would merely install the 'ca-cacert' package. -- name: Create directory /usr/local/share/ca-certificates/CAcert - file: path=/usr/local/share/ca-certificates/CAcert - state=directory - owner=root group=root - mode=0755 - tags: - - certs + - bind9-dnsutils -- name: Copy CAcert root CAs - copy: src=certs/CAcert/{{ item }} - dest=/usr/local/share/ca-certificates/CAcert/{{ item }} +- name: Disable resume device + # Cf. initramfs-tools(7) and initramfs.conf(5). + copy: src=etc/initramfs-tools/conf.d/resume + dest=/etc/initramfs-tools/conf.d/resume owner=root group=root mode=0644 - with_items: - - root.crt - - class3.crt tags: - - certs + - initramfs + - resume notify: - - Update certificate + - Update initramfs diff --git a/roles/common/tasks/munin-node.yml b/roles/common/tasks/munin-node.yml index 9e5d8f4..2411b59 100644 --- a/roles/common/tasks/munin-node.yml +++ b/roles/common/tasks/munin-node.yml @@ -1,23 +1,24 @@ - name: Install munin-node - apt: pkg={{ item }} - with_items: + apt: pkg={{ packages }} + vars: + packages: - munin-node - munin-plugins-extra ### - acpi - lm-sensors - ethtool - hdparm - libwww-perl - libxml-simple-perl - logtail - name: Create directory /usr/local/share/munin/plugins file: path=/usr/local/share/munin/plugins state=directory owner=root group=root mode=0755 - name: Copy our own Munin plugins copy: src={{ item }} dest=/usr/local/share/munin/plugins/ @@ -44,68 +45,90 @@ owner=root group=root state=link force=yes register: r2 with_items: - cpu - df - df_inode - diskstats - entropy - fail2ban - forks - fw_conntrack - fw_forwarded_local - fw_packets - hddtemp_smartctl - interrupts - irqstats - load - memory - netstat - - ntp_kernel_err - - ntp_kernel_pll_freq - - ntp_kernel_pll_off - - ntp_offset - open_files - open_inodes - processes - proc_pri - swap - threads - uptime - users - vmstat notify: - Restart munin-node -- name: Delete Munin plugins +- name: Install Munin plugins + file: src=/usr/share/munin/plugins/{{ item }} + dest=/etc/munin/plugins/{{ item }} + owner=root group=root + state=link force=yes + with_items: + - ntp_kernel_err + - ntp_kernel_pll_freq + - ntp_kernel_pll_off + - ntp_offset + when: "'NTP_master' in group_names" + notify: + - Restart munin-node + +- name: Delete unnecessary Munin plugins file: path=/etc/munin/plugins/{{ item }} state=absent register: r3 with_items: - http_loadtime - ip_255.255.255.255 - postfix_mailqueue - postfix_mailvolume notify: - Restart munin-node +- name: Delete unnecessary Munin plugins + file: path=/etc/munin/plugins/{{ item }} + state=absent + with_items: + - ntp_kernel_err + - ntp_kernel_pll_freq + - ntp_kernel_pll_off + - ntp_offset + when: "'NTP_master' not in group_names" + notify: + - Restart munin-node + - name: Install 'if_' Munin wildcard plugin file: src=/usr/share/munin/plugins/{{ item.0 }}_ dest=/etc/munin/plugins/{{ item.0 }}_{{ item.1 }} owner=root group=root state=link force=yes register: r4 with_nested: - [ if, if_err ] - [ lo, "{{ ansible_default_ipv4.interface }}" ] notify: - Restart munin-node - name: Install 'postfix_mailvolume2' Munin plugin file: src=/usr/local/share/munin/plugins/postfix_mailvolume2 dest=/etc/munin/plugins/postfix_mailvolume2 owner=root group=root state=link force=yes register: r5 notify: - Restart munin-node @@ -115,93 +138,49 @@ dest=/etc/munin/plugins/postfix_mailqueue_postfix owner=root group=root state=link force=yes register: r6 notify: - Restart munin-node - name: Install 'postfix_stats_' Munin wildcard plugin file: src=/usr/local/share/munin/plugins/postfix_stats_ dest=/etc/munin/plugins/postfix_stats_{{ item }}_postfix owner=root group=root state=link force=yes register: r7 with_items: - smtpd - qmgr - smtp notify: - Restart munin-node -- name: Start munin-node - service: name=munin-node state=started - when: not (r1.changed or r2.changed or r3.changed or r4.changed or r5.changed or r6.changed or r7.changed) - -- meta: flush_handlers - - - -- name: Install stunnel - apt: pkg=stunnel4 - -- name: Auto-enable stunnel - lineinfile: dest=/etc/default/stunnel4 - regexp='^(\s*#)?\s*ENABLED=' - line='ENABLED=1' - owner=root group=root - mode=0644 - -- name: Create /etc/stunnel/certs - file: path=/etc/stunnel/certs +- name: Create directory /etc/systemd/system/munin-node.service.d + file: path=/etc/systemd/system/munin-node.service.d state=directory owner=root group=root mode=0755 -- name: Generate a private key and a X.509 certificate for munin-node - command: genkeypair.sh x509 - --pubkey=/etc/stunnel/certs/munin-{{ inventory_hostname_short }}.pem - --privkey=/etc/stunnel/certs/munin-{{ inventory_hostname_short }}.key - --ou=Munin --cn={{ inventory_hostname }} --dns={{ inventory_hostname }} - -t rsa -b 4096 -h sha512 - register: r1 - changed_when: r1.rc == 0 - failed_when: r1.rc > 1 - notify: - - Restart stunnel - tags: - - genkey - -- name: Fetch Munin X.509 certificate - # Ensure we don't fetch private data - sudo: False - fetch: src=/etc/stunnel/certs/munin-{{ inventory_hostname_short }}.pem - dest=certs/munin/{{ inventory_hostname }}.pem - fail_on_missing=yes - flat=yes - tags: - - genkey - -- name: Copy munin-master X.509 certificates - assemble: src=certs/munin regexp="{{ groups['munin-master'] | join('|') }}\.pem$" remote_src=no - dest=/etc/stunnel/certs/munin-master.pem - owner=root group=root - mode=0644 - register: r2 - when: "'munin-master' not in group_names" +- name: Copy munin-node.service override + copy: src=etc/systemd/system/munin-node.service.d/override.conf + dest=/etc/systemd/system/munin-node.service.d/override.conf + owner=root group=root + mode=0644 + register: r8 notify: - - Restart stunnel + - systemctl daemon-reload + - Restart munin-node -- name: Configure stunnel - template: src=etc/stunnel/munin-node.conf.j2 - dest=/etc/stunnel/munin-node.conf - owner=root group=root - mode=0644 - register: r3 - when: "'munin-master' not in group_names" - notify: - - Restart stunnel +# We use RuntimeDirectory in our overrride unit to avoid permission +# issues caused by the restrictive Capability Bounding Set +- name: Mask /usr/lib/tmpfiles.d/munin-common.conf + file: src=/dev/null + dest=/etc/tmpfiles.d/munin-common.conf + owner=root group=root + state=link -- name: Start stunnel - service: name=stunnel4 pattern=/usr/bin/stunnel4 state=started - when: not (r1.changed or r2.changed or r3.changed) +- name: Start munin-node + service: name=munin-node state=started + when: not (r1.changed or r2.changed or r3.changed or r4.changed or r5.changed or r6.changed or r7.changed or r8.changed) - meta: flush_handlers diff --git a/roles/common/tasks/ntp.yml b/roles/common/tasks/ntp.yml index f9a01c8..2ff9e49 100644 --- a/roles/common/tasks/ntp.yml +++ b/roles/common/tasks/ntp.yml @@ -1,15 +1,33 @@ -- name: Install ntp - apt: pkg=ntp +- name: Remove ntp package + apt: pkg=ntp state={{ state }} purge=yes + vars: + state: "{{ ('NTP_master' in group_names) | ternary('present', 'absent') }}" + +- name: Install systemd-timesyncd package + apt: pkg=systemd-timesyncd state=present purge=yes + when: "'NTP_master' not in group_names" + +- name: Create /etc/systemd/timesyncd.conf.d + file: path=/etc/systemd/timesyncd.conf.d + state=directory + owner=root group=root + mode=0755 + when: "'NTP_master' not in group_names" - name: Configure ntp - template: src=etc/ntp.conf.j2 - dest=/etc/ntp.conf + template: src=etc/{{ conf }}.j2 + dest=/etc/{{ conf }} owner=root group=root mode=0644 + vars: + conf: "{{ ('NTP_master' in group_names) | ternary('ntp.conf', 'systemd/timesyncd.conf.d/fripost.conf') }}" + service: "{{ ('NTP_master' in group_names) | ternary('ntp', 'systemd-timesyncd') }}" notify: - - Restart ntp + - Restart {{ service }} - meta: flush_handlers -- name: Start ntp - service: name=ntp state=started +- name: Start and enable ntp + service: name={{ service }}.service state=started enabled=true + vars: + service: "{{ ('NTP_master' in group_names) | ternary('ntp', 'systemd-timesyncd') }}" diff --git a/roles/common/tasks/resolved.yml b/roles/common/tasks/resolved.yml new file mode 100644 index 0000000..2834eaa --- /dev/null +++ b/roles/common/tasks/resolved.yml @@ -0,0 +1,36 @@ +- name: Install systemd-resolved + apt: pkg={{ packages }} + vars: + packages: + - systemd-resolved + - libnss-resolve + - libnss-myhostname + +- name: Create directory /etc/systemd/resolved.conf.d + file: path=/etc/systemd/resolved.conf.d + state=directory + owner=root group=root + mode=0755 + +- name: Configure systemd-resolved + template: src=etc/systemd/resolved.conf.d/local.conf.j2 + dest=/etc/systemd/resolved.conf.d/local.conf + owner=root group=root + mode=0644 + notify: + - Restart systemd-resolved + +- name: Start systemd-resolved + service: name=systemd-resolved.service enabled=true state=started + +- meta: flush_handlers + +- name: Remove resolvconf + apt: pkg=resolvconf state=absent purge=yes + +- name: Configure /etc/nsswitch.conf + lineinfile: "dest=/etc/nsswitch.conf create=no + regexp='^(hosts:\\s+).*' + line='\\1resolve [!UNAVAIL=return] files myhostname dns' + backrefs=true" + tags: nsswitch diff --git a/roles/common/tasks/rkhunter.yml b/roles/common/tasks/rkhunter.yml index c9d26fa..64f2aac 100644 --- a/roles/common/tasks/rkhunter.yml +++ b/roles/common/tasks/rkhunter.yml @@ -1,23 +1,24 @@ - name: Install rkhunter - apt: pkg={{ item }} - with_items: + apt: pkg={{ packages }} + vars: + packages: - rkhunter - curl - iproute2 - lsof - unhide # To test the configuration: # ansible all -m command -a '/usr/bin/rkhunter -c --nomow --rwo' - name: Configure rkhunter copy: src=etc/{{ item }} dest=/etc/{{ item }} owner=root group=root mode=0644 with_items: - rkhunter.conf - default/rkhunter notify: # This might not always be necessary, but it's not like we would # change the config every day... - Update rkhunter's data file diff --git a/roles/common/tasks/samhain.yml b/roles/common/tasks/samhain.yml deleted file mode 100644 index dd5c09b..0000000 --- a/roles/common/tasks/samhain.yml +++ /dev/null @@ -1,26 +0,0 @@ -- name: Install samhain - apt: pkg=samhain - # XXX: Doesn't work out of the box, see #660197. - # Every once in a while, or after a major upgrade, you may want to - # update Samhain's database: - # - # sudo samhain -t update --foreground -l none - # - # To update the database interactively, without sending mails: - # - # sudo samhain -t update --interactive -l none -m none - -- name: Configure samhain - copy: src=etc/samhain/samhainrc - dest=/etc/samhain/samhainrc - owner=root group=root - mode=0644 - notify: - - Reload samhain - -- name: Start samhain - # This task is inconditional because samhain is reloaded not - # restarted. - service: name=samhain state=started - -- meta: flush_handlers diff --git a/roles/common/tasks/smart.yml b/roles/common/tasks/smart.yml index 8d35d9f..68e507f 100644 --- a/roles/common/tasks/smart.yml +++ b/roles/common/tasks/smart.yml @@ -1,12 +1,5 @@ - name: Install smartmontools apt: pkg=smartmontools -- name: Auto-enable smartmontools - lineinfile: dest=/etc/default/smartmontools - regexp='^(\s*#)?\s*start_smartd=' - line='start_smartd=yes' - owner=root group=root - mode=0644 - - name: Start smartd service: name=smartmontools state=started diff --git a/roles/common/tasks/stunnel.yml b/roles/common/tasks/stunnel.yml new file mode 100644 index 0000000..1522f1f --- /dev/null +++ b/roles/common/tasks/stunnel.yml @@ -0,0 +1,16 @@ +- name: Install stunnel4 + apt: pkg=stunnel4 + +- name: Copy stunnel4 service files + copy: src=etc/systemd/system/{{ item }} + dest=/etc/systemd/system/{{ item }} + owner=root group=root + mode=0644 + notify: + - systemctl daemon-reload + with_items: + - stunnel4.service + - stunnel4@.service + +- name: Disable stunnel4 service + service: name=stunnel4.service enabled=false diff --git a/roles/common/tasks/sysctl.yml b/roles/common/tasks/sysctl.yml index 6ac7feb..08a1b13 100644 --- a/roles/common/tasks/sysctl.yml +++ b/roles/common/tasks/sysctl.yml @@ -1,49 +1,48 @@ -- sysctl: name={{ item.name }} "value={{ item.value }}" sysctl_set=yes +- sysctl: name={{ item.name }} value={{ item.value }} sysctl_set=yes with_items: - { name: 'kernel.domainname', value: '{{ ansible_domain }}' } # Networking. See # https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt # Enable Spoof protection (reverse-path filter). Turn on Source # Address Verification in all interfaces to prevent some spoofing # attacks. - { name: 'net.ipv4.conf.default.rp_filter', value: 1 } - { name: 'net.ipv4.conf.all.rp_filter', value: 1 } - # Enable TCP/IP SYN cookies to avoid TCP SYN flood attacks. We - # rate-limit not only the default ICMP types 3, 4, 11 and 12 + # Disable SYN cookies and improve SYN backlog handling, see tcp(7) and + # https://levelup.gitconnected.com/linux-kernel-tuning-for-high-performance-networking-high-volume-incoming-connections-196e863d458a + - { name: 'net.ipv4.tcp_syncookies', value: 0 } + - { name: 'net.ipv4.tcp_synack_retries', value: 1 } + - { name: 'net.ipv4.tcp_max_syn_backlog', value: 32768 } + + # We rate-limit not only the default ICMP types 3, 4, 11 and 12 # (0x1818), but also types 0 and 8. See icmp(7). - - { name: 'net.ipv4.tcp_syncookies', value: 1 } - { name: 'net.ipv4.icmp_ratemask', value: 6425 } - { name: 'net.ipv4.icmp_ratelimit', value: 1000 } - # Disable paquet forwarding between interfaces (we are not a router). + # Disable packet forwarding between interfaces (we are not a router). - { name: 'net.ipv4.ip_forward', value: 0 } - { name: 'net.ipv6.conf.all.forwarding', value: 0 } - # Enable IPv6 Privacy Extensions. - - { name: 'net.ipv6.conf.default.use_tempaddr', value: 2 } - - { name: 'net.ipv6.conf.all.use_tempaddr', value: 2 } - - { name: 'net.ipv6.conf.all.autoconf', value: 0 } - # Do not accept ICMP redirects (prevent MITM attacks). - { name: 'net.ipv4.conf.all.accept_redirects', value: 0 } - { name: 'net.ipv6.conf.all.accept_redirects', value: 0 } # Do not send ICMP redirects (we are not a router). - { name: 'net.ipv4.conf.default.send_redirects', value: 0 } - { name: 'net.ipv4.conf.all.send_redirects', value: 0 } # Do not accept IP source route packets (we are not a router). - { name: 'net.ipv4.conf.all.accept_source_route', value: 0 } - { name: 'net.ipv6.conf.all.accept_source_route', value: 0 } # Log Martian Packets. - { name: 'net.ipv4.conf.all.log_martians', value: 1 } # Ignore ICMP broadcasts. - { name: 'net.ipv4.icmp_echo_ignore_broadcasts', value: 1 } # Ignore bogus ICMP errors. - { name: 'net.ipv4.icmp_ignore_bogus_error_responses', value: 1 } diff --git a/roles/common/tasks/unbound.yml b/roles/common/tasks/unbound.yml new file mode 100644 index 0000000..dda6769 --- /dev/null +++ b/roles/common/tasks/unbound.yml @@ -0,0 +1,21 @@ +- name: Install unbound + apt: pkg={{ packages }} + vars: + packages: + - unbound + - dns-root-data + +- name: Copy unbound configuration + template: src=templates/etc/unbound/unbound.conf.j2 + dest=/etc/unbound/unbound.conf + owner=root group=root + mode=0644 + register: r + notify: + - Restart unbound + +- name: Start unbound + service: name=unbound state=started + when: not r.changed + +#- meta: flush_handlers |