diff --git a/amavis/handlers/main.yml b/amavis/handlers/main.yml new file mode 100644 index 00000000..62049999 --- /dev/null +++ b/amavis/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart amavis + service: + name: amavis + state: restarted diff --git a/amavis/tasks/main.yml b/amavis/tasks/main.yml new file mode 100644 index 00000000..810ba505 --- /dev/null +++ b/amavis/tasks/main.yml @@ -0,0 +1,19 @@ +--- +- name: install Amavis + apt: + name: "{{ item }}" + state: present + with_items: + - postgrey + - amavisd-new + tags: + - amavis + +- name: configure Amavis + template: + src: amavis.conf.j2 + dest: /etc/amavis/conf.d/49-evolinux-defaults.conf + mode: "0644" + notify: restart amavis + tags: + - amavis diff --git a/amavis/templates/amavis.conf.j2 b/amavis/templates/amavis.conf.j2 new file mode 100644 index 00000000..cbe597a2 --- /dev/null +++ b/amavis/templates/amavis.conf.j2 @@ -0,0 +1,57 @@ +use strict; + +## Liste des domaines considérés comme locaux +#@local_domains_acl = qw(.); +@local_domains_acl = (".example.net","example.com"); + +# On customise la ligne ajoutée dans les entêtes +$X_HEADER_LINE = "by Amavis at $mydomain"; + +# On precise les FROM pour etre (bugs dans certaines version d'Amavis) +$mailfrom_notify_admin = "postmaster\@$mydomain"; +$mailfrom_notify_recip = "postmaster\@$mydomain"; +$mailfrom_notify_spamadmin = "postmaster\@$mydomain"; + +# Notifications de fichiers bannis / virus +$virus_admin = "postmaster\@$mydomain"; +# Ne pas recevoir des notifications pour les mails UNCHECKED +delete $admin_maps_by_ccat{&CC_UNCHECKED}; + +# Que faire avec les messages détectés +$final_virus_destiny = D_DISCARD; +$final_banned_destiny = D_BOUNCE; +$final_spam_destiny = D_BOUNCE; +$final_bad_header_destiny = D_PASS; + +# Pour recevoir des bounces (mails originals) des fichiers bloqués / virus +#$banned_quarantine_to = "banned\@$mydomain"; +#$virus_quarantine_to = "virus\@$mydomain"; + +# Note tueuse +$sa_tag2_level_deflt = 6.31; +# Pour un comportement "normal" de SA +$sa_tag_level_deflt = -1999; +$sa_kill_level_deflt = 1999; +$sa_dsn_cutoff_level = -99; +$sa_spam_subject_tag = '[SPAM]'; + +# log +$log_level = 2; + +# En fonction besoin/ressources, on a juste le nbre de process +$max_servers = 2; + +$enable_ldap = 1; +$default_ldap = { + hostname => '127.0.0.1', tls => 0, + base => '{{ ldap_suffix }}', scope => 'sub', + query_filter => '(&(mailacceptinggeneralid=%m)(isActive=TRUE))' +}; + +# Activer l'antivirus et antivirus +@bypass_virus_checks_maps = ( + \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re); +@bypass_spam_checks_maps = ( + \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re); + +1; # ensure a defined return diff --git a/apache/tasks/main.yml b/apache/tasks/main.yml index ed99fe5a..35ffcf44 100644 --- a/apache/tasks/main.yml +++ b/apache/tasks/main.yml @@ -38,6 +38,10 @@ - expires - headers - cgi + - ssl + - include + - negotiation + - alias notify: reload apache tags: - apache diff --git a/apache/tasks/remount_usr_rw.yml b/apache/tasks/remount_usr_rw.yml index 60162607..1f6d064d 100644 --- a/apache/tasks/remount_usr_rw.yml +++ b/apache/tasks/remount_usr_rw.yml @@ -1,19 +1,12 @@ --- -- name: Get mount options for partitions - shell: "mount | grep 'on /usr type'" - args: - warn: no - register: mount - changed_when: False - failed_when: False - when: not ansible_check_mode +- name: update ansible_mounts facts + setup: + filter: ansible_mounts -- name: Remount /usr if it is a partition and it is not mounted in rw - command: "mount -o remount,rw /usr" - when: - - not ansible_check_mode - - mount.rc == 0 - - not mount.stdout_lines.0 | search("rw") - check_mode: yes +- name: mount /usr in rw + command: mount -o remount,rw /usr args: warn: no + changed_when: false + when: item.mount == '/usr' and item.options | match(".*ro.*") + with_items: "{{ ansible_mounts }}" diff --git a/clamav/handlers/main.yml b/clamav/handlers/main.yml new file mode 100644 index 00000000..e053f01a --- /dev/null +++ b/clamav/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart clamav + service: + name: clamav-daemon + state: restarted diff --git a/clamav/meta/main.yml b/clamav/meta/main.yml new file mode 100644 index 00000000..510b6855 --- /dev/null +++ b/clamav/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - { role: amavis } diff --git a/clamav/tasks/main.yml b/clamav/tasks/main.yml new file mode 100644 index 00000000..6e3058dd --- /dev/null +++ b/clamav/tasks/main.yml @@ -0,0 +1,111 @@ +--- +- name: configure clamav-daemon + debconf: + name: clamav-daemon + question: "{{ item.key }}" + value: "{{ item.value }}" + vtype: "{{ item.type }}" + with_items: + - { key: 'clamav-daemon/debconf', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/MaxHTMLNormalize', type: 'string', value: '10M' } + - { key: 'clamav-daemon/StatsPEDisabled', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/FollowDirectorySymlinks', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/StreamMaxLength', type: 'string', value: '25' } + - { key: 'clamav-daemon/ReadTimeout', type: 'string', value: '180' } + - { key: 'clamav-daemon/StatsEnabled', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/MaxConnectionQueueLength', type: 'string', value: '15' } + - { key: 'clamav-daemon/LogRotate', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/AllowAllMatchScan', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/ScanOnAccess', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/LogFile', type: 'string', value: '/var/log/clamav/clamav.log' } + - { key: 'clamav-daemon/ScanMail', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/BytecodeTimeout', type: 'string', value: '60000' } + - { key: 'clamav-daemon/LogTime', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/OnAccessMaxFileSize', type: 'string', value: '5M' } + - { key: 'clamav-daemon/TcpOrLocal', type: 'select', value: 'UNIX' } + - { key: 'clamav-daemon/MaxEmbeddedPE', type: 'string', value: '10M' } + - { key: 'clamav-daemon/FixStaleSocket', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/User', type: 'string', value: 'clamav' } + - { key: 'clamav-daemon/BytecodeSecurity', type: 'select', value: 'TrustSigned' } + - { key: 'clamav-daemon/ScanSWF', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/MaxDirectoryRecursion', type: 'string', value: '0' } + - { key: 'clamav-daemon/MaxThreads', type: 'string', value: '12' } + - { key: 'clamav-daemon/LocalSocketGroup', type: 'string', value: 'clamav' } + - { key: 'clamav-daemon/MaxScriptNormalize', type: 'string', value: '5M' } + - { key: 'clamav-daemon/ForceToDisk', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/StatsHostID', type: 'string', value: 'auto' } + - { key: 'clamav-daemon/FollowFileSymlinks', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/TCPSocket', type: 'string', value: '3310' } + - { key: 'clamav-daemon/TCPAddr', type: 'string', value: 'any' } + - { key: 'clamav-daemon/DisableCertCheck', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/SelfCheck', type: 'string', value: '3600' } + - { key: 'clamav-daemon/LocalSocket', type: 'string', value: '/var/run/clamav/clamd.ctl' } + - { key: 'clamav-daemon/LocalSocketMode', type: 'string', value: '666' } + - { key: 'clamav-daemon/StatsTimeout', type: 'string', value: '10' } + - { key: 'clamav-daemon/MaxZipTypeRcg', type: 'string', value: '1M' } + - { key: 'clamav-daemon/MaxHTMLNoTags', type: 'string', value: '2M' } + - { key: 'clamav-daemon/LogSyslog', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/AddGroups', type: 'string', value: '' } + - { key: 'clamav-daemon/Bytecode', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/ScanArchive', type: 'boolean', value: 'true' } + tags: + - clamav + +- name: configure clamav-freshclam + debconf: + name: clamav-freshclam + question: "{{ item.key }}" + value: "{{ item.value }}" + vtype: "{{ item.type }}" + with_items: + - { key: 'clamav-freshclam/autoupdate_freshclam', type: 'select', value: 'daemon' } + - { key: 'clamav-freshclam/proxy_user', type: 'string', value: '' } + - { key: 'clamav-freshclam/NotifyClamd', type: 'boolean', value: 'true' } + - { key: 'clamav-freshclam/local_mirror', type: 'select', value: 'db.fr.clamav.net' } + - { key: 'clamav-freshclam/http_proxy', type: 'string', value: '' } + - { key: 'clamav-freshclam/LogRotate', type: 'boolean', value: 'true' } + - { key: 'clamav-freshclam/Bytecode', type: 'boolean', value: 'true' } + - { key: 'clamav-freshclam/update_interval', type: 'string', value: '24' } + - { key: 'clamav-freshclam/SafeBrowsing', type: 'boolean', value: 'false' } + - { key: 'clamav-freshclam/PrivateMirror', type: 'string', value: '' } + - { key: 'clamav-freshclam/internet_interface', type: 'string', value: '' } + tags: + - clamav + +- name: install ClamAV + apt: + name: "{{ item }}" + state: present + with_items: + - clamav-daemon + - clamav + - clamdscan + - clamav-freshclam + - arc + - arj + - zoo + - pax + - bzip2 + - cabextract + - rpm + - lzop + - razor + tags: + - clamav + +- name: add clamav user to amavis group + user: + name: clamav + groups: amavis + append: True + tags: + - clamav + +- name: allow supplementary groups + replace: + dest: /etc/clamav/clamd.conf + regexp: 'AllowSupplementaryGroups false' + replace: 'AllowSupplementaryGroups true' + notify: restart clamav + tags: + - clamav diff --git a/dovecot/.kitchen.yml b/dovecot/.kitchen.yml new file mode 100644 index 00000000..687c2033 --- /dev/null +++ b/dovecot/.kitchen.yml @@ -0,0 +1,36 @@ +--- +driver: + name: docker + privileged: true + use_sudo: false + +provisioner: + name: ansible_playbook + hosts: test-kitchen + roles_path: ../ + ansible_verbose: true + require_ansible_source: false + require_chef_for_busser: false + idempotency_test: true + +platforms: + - name: debian + driver_config: + image: evolix/ansible:2.2.1 + +verifier: + name: serverspec + +suites: + - name: default + provisioner: + name: ansible_playbook + playbook: ./tests/test.yml + verifier: + patterns: + - nginx/tests/spec/memcached_spec.rb + bundler_path: '/usr/local/bin' + rspec_path: '/usr/local/bin' + +transport: + max_ssh_sessions: 6 diff --git a/dovecot/README.md b/dovecot/README.md new file mode 100644 index 00000000..736b95dc --- /dev/null +++ b/dovecot/README.md @@ -0,0 +1,11 @@ +# Dovecot + +Installation and basic configuration of dovecot + +## Tasks + +Minimal configuration is in `tasks/main.yml` + +## Available variables + +The full list of variables (with default values) can be found in `defaults/main.yml`. diff --git a/dovecot/defaults/main.yml b/dovecot/defaults/main.yml new file mode 100644 index 00000000..884bc1ca --- /dev/null +++ b/dovecot/defaults/main.yml @@ -0,0 +1,2 @@ +--- +dovecot_foo: bar diff --git a/dovecot/files/munin_plugin b/dovecot/files/munin_plugin new file mode 100755 index 00000000..e5a6d1d1 --- /dev/null +++ b/dovecot/files/munin_plugin @@ -0,0 +1,126 @@ +#! /bin/bash +# +# Munin Plugin +# to count logins to your dovecot mailserver +# +# Created by Dominik Schulz +# http://developer.gauner.org/munin/ +# Contributions by: +# - Stephane Enten +# - Steve Schnepp +# +# Parameters understood: +# +# config (required) +# autoconf (optional - used by munin-config) +# +# Config variables: +# +# logfile - Where to find the syslog file +# +# Add the following line to a file in /etc/munin/plugin-conf.d: +# env.logfile /var/log/your/logfile.log +# +# Magic markers (optional - used by munin-config and installation scripts): +# +#%# family=auto +#%# capabilities=autoconf + +###################### +# Configuration +###################### +EXPR_BIN=/usr/bin/expr +LOGFILE=${logfile:-/var/log/mail.log} +###################### + +if [ "$1" = "autoconf" ]; then + echo yes + exit 0 +fi + +if [ "$1" = "config" ]; then + echo 'graph_title Dovecot Logins' + echo 'graph_category Mail' + echo 'graph_args --base 1000 -l 0' + echo 'graph_vlabel Login Counters' + + for t in Total TLS SSL IMAP POP3 + do + field=$(echo $t | tr '[:upper:]' '[:lower:]') + echo "login_$field.label $t Logins" + echo "login_$field.type DERIVE" + echo "login_$field.min 0" + done + + echo 'connected.label Connected Users' + + exit 0 +fi + +###################### +# Total Logins +###################### +echo -en "login_total.value " +VALUE=$(egrep -c '[dovecot]?.*Login' $LOGFILE) +if [ ! -z "$VALUE" ]; then + echo "$VALUE" +else + echo "0" +fi +echo -n +###################### +# Connected Users +###################### +DISCONNECTS=$(egrep -c '[dovecot]?.*Disconnected' $LOGFILE) +CONNECTS=$(egrep -c '[dovecot]?.*Login' $LOGFILE) +VALUE=$($EXPR_BIN $CONNECTS - $DISCONNECTS) +if [ -z "$VALUE" ] || [ "$VALUE" -lt 0 ]; then + VALUE=0 +fi +echo -en "connected.value " +echo $VALUE +echo -n +###################### +# TLS Logins +###################### +echo -en "login_tls.value " +VALUE=$(egrep -c '[dovecot]?.*Login.*TLS' $LOGFILE) +if [ ! -z "$VALUE" ]; then + echo "$VALUE" +else + echo "0" +fi +echo -n +###################### +# SSL Logins +###################### +echo -en "login_ssl.value " +VALUE=$(egrep -c '[dovecot]?.*Login.*SSL' $LOGFILE) +if [ ! -z "$VALUE" ]; then + echo "$VALUE" +else + echo "0" +fi +echo -n +###################### +# IMAP Logins +###################### +echo -en "login_imap.value " +VALUE=$(egrep -c '[dovecot]?.*imap.*Login' $LOGFILE) +if [ ! -z "$VALUE" ]; then + echo "$VALUE" +else + echo "0" +fi +echo -n +###################### +# POP3 Logins +###################### +echo -en "login_pop3.value " +VALUE=$(egrep -c '[dovecot]?.*pop3.*Login' $LOGFILE) +if [ ! -z "$VALUE" ]; then + echo "$VALUE" +else + echo "0" +fi +echo -n diff --git a/dovecot/handlers/main.yml b/dovecot/handlers/main.yml new file mode 100644 index 00000000..8d1b78d8 --- /dev/null +++ b/dovecot/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: restart dovecot + service: + name: dovecot + state: restarted + +- name: reload dovecot + service: + name: dovecot + state: reloaded diff --git a/dovecot/tasks/main.yml b/dovecot/tasks/main.yml new file mode 100644 index 00000000..1a835160 --- /dev/null +++ b/dovecot/tasks/main.yml @@ -0,0 +1,68 @@ +- name: ensure packages are installed + apt: + name: '{{ item }}' + state: present + with_items: + - dovecot-ldap + - dovecot-imapd + - dovecot-pop3d + - dovecot-sieve + - dovecot-managesieved + tags: + - dovecot + +- name: disable pam auth + replace: + dest: /etc/dovecot/conf.d/10-auth.conf + regexp: "[^#]!include auth-system.conf.ext" + replace: "#!include auth-system.conf.ext" + tags: + - dovecot + +- name: update ldap auth + lineinfile: + dest: /etc/dovecot/dovecot-ldap.conf.ext + line: "{{ item.key }} = {{ item.value }}" + regexp: "^#*{{ item.key }}" + state: present + with_items: + - { key: 'hosts', value: '127.0.0.1' } + - { key: 'auth_bind', value: 'yes' } + - { key: 'ldap_version', value: 3 } + - { key: 'base', value: "{{ ldap_suffix }}" } + - { key: 'user_attrs', value: 'homeDirectory=home' } + - { key: 'user_filter', value: '(&(isActive=TRUE)(uid=%u))' } + - { key: 'pass_attrs', value: 'uid=user,userPassword=password' } + when: ldap_suffix is defined + notify: reload dovecot + tags: + - dovecot + +- name: create vmail group + group: + name: vmail + gid: 5000 + tags: + - dovecot + +- name: create vmail user + user: + name: vmail + group: vmail + uid: 5000 + shell: /bin/false + tags: + - dovecot + +- name: deploy evolix config + template: + src: z-evolinux-defaults.conf.j2 + dest: /etc/dovecot/conf.d/z-evolinux-defaults.conf + mode: "0644" + notify: reload dovecot + tags: + - dovecot + +- include: munin.yml + tags: + - dovecot diff --git a/dovecot/tasks/munin.yml b/dovecot/tasks/munin.yml new file mode 100644 index 00000000..7f5003f0 --- /dev/null +++ b/dovecot/tasks/munin.yml @@ -0,0 +1,20 @@ +--- + +- name: is Munin present ? + stat: + path: /etc/munin/plugin-conf.d/munin-node + check_mode: no + register: munin_node_plugins_config + +- block: + - name: Install munin plugin + copy: + src: munin_plugin + dest: /etc/munin/plugins/dovecot + mode: "0755" + +# TODO : add in /etc/munin/plugin-conf.d/munin-node +# [dovecot] +# group adm + + when: munin_node_plugins_config.stat.exists diff --git a/dovecot/templates/z-evolinux-defaults.conf.j2 b/dovecot/templates/z-evolinux-defaults.conf.j2 new file mode 100644 index 00000000..b6d8d5e5 --- /dev/null +++ b/dovecot/templates/z-evolinux-defaults.conf.j2 @@ -0,0 +1,36 @@ +# {{ ansible_managed }} + +# Autorise les mécanismes PLAIN/LOGIN même sans SSL/TLS +disable_plaintext_auth = no +auth_mechanisms = plain login + +# Authentification LDAP + intégration avec Postfix pour l'auth SMTP +!include auth-ldap.conf.ext +service auth { + unix_listener auth-userdb { + mode = 0600 + user = vmail + group = vmail + } + unix_listener /var/spool/postfix/private/auth-client { + mode = 0666 + user = postfix + group = postfix + } +} + +# Stockage des emails dans /home/mail avec UID/GID 5000/5000 +mail_location = maildir:/home/vmail/%d/%n +mail_uid = 5000 +mail_gid = 5000 + +# Activation Sieve +protocol lda { + mail_plugins = sieve +} + +# Optimisations +service login { + process_limit = 256 +} +mail_max_userip_connections = 42 diff --git a/fail2ban/defaults/main.yml b/fail2ban/defaults/main.yml index 5c4df4f0..d0716d95 100644 --- a/fail2ban/defaults/main.yml +++ b/fail2ban/defaults/main.yml @@ -3,3 +3,4 @@ general_alert_email: "root@localhost" fail2ban_alert_email: Null fail2ban_ignore_ips: [] fail2ban_wordpress: False +fail2ban_roundcube: False diff --git a/fail2ban/files/roundcube.conf b/fail2ban/files/roundcube.conf new file mode 100644 index 00000000..d4ad016a --- /dev/null +++ b/fail2ban/files/roundcube.conf @@ -0,0 +1,2 @@ +[Definition] +failregex = Login failed for .*. from diff --git a/fail2ban/tasks/main.yml b/fail2ban/tasks/main.yml index fbed85eb..6a9a6ff7 100644 --- a/fail2ban/tasks/main.yml +++ b/fail2ban/tasks/main.yml @@ -22,14 +22,6 @@ tags: - fail2ban -- name: package is installed - apt: - name: fail2ban - state: present - tags: - - fail2ban - - packages - - name: custom filters are installed copy: src: "{{ item }}" @@ -40,6 +32,16 @@ - sasl-evolix.conf - wordpress-soft.conf - wordpress-hard.conf + - roundcube.conf notify: restart fail2ban tags: - fail2ban + +- name: package is installed + apt: + name: fail2ban + state: present + tags: + - fail2ban + - packages + diff --git a/fail2ban/templates/jail.local.j2 b/fail2ban/templates/jail.local.j2 index b336e535..73b5f21f 100644 --- a/fail2ban/templates/jail.local.j2 +++ b/fail2ban/templates/jail.local.j2 @@ -44,3 +44,12 @@ logpath = /var/log/auth.log maxretry = 5 findtime = 300 {% endif %} + +{% if fail2ban_roundcube %} +[roundcube] +enabled = true +port = http,https +filter = roundcube +logpath = /var/lib/roundcube/logs/errors +maxretry = 5 +{% endif %} diff --git a/ldap/defaults/main.yml b/ldap/defaults/main.yml index 1e90583f..2f208f98 100644 --- a/ldap/defaults/main.yml +++ b/ldap/defaults/main.yml @@ -1,4 +1,5 @@ --- ldap_domain: "{{ ansible_fqdn }}" ldap_organization: "{{ ansible_domain }}" -#ldap_password=$(apg -n1 -m 12 -c cl_seed) +ldap_suffix: "dc=example,dc=com" +ldap_suffix_dc: "example" diff --git a/ldap/tasks/main.yml b/ldap/tasks/main.yml index c28c01fe..84bed58d 100644 --- a/ldap/tasks/main.yml +++ b/ldap/tasks/main.yml @@ -6,8 +6,82 @@ - slapd - ldap-utils - ldapvi + - shelldap + +- name: "Is /root/.ldapvirc present ?" + stat: + path: /root/.ldapvirc + check_mode: no + register: root_ldapvirc_path - name: apg package is installed apt: name: apg state: present + when: not root_ldapvirc_path.stat.exists + +- name: create a password for cn=admin + command: "apg -n 1 -m 16 -M lcN" + register: ldap_admin_password + changed_when: False + when: not root_ldapvirc_path.stat.exists + +- name: create a password for cn=nagios + command: "apg -n 1 -m 16 -M lcN" + register: ldap_nagios_password + changed_when: False + when: not root_ldapvirc_path.stat.exists + +- name: hash password for cn=admin + command: "slappasswd -s {{ ldap_admin_password.stdout }}" + register: ldap_admin_password_ssha + changed_when: False + when: not root_ldapvirc_path.stat.exists + +- name: hash password for cn=nagios + command: "slappasswd -s {{ ldap_nagios_password.stdout }}" + register: ldap_nagios_password_ssha + changed_when: False + when: not root_ldapvirc_path.stat.exists + +- name: create ldapvirc config + template: + src: ldapvirc.j2 + dest: /root/.ldapvirc + mode: "0640" + when: not root_ldapvirc_path.stat.exists + +- name: upload ldap initial config + template: + src: config_ldapvi.j2 + dest: /root/evolinux_ldap_config.ldapvi + mode: "0640" + when: not root_ldapvirc_path.stat.exists + +- name: upload ldap initial entries + template: + src: first-entries.ldif.j2 + dest: /root/evolinux_ldap_first-entries.ldif + mode: "0640" + when: not root_ldapvirc_path.stat.exists + +- name: inject config + command: ldapvi -Y EXTERNAL -h ldapi:// --ldapmodify /root/evolinux_ldap_config.ldapvi + environment: + TERM: xterm + when: not root_ldapvirc_path.stat.exists + +- name: inject first entries + command: slapadd -l /root/evolinux_ldap_first-entries.ldif + when: not root_ldapvirc_path.stat.exists + +- name: upload custom schema + copy: + src: "{{ ldap_schema }}" + dest: "/root/{{ ldap_schema }}" + mode: "0640" + when: not root_ldapvirc_path.stat.exists and ldap_schema is defined + +- name: inject custom schema + command: "ldapadd -Y EXTERNAL -H ldapi:/// -f /root/{{ ldap_schema }}" + when: not root_ldapvirc_path.stat.exists and ldap_schema is defined diff --git a/ldap/templates/config_ldapvi.j2 b/ldap/templates/config_ldapvi.j2 new file mode 100644 index 00000000..9be8044c --- /dev/null +++ b/ldap/templates/config_ldapvi.j2 @@ -0,0 +1,8 @@ +modify: olcDatabase={1}mdb,cn=config +olcSuffix: {{ ldap_suffix }} +olcRootDN: cn=admin,{{ ldap_suffix }} +olcRootPW: {{ ldap_admin_password_ssha.stdout }} +olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break +olcAccess: {1}to attrs=userPassword by self write by anonymous auth by dn="cn=admin,{{ ldap_suffix }}" write by dn="cn=perl,ou=ldapusers,{{ ldap_suffix }}" write by * none +olcAccess: {2}to attrs=shadowLastChange by self write by dn="cn=admin,{{ ldap_suffix }}" write by dn="cn=perl,ou=ldapusers,{{ ldap_suffix }}" write by * read +olcAccess: {3}to * by self write by dn="cn=admin,{{ ldap_suffix }}" write by dn="cn=perl,ou=ldapusers,{{ ldap_suffix }}" write by * read diff --git a/ldap/templates/first-entries.ldif.j2 b/ldap/templates/first-entries.ldif.j2 new file mode 100644 index 00000000..56828636 --- /dev/null +++ b/ldap/templates/first-entries.ldif.j2 @@ -0,0 +1,30 @@ +dn: {{ ldap_suffix }} +objectClass: top +objectClass: dcObject +objectClass: organization +o: {{ ldap_suffix_dc }} +dc: {{ ldap_suffix_dc }} + +dn: cn=admin,{{ ldap_suffix }} +objectClass: simpleSecurityObject +objectClass: organizationalRole +cn: admin +description: LDAP administrator +userPassword: {{ ldap_admin_password_ssha.stdout }} + +dn: ou=ldapusers,{{ ldap_suffix }} +objectClass: top +objectClass: organizationalUnit +ou: ldapusers + +dn: cn=perl,ou=ldapusers,{{ ldap_suffix }} +objectClass: simpleSecurityObject +objectClass: organizationalRole +cn: perl +userPassword: {{ ldap_admin_password_ssha.stdout }} + +dn: cn=nagios,ou=ldapusers,{{ ldap_suffix }} +objectClass: simpleSecurityObject +objectClass: organizationalRole +cn: nagios +userPassword: {{ ldap_nagios_password_ssha.stdout }} diff --git a/ldap/templates/ldapvirc.j2 b/ldap/templates/ldapvirc.j2 new file mode 100644 index 00000000..e61a7524 --- /dev/null +++ b/ldap/templates/ldapvirc.j2 @@ -0,0 +1,6 @@ +profile default +host: ldap://127.0.0.1 +base: {{ ldap_suffix }} +user: cn=admin,{{ ldap_suffix }} +bind: simple +password: {{ ldap_admin_password.stdout }} diff --git a/nagios-nrpe/templates/evolix.cfg.j2 b/nagios-nrpe/templates/evolix.cfg.j2 index 45223167..d85f9844 100644 --- a/nagios-nrpe/templates/evolix.cfg.j2 +++ b/nagios-nrpe/templates/evolix.cfg.j2 @@ -28,6 +28,7 @@ command[check_ldap]=/usr/lib/nagios/plugins/check_ldap -3 -H localhost -D cn=nag command[check_ldaps]=/usr/lib/nagios/plugins/check_ldaps -3 -H localhost -b {{ nagios_nrpe_ldap_dc }} command[check_imap]=/usr/lib/nagios/plugins/check_imap -H localhost command[check_imaps]=/usr/lib/nagios/plugins/check_imap -S -H localhost -p 993 +command[check_imapproxy]=/usr/lib/nagios/plugins/check_imap -H localhost -p 1143 command[check_pop]=/usr/lib/nagios/plugins/check_pop -H localhost command[check_pops]=/usr/lib/nagios/plugins/check_pop -S -H localhost -p 995 command[check_ftp]=/usr/lib/nagios/plugins/check_ftp -H localhost diff --git a/opendkim/files/opendkim-add.sh b/opendkim/files/opendkim-add.sh new file mode 100644 index 00000000..a7da1ce0 --- /dev/null +++ b/opendkim/files/opendkim-add.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +if [ "$#" -ne 1 ]; then + echo "Usage : $0 example.com" >&2 + exit 1 +fi + +domain="$(echo "$1"|xargs)" + +mkdir -pm 0750 "/etc/opendkim/keys/${domain}" +chown opendkim:opendkim "/etc/opendkim/keys/${domain}" + +if [ ! -f "/etc/opendkim/keys/${domain}/default.private" ]; then + cd "/etc/opendkim/keys/${domain}" + echo "Generate DKIM keys ..." + sudo -u opendkim opendkim-genkey -r -d "${domain}" + chmod 640 /etc/opendkim/keys/${domain}/* +fi + +grep -q "${domain}" /etc/opendkim/TrustedHosts +if [ "$?" -ne 0 ]; then + echo "Add ${domain} to TrustedHosts ..." + echo "${domain}" >> /etc/opendkim/TrustedHosts +fi + +grep -q "${domain}" /etc/opendkim/KeyTable +if [ "$?" -ne 0 ]; then + echo "Add ${domain} to KeyTable ..." + echo "default._domainkey.${domain} ${domain}:default:/etc/opendkim/keys/${domain}/default.private" >> /etc/opendkim/KeyTable +fi + +grep -q "${domain}" /etc/opendkim/SigningTable +if [ "$?" -ne 0 ]; then + echo "Add ${domain} to SigningTable ..." + echo "*@${domain} default._domainkey.${domain}" >> /etc/opendkim/SigningTable +fi + +systemctl reload opendkim +if [ "$?" -eq 0 ]; then + echo "OpenDKIM successfully reloaded" + echo "Public key is in : /etc/opendkim/keys/${domain}/default.txt" + exit 0 +else + echo "An error has occurred while opendkim reload, please FIX configuration !" >&2 + exit 1 +fi diff --git a/opendkim/files/opendkim.conf b/opendkim/files/opendkim.conf new file mode 100644 index 00000000..c8c4d385 --- /dev/null +++ b/opendkim/files/opendkim.conf @@ -0,0 +1,18 @@ +UserID opendkim:opendkim +Socket inet:54321@127.0.0.1 +PidFile /var/run/opendkim/opendkim.pid +OversignHeaders From +TrustAnchorFile /usr/share/dns/root.key +Selector default +Canonicalization relaxed/relaxed +ExternalIgnoreList refile:/etc/opendkim/TrustedHosts +InternalHosts refile:/etc/opendkim/TrustedHosts +KeyTable refile:/etc/opendkim/KeyTable +LogResults Yes +LogWhy Yes +Mode sv +SigningTable refile:/etc/opendkim/SigningTable +Syslog Yes +SyslogSuccess Yes +TemporaryDirectory /var/tmp +UMask 007 diff --git a/opendkim/handlers/main.yml b/opendkim/handlers/main.yml new file mode 100644 index 00000000..ccf166a8 --- /dev/null +++ b/opendkim/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: reload opendkim + systemd: + name: opendkim + state: reloaded + +- name: restart opendkim + systemd: + name: opendkim + state: restarted diff --git a/opendkim/tasks/main.yml b/opendkim/tasks/main.yml new file mode 100644 index 00000000..d491cd39 --- /dev/null +++ b/opendkim/tasks/main.yml @@ -0,0 +1,95 @@ +--- +- name: install OpenDKIM + apt: + name: "{{ item }}" + state: present + with_items: + - opendkim + - opendkim-tools + tags: + - opendkim + +- name: create keys directory + file: + name: "{{ item }}" + state: directory + owner: opendkim + group: opendkim + mode: "0750" + with_items: + - '/etc/opendkim' + - '/etc/opendkim/keys' + tags: + - opendkim + +- name: add 127.0.0.1 to TrustedHosts + lineinfile: + dest: '/etc/opendkim/TrustedHosts' + line: '127.0.0.1' + create: True + owner: opendkim + group: opendkim + mode: "0640" + notify: reload opendkim + tags: + - opendkim + +- name: create config files + file: + name: "/etc/opendkim/{{ item }}" + state: touch + owner: opendkim + group: opendkim + mode: "0640" + with_items: + - 'KeyTable' + - 'SigningTable' + changed_when: False + tags: + - opendkim + +- name: copy OpenDKIM config + copy: + src: opendkim.conf + dest: /etc/opendkim.conf + mode: "0644" + force: yes + notify: restart opendkim + tags: + - opendkim + +- name: ensure opendkim is started and enabled + systemd: + name: opendkim + state: started + enabled: True + tags: + - opendkim + +- name: check if /usr is a partition + shell: "mount | grep 'on /usr type'" + args: + warn: no + changed_when: False + failed_when: False + register: usr_partition + check_mode: no + tags: + - opendkim + +- name: mount /usr in rw + command: mount -o remount,rw /usr + args: + warn: no + changed_when: False + when: usr_partition.rc == 0 + tags: + - opendkim + +- name: deploy opendkim-add.sh script + copy: + src: opendkim-add.sh + dest: /usr/share/scripts/opendkim-add.sh + mode: "0750" + tags: + - opendkim diff --git a/postfix/README.md b/postfix/README.md index 67f56298..04bf879a 100644 --- a/postfix/README.md +++ b/postfix/README.md @@ -4,9 +4,10 @@ Installation and basic configuration of Postfix. ## Tasks -Minimal configuration is in `tasks/main.yml` and optional customization in : +Minimal configuration is in `tasks/minimal.yml` and optional customization in : * `slow_transport.yml` : slow transport to specific destination. +* `packmail.yml` : config for virtual mail accounts with OpenLDAP ## Available variables @@ -14,5 +15,7 @@ Main variables are : * `postfix_hostname` : hostname for Postfix ; * `postfix_slow_transport` : enable customization for delivrability. +* `postfix_force_main_cf` : force copy of main.cf +* `postfix_packmail` : install an Evolix Packmail instead of lite postfix config The full list of variables (with default values) can be found in `defaults/main.yml`. diff --git a/postfix/defaults/main.yml b/postfix/defaults/main.yml index f0673d65..55ab72cd 100644 --- a/postfix/defaults/main.yml +++ b/postfix/defaults/main.yml @@ -1,3 +1,5 @@ --- postfix_hostname: "{{ ansible_fqdn }}" -postfix_slow_transport_include: False +postfix_force_main_cf: False +postfix_packmail: False +postfix_slow_transport_include: "{{ postfix_packmail }}" diff --git a/postfix/files/cn4evolix.ldif b/postfix/files/cn4evolix.ldif new file mode 100644 index 00000000..a17532ad --- /dev/null +++ b/postfix/files/cn4evolix.ldif @@ -0,0 +1,63 @@ +dn: cn={4}evolix,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: {4}evolix +olcAttributeTypes: {0}( 1.3.6.1.4.1.24331.22.1.1 NAME 'maildrop' DESC 'mail fo + rward' SUP mail ) +olcAttributeTypes: {1}( 1.3.6.1.4.1.24331.22.1.2 NAME 'mailacceptinggeneralid' + DESC 'mail alias' SUP mail ) +olcAttributeTypes: {2}( 1.3.6.1.4.1.24331.22.1.3 NAME 'isActive' DESC 'boolean + to verify an global account is active or not' EQUALITY booleanMatch SYNTAX 1 + .3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: {3}( 1.3.6.1.4.1.24331.22.1.4 NAME 'accountActive' DESC 'bo + olean to verify if an mail account is active' EQUALITY booleanMatch SYNTAX 1. + 3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: {4}( 1.3.6.1.4.1.24331.22.1.5 NAME 'authsmtpActive' DESC 'b + oolean to verify if SMTP-AUTH is enabled for entry' EQUALITY booleanMatch SYN + TAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: {5}( 1.3.6.1.4.1.24331.22.1.6 NAME 'courierActive' DESC 'bo + olean to verify if Courier POP/IMAP is enabled for entry' EQUALITY booleanMat + ch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: {6}( 1.3.6.1.4.1.24331.22.1.7 NAME 'webmailActive' DESC 'bo + olean to verify if webmail is enabled for entry' EQUALITY booleanMatch SYNTAX + 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: {7}( 1.3.6.1.4.1.24331.22.1.8 NAME 'isAdmin' DESC 'boolean + to verify if entry is admin for entry' EQUALITY booleanMatch SYNTAX 1.3.6.1.4 + .1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: {8}( 1.3.6.1.4.1.24331.22.1.9 NAME 'postfixTransport' DESC + 'transport for Postfix' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.11 + 5.121.1.26{20} SINGLE-VALUE ) +olcAttributeTypes: {9}( 1.3.6.1.4.1.24331.22.1.10 NAME 'domain' DESC 'Postfix + domain' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTA + X 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: {10}( 1.3.6.1.4.1.24331.22.1.11 NAME 'quota' DESC 'Courier + maildir quota' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1. + 26 SINGLE-VALUE ) +olcAttributeTypes: {11}( 1.3.6.1.4.1.24331.22.1.16 NAME 'vacationActive' DESC + 'A flag, for marking the user as being away' EQUALITY booleanMatch SYNTAX 1.3 + .6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: {12}( 1.3.6.1.4.1.24331.22.1.17 NAME 'vacationInfo' DESC 'A + bsentee note to leave behind, while on vacation' EQUALITY octetStringMatch SY + NTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE ) +olcAttributeTypes: {13}( 1.3.6.1.4.1.24331.22.1.18 NAME 'vacationStart' DESC ' + Beginning of vacation' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115. + 121.1.40 SINGLE-VALUE ) +olcAttributeTypes: {14}( 1.3.6.1.4.1.24331.22.1.19 NAME 'vacationEnd' DESC 'En + d of vacation' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 + SINGLE-VALUE ) +olcAttributeTypes: {15}( 1.3.6.1.4.1.24331.22.1.20 NAME 'vacationForward' DESC + 'Where to forward mails to, while on vacation' EQUALITY caseIgnoreIA5Match S + UBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} + ) +olcAttributeTypes: {16}( 1.3.6.1.4.1.24331.22.1.21 NAME 'smbActive' DESC 'bool + ean to verify if an Samba account is active' EQUALITY booleanMatch SYNTAX 1.3 + .6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcObjectClasses: {0}( 1.3.6.1.4.1.24331.22.2.1 NAME 'mailAccount' DESC 'LDAP/ + Unix mail account or virtual account' SUP top AUXILIARY MUST ( uid $ mailacce + ptinggeneralid ) MAY ( accountActive $ authsmtpActive $ quota $ isActive $ co + urierActive $ webmailActive $ isAdmin $ vacationActive $ vacationInfo $ vacat + ionStart $ vacationEnd $ vacationForward $ maildrop ) ) +olcObjectClasses: {1}( 1.3.6.1.4.1.24331.22.2.2 NAME 'mailAlias' DESC 'Mail al + iasing/forwarding entry' SUP top STRUCTURAL MUST ( mailacceptinggeneralid $ m + aildrop ) MAY ( cn $ isActive ) ) +olcObjectClasses: {2}( 1.3.6.1.4.1.24331.22.2.4 NAME 'postfixDomain' DESC 'Pos + tfix domain' SUP posixGroup STRUCTURAL MAY ( postfixTransport $ isActive ) ) diff --git a/postfix/files/filter b/postfix/files/filter new file mode 100644 index 00000000..586574a1 --- /dev/null +++ b/postfix/files/filter @@ -0,0 +1 @@ +# Default empty file diff --git a/postfix/files/spam.sh b/postfix/files/spam.sh new file mode 100644 index 00000000..10d5e62a --- /dev/null +++ b/postfix/files/spam.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +#set -x + +umask 022 + +tmp_file=$(mktemp) + +tmp=$(mktemp -d) + +if [ -f $tmp_file ] ; + then rm $tmp_file ; +fi + +sleep $[ $RANDOM / 1024 ] + +# Postfix +cd $tmp + +wget -q -t 3 http://antispam00.evolix.org/spam/client.access -O $tmp_file +cp $tmp_file /etc/postfix/client.access +rm $tmp_file + +wget -q -t 3 http://antispam00.evolix.org/spam/sender.access -O $tmp_file +cp $tmp_file /etc/postfix/sender.access +rm $tmp_file + +wget -q -t 3 http://antispam00.evolix.org/spam/recipient.access -O $tmp_file +cp $tmp_file /etc/postfix/recipient.access +rm $tmp_file + +wget -q -t 3 http://antispam00.evolix.org/spam/header_kill -O $tmp_file +cp $tmp_file /etc/postfix/header_kill +rm $tmp_file + +wget -q -t 3 http://antispam00.evolix.org/spam/sa-blacklist.access -O sa-blacklist.access +wget -q -t 3 http://antispam00.evolix.org/spam/sa-blacklist.access.md5 -O $tmp_file +if md5sum -c $tmp_file > /dev/null && [ -s sa-blacklist.access ] ; then + cp sa-blacklist.access /etc/postfix/sa-blacklist.access +fi +rm sa-blacklist.access +rm $tmp_file + +/usr/sbin/postmap hash:/etc/postfix/client.access +/usr/sbin/postmap hash:/etc/postfix/sender.access +/usr/sbin/postmap hash:/etc/postfix/recipient.access +/usr/sbin/postmap -r hash:/etc/postfix/sa-blacklist.access + +wget -q -t 3 http://antispam00.evolix.org/spam/spamd.cidr -O spamd.cidr +wget -q -t 3 http://antispam00.evolix.org/spam/spamd.cidr.md5 -O $tmp_file +if md5sum -c $tmp_file > /dev/null && [ -s spamd.cidr ] ; then + cp spamd.cidr /etc/postfix/spamd.cidr +fi +rm spamd.cidr +rm $tmp_file + + +# SpamAssassin +cd $tmp +wget -q -t 3 http://antispam00.evolix.org/spam/evolix_rules.cf -O evolix_rules.cf +wget -q -t 3 http://antispam00.evolix.org/spam/evolix_rules.cf.md5 -O $tmp_file +if md5sum -c $tmp_file > /dev/null && [ -s evolix_rules.cf ] ; then + dpkg -l spamassassin 2>&1 | grep -v "no packages found matching" | grep -q ^ii && cp evolix_rules.cf /etc/spamassassin + dpkg -l spamassassin 2>&1 | grep -v "no packages found matching" | grep -q ^ii && /etc/init.d/spamassassin reload > /dev/null + if [ -d /etc/spamassassin/sa-update-hooks.d ]; then + run-parts --lsbsysinit /etc/spamassassin/sa-update-hooks.d + fi +fi + +# ClamAV +cd $tmp +wget -q -t 3 http://antispam00.evolix.org/spam/evolix.ndb -O evolix.ndb +wget -q -t 3 http://antispam00.evolix.org/spam/evolix.ndb.md5 -O $tmp_file +dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && chown clamav: evolix.ndb +if md5sum -c $tmp_file > /dev/null && [ -s evolix.ndb ] ; then + dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && cp -a evolix.ndb /var/lib/clamav/ +fi +wget -q -t 3 http://antispam00.evolix.org/spam/evolix.hsb -O evolix.hsb +wget -q -t 3 http://antispam00.evolix.org/spam/evolix.hsb.md5 -O $tmp_file +dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && chown clamav: evolix.hsb +if md5sum -c $tmp_file > /dev/null && [ -s evolix.hsb ] ; then + dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && cp -a evolix.hsb /var/lib/clamav/ +fi +dpkg -l clamav-daemon 2>&1 | grep -v "no packages found matching" | grep -q ^ii && /etc/init.d/clamav-daemon reload-database > /dev/null +rm $tmp_file + +rm -rf $tmp diff --git a/postfix/meta/main.yml b/postfix/meta/main.yml index a4cc6bd0..3c7b219a 100644 --- a/postfix/meta/main.yml +++ b/postfix/meta/main.yml @@ -13,7 +13,9 @@ galaxy_info: versions: - jessie -dependencies: [] - # List your role dependencies here, one per line. - # Be sure to remove the '[]' above if you add dependencies - # to this list. +dependencies: + - { role: ldap, ldap_schema: 'cn4evolix.ldif', when: postfix_packmail == True } + - { role: spamassasin, when: postfix_packmail == True } + - { role: clamav, when: postfix_packmail == True } + - { role: opendkim, when: postfix_packmail == True } + - { role: dovecot, when: postfix_packmail == True } diff --git a/postfix/tasks/main.yml b/postfix/tasks/main.yml index 77a4fb95..714787d6 100644 --- a/postfix/tasks/main.yml +++ b/postfix/tasks/main.yml @@ -1,30 +1,17 @@ -- name: ensure packages are installed - apt: - name: '{{ item }}' - state: present - with_items: - - postfix - - mailgraph - +--- - name: check if main.cf is default shell: grep -v -E "^(myhostname|mydestination|mailbox_command)" /etc/postfix/main.cf | md5sum - changed_when: False check_mode: no register: default_main_cf + tags: + - postfix -- name: create minimal main.cf - template: - src: evolinux_main.cf.j2 - dest: /etc/postfix/main.cf - owner: root - group: root - mode: "0644" - force: yes - when: default_main_cf.stdout == "5450c05d65878e99dad696c7c722e511 -" or - default_main_cf.stdout == "30022953f1f61f002bfb72e163ecb27e -" - notify: restart postfix +- include: minimal.yml + when: postfix_packmail == False -- meta: flush_handlers +- include: packmail.yml + when: postfix_packmail == True - include: slow_transport.yml when: postfix_slow_transport_include diff --git a/postfix/tasks/minimal.yml b/postfix/tasks/minimal.yml new file mode 100644 index 00000000..99b99003 --- /dev/null +++ b/postfix/tasks/minimal.yml @@ -0,0 +1,24 @@ +--- +- name: ensure packages are installed + apt: + name: '{{ item }}' + state: present + with_items: + - postfix + tags: + - postfix + +- name: create minimal main.cf + template: + src: evolinux_main.cf.j2 + dest: /etc/postfix/main.cf + owner: root + group: root + mode: "0644" + force: yes + notify: restart postfix + when: postfix_force_main_cf == True or + default_main_cf.stdout == "5450c05d65878e99dad696c7c722e511 -" or + default_main_cf.stdout == "30022953f1f61f002bfb72e163ecb27e -" + tags: + - postfix diff --git a/postfix/tasks/packmail.yml b/postfix/tasks/packmail.yml new file mode 100644 index 00000000..69d41581 --- /dev/null +++ b/postfix/tasks/packmail.yml @@ -0,0 +1,128 @@ +--- +- name: ensure packages are installed + apt: + name: '{{ item }}' + state: present + with_items: + - postfix + - postfix-ldap + - postfix-policyd-spf-python + - mailgraph + tags: + - postfix + +- name: create packmail main.cf + template: + src: packmail_main.cf.j2 + dest: /etc/postfix/main.cf + owner: root + group: root + mode: "0644" + force: yes + notify: restart postfix + when: postfix_force_main_cf == True or + default_main_cf.stdout == "5450c05d65878e99dad696c7c722e511 -" or + default_main_cf.stdout == "30022953f1f61f002bfb72e163ecb27e -" + tags: + - postfix + +- name: deploy packmail master.cf + template: + src: packmail_master.cf.j2 + dest: /etc/postfix/master.cf + mode: "0644" + notify: restart postfix + tags: + - postfix + +- name: copy default filter files + copy: + src: filter + dest: "/etc/postfix/{{ item }}" + force: no + with_items: + - virtual + - client.access + - client.access_local + - header_kill + - header_kill_local + - recipient.access + - recipient.access_local + - sa-blacklist.access + - sender.access + - sender.access_local + - spamd.cidr + register: postfix_copy_filter + tags: + - postfix + +- name: postmap filter files + command: "postmap /etc/postfix/{{ item }}" + with_items: + - virtual + - client.access + - client.access_local + - header_kill + - header_kill_local + - recipient.access + - recipient.access_local + - sa-blacklist.access + - sender.access + - sender.access_local + - spamd.cidr + when: postfix_copy_filter.changed + tags: + - postfix + +- name: deploy ldap postfix config + template: + src: "{{ item }}.j2" + dest: "/etc/postfix/{{ item }}" + mode: "0644" + with_items: + - virtual_aliases.cf + - virtual_domains.cf + - virtual_mailboxes.cf + notify: restart postfix + tags: + - postfix + +- name: update ansible_mounts facts + setup: + filter: ansible_mounts + tags: + - postfix + +- name: mount /usr in rw + command: mount -o remount,rw /usr + args: + warn: no + changed_when: false + when: item.mount == '/usr' and item.options | match(".*ro.*") + with_items: "{{ ansible_mounts }}" + tags: + - postfix + +- name: copy spam.sh script + copy: + src: spam.sh + dest: /usr/share/scripts/spam.sh + mode: "0700" + tags: + - postfix + +- name: enable spam.sh cron + lineinfile: + dest: /etc/cron.d/spam + line: "42 * * * * /usr/share/scripts/spam.sh" + create: yes + state: present + mode: "0640" + tags: + - postfix + +- name: update antispam list + command: /usr/share/scripts/spam.sh + changed_when: false + tags: + - postfix diff --git a/postfix/tasks/slow_transport.yml b/postfix/tasks/slow_transport.yml index 3bf8ae6d..2f4cab1e 100644 --- a/postfix/tasks/slow_transport.yml +++ b/postfix/tasks/slow_transport.yml @@ -1,10 +1,12 @@ --- - - name: slow transport is defined in master.cf lineinfile: dest: /etc/postfix/master.cf regexp: "^slow " line: "slow unix - - n - - smtp" + notify: restart postfix + tags: + - postfix - name: list of providers for slow transport lineinfile: @@ -21,24 +23,5 @@ - "hotmail.fr slow:" - "hotmail.com slow:" notify: postmap transport - -- name: main.cf is configured for slow transports - blockinfile: - dest: /etc/postfix/main.cf - marker: "# {mark} Slow transports configuration (installed by Ansible)" - block: | - minimal_backoff_time = 2h - maximal_backoff_time = 6h - maximal_queue_lifetime = 4d - queue_run_delay = 100s - bounce_queue_lifetime = 1d - initial_destination_concurrency = 5 - default_destination_concurrency_limit = 20 - slow_destination_rate_delay = 0 - slow_destination_concurrency_limit = 1 - slow_destination_concurrency_failed_cohort_limit = 100 - slow_destination_recipient_limit = 25 - transport_maps = hash:$config_directory/transport - notify: restart postfix - -- meta: flush_handlers + tags: + - postfix diff --git a/postfix/templates/evolinux_main.cf.j2 b/postfix/templates/evolinux_main.cf.j2 index 429e6602..e42a413f 100644 --- a/postfix/templates/evolinux_main.cf.j2 +++ b/postfix/templates/evolinux_main.cf.j2 @@ -13,3 +13,19 @@ recipient_delimiter = + inet_interfaces = all inet_protocols = ipv4 disable_vrfy_command = yes + +{% if postfix_slow_transport_include == True %} +# Slow transports configuration +minimal_backoff_time = 2h +maximal_backoff_time = 6h +maximal_queue_lifetime = 4d +queue_run_delay = 100s +bounce_queue_lifetime = 1d +initial_destination_concurrency = 5 +default_destination_concurrency_limit = 20 +slow_destination_rate_delay = 0 +slow_destination_concurrency_limit = 1 +slow_destination_concurrency_failed_cohort_limit = 100 +slow_destination_recipient_limit = 25 +transport_maps = hash:$config_directory/transport +{% endif %} diff --git a/postfix/templates/packmail_main.cf.j2 b/postfix/templates/packmail_main.cf.j2 new file mode 100644 index 00000000..9f14ec50 --- /dev/null +++ b/postfix/templates/packmail_main.cf.j2 @@ -0,0 +1,423 @@ +## fichier principal de configuration de Postfix +## commentaires de Gregory Colpart reg AT evolix DOT fr +## version 1.0 : 1ere version publique (05.04.2010) + +######################## +# Section : Emplacements +######################## + +# Repertoire ou se trouvent les commandes de postfix [OBLIGATOIRE] +#par defaut, = $program_directory +command_directory = /usr/sbin + +# Repertoire ou se trouvent les demons de postfix [OBLIGATOIRE] +#par defaut, = $program_directory +daemon_directory = /usr/lib/postfix/sbin + +# Variable pour indiquer les emplacements des commandes et demons de postfix +#program_directory = /usr/lib/postfix + +# Repertoire contenant les fichiers de boites aux lettres +#par defaut, = /var/mail +#mail_spool_directory = + +# Repertoire de la file d'attente de postfix +#par defaut, = /var/spool/postfix +#queue_directory = + +# Boites aux lettres +#par defaut, = +home_mailbox = Maildir/ + +# Transmettre les mails a un MDA +#par defaut, = +#mailbox_command = /usr/bin/procmail + +# Separateur entre noms d'utilisateur et extensions d'adresse +# mettre + pour integration avec amavis +#par defaut, = +recipient_delimiter = + + +# Controle si le repertoire existe (souvent pour les systemes de fichiers montes) +#par defaut, = no +#require_home_directory = + +# Commande pour transmettre le courrier a un MDA +#par defaut, = +#mailbox_command = /usr/bin/procmail + +# Banniere SMTP affichee +#par default, = $myhostname ESMTP $mail_name +smtpd_banner = $myhostname ESMTP mail server + +# Groupe des commandes set-gid ayant des acces en ecriture +#par defaut, = postdrop +# setgid_group = postdrop + +# Produire des "biff notifications" aux utilisateurs pour +# prevenir de l'arrivee de nouveaux mails +# par default, = yes +#biff = no + + +#################### +# Section : domaines +#################### + +# Indique le nom d'hote pleinement qualifie ou se trouve postfix [OBLIGATOIRE] +#par defaut, = [retour de la commande Unix hostname] +myhostname = {{ ansible_fqdn }} + +# Variable indiquant le domaine dans lequel se trouve la machine +#par defaut, = [partie domain de la variable $myhostname] +#mydomain = + +# Liste des noms de domaine (ou IP) consideres comme local +#par defaut, = $myhostname, localhost.$mydomain, localhost +mydestination = $myhostname + +# Indique le domaine apparaissant dans le courrier envoye +#par defaut, = $myhostname +myorigin = {{ ansible_fqdn }} + +# Liste de domaine fonctionnant UNIQUEMENT avec des alias virtuels +#par defaut, = $virtual_alias_maps +#virtual_alias_domains = [ domaines avec alias virtuels ] + +# Liste de domaine fonctionnant avec des comptes virtuels +#par defaut, = $virtual_mailbox_maps +virtual_mailbox_domains = ldap:$config_directory/virtual_domains.cf + +# Repertoire de base de l'espace de stockage +#par defaut, = +virtual_mailbox_base = / + +# Ajoute $mydomain aux adresse ne compoirtant que la partie hote sans le domaine +#par defaut, = yes +#append_dot_mydomain = no + +# Ajoute $myorigin aux adresses ne comportant pas de composante de domaine +#par defaut, = yes +#append_at_myorigin = no + +# Liste de domaines cachant des sous-domaines internes +#par defaut, = +#masquerade_domains = + +# A l'exception de certains comptes : +#par defaut, = +#masquerade_exceptions = root, admin + +# Champs d'application de la reecriture des sous-domaines caches +#par defaut, = envelope_sender, header_sender, header_recipient +#masquerade_classes = + +# Sites eligibles pour un vidage rapide (postqueue -s [domain.tld]) +#par defaut, = $relay_domains +#fast_flush_domains = + +# Interfaces sur lesquelles ecoutent postfix +#par defaut, = all +#inet_interfaces = all + +# Adresse IP externe du firewall/proxy si derriere NAT ou proxy +# evite principalement les boucles si MX secondaire et MX primaire indisponible +#par defaut, = +#proxy_interfaces = [adresse IP] + +# Domaines acceptes pour faire relai (MX 2aire) +#relay_domains = [domaine a relayer] + + +########################### +# Section : base de donnees +########################### + +# Liste des bases de donnees utilisees par l'agent de distribution locale +# Pour regenerer une base de donnees : postalias /etc/aliases (par ex) +#par defaut, = hash:/etc/aliases, nis:mail.aliases +alias_maps = hash:/etc/aliases + +# Liste des bases de donnees locales +# Pour regenerer avec newaliases +#par defaut, = hash:/etc/aliases +alias_database = hash:/etc/aliases + +# Chemin vers la commande newaliases +#par defaut, = /usr/bin/newaliases +#newaliases_path = + +# Base de donnes d'alias virtuels +# ne pas oublier : postmap /etc/postfix/virtual +#par defaut, = $virtual_maps +virtual_alias_maps = hash:$config_directory/virtual, ldap:$config_directory/virtual_aliases.cf + +# Base de donners des boites virtuelles +# ne pas oublier : postmap /etc/postfix/vmailbox +#par defaut, = +virtual_mailbox_maps = ldap:$config_directory/virtual_mailboxes.cf + +virtual_uid_maps = static:5000 +virtual_gid_maps = static:5000 +virtual_transport = dovecot +dovecot_destination_recipient_limit = 1 + +# Reecriture des adresses +#par defaut, = +#canonical_maps = hash:/etc/postfix/canonical + +# Reecriture des adresses a l'arrivee (ecrase $canonical_maps) +#par defaut, = +#recipient_canonical_maps = hash:/etc/postfix/canonical + +# Reecriture des adresses au depart +#par defaut, = +#sender_canonical_maps = hash:/etc/postfix/canonical + +# Adresses changees +#relocated_maps = hash:/etc/postfix/relocated + +# Boite pour receptionner tous les utilisateurs inconnus +#luser_relay = spam + +# Liste de base de donnees contenant les adresses locales permettant de rejeter les messages aux utilisateurs inconnus +# (sera nulle pour recuperer les courriels vers les utilisateurs inconnus) +#par defaut, = proxy:unix:passwd.byname $alias_maps +#local_recipient_maps = + +# MAILING-LIST nommee xx +# dans le fichier /etc/aliases : +# xx: user1@domain1 user2@domain2 etc. +# owner-xx: admin@domain +# Utiliser ou non l'alias xx-owner comme adresse d'enveloppe d'expedition +#par defaut, = yes +#owner_request_special = + +# Utiliser l'adresse relle de l'admin au lieu de xx-owner +#par defaut, = no +#expand_owner_alias = + + +########################################### +# Section : parametres de la file d'attente +########################################### + +# Lorsqu'un message n'a pas ete delivre, Postfix adjoint une marque indiquant le moment ou la prochaine tentaive pourra avoir lieu + +# Delai au-dela duquel les messages non delivres seront renvoyes a l'expediteur +#par defaut, = 5d +#maximal_queue_lifetime = + +# Delai au-dela duquel les *bounces* non delivres ne seront plus envoyes +#par defaut, = 5d +bounce_queue_lifetime = 1d + +# Intervalle de temps ou postfix examinera la file +# Il examine notamment la file deferred pour voir si de NOUVEAUX messages sont arrives +# Il faut aussi que la marque indique qu'ils soient prets +#par defaut, = 1000s +#queue_run_delay = + +# A chaque echec, le delai de la prochaine distribution double, avec les restrictions suivantes : +# Delai minimal +#par defaut, = 1000s +#minimal_backoff_time = +# Delai maximal +#par defaut, = 4000s +#maximal_backoff_time = + +# Si maxproc est vide (master.cf), nombre maximal est : +#par defaut, = 100 +#default_process_limit = + +# Nombre maximal de destinataires stockes en memoire par qmgr pour un transport particulier +#par defaut, = 10000 +#default_recipient_limit = + +# Nombre limitant de messages envoyes simultanement INITIALEMENT pour une destination particuliere +# (forcement majoree par maxproc du master.cf ou $default_process_limit) +#par defaut, = 5 +#initial_destination_concurrency = + +# Une fois ces messages distribues, si il reste des messages dans la file d'attente pour cette destination +# particuliere, postfix augmente le nombre de tentative tant qu'il ne detecte pas de probleme avec +# la destination, avec la limite suivante : +#par defaut, = 20 +#default_destination_concurrency_limit = + +# Cette limite peut etre differente selon le type de transport utilise : +#par defaut, = $default_destination_concurrency_limit +#lmtp_destination_concurrency_limit = +#par defaut, = 2 +#local_destination_concurrency_limit = +#par defaut, = $default_destination_concurrency_limit +#relay_destination_concurrency_limit = +#par defaut, = $default_destination_concurrency_limit +#smtp_destination_concurrency_limit = +#par defaut, = $default_destination_concurrency_limit +#virtual_destination_concurrency_limit = + +# On peut aussi limiter le nombre maximum de destinataire pour un meme message +# Si le nombre de destinataire depasse la limite, postfix divise en groupe d'adresses plus petites et envoie des copies distinctes du message +#par defaut, = 10000 +#default_destination_recipient_limit = +#par defaut, = $default_destination_recipient_limit +#lmtp_destination_recipient_limit = +#par defaut, = 1 +#local_destination_recipient_limit = +#par defaut, = 20000 +#qmgr_message_recipient_limit = +#par defaut, = $default_destination_recipient_limit +#relay_destination_recipient_limit = +#par defaut, = $default_destination_recipient_limit +#smtp_destination_recipient_limit = +#par defaut, = 1000 +#smtpd_recipient_limit = +#par defaut, = $default_destination_recipient_limit +#virtual_destination_recipient_limit = + +# Nombre maximum de destinataires pour un transport lorsque priorite superieure de transport +#par defaut, = 1000 +#default_extra_recipient_limit = + +slow_destination_rate_delay = 0 +slow_destination_concurrency_limit = 1 +slow_destination_recipient_limit = 25 +slow_destination_concurrency_failed_cohort_limit = 100 + +# Types d'incidents a rapporter +# resource : message non delivre pour probleme de ressource +# software : message non delivre pour probleme de logiciels +# policy : envoie le transcription smtp d'un message rejete par restrictions +# protocol : envoie toute transcription smtp erronee +# delay : envoie les entetes de messages differes +# bounce : envoie les entetes de tous les message renvoyes +# 2bounce : envoie les entetes de tous les messages renvoyes non delivres +#par defaut, = resource, software +notify_classes = resource, software, bounce, 2bounce, delay, policy, protocol + +# A qui les reporter ? +#Pour delay +#par defaut, = postmaster +delay_notice_recipient = delay +#Pour policy, protocol, resource, software +#par defaut, = postmaster +error_notice_recipient = error +#Pour bounce +#par defaut, = postmaster +bounce_notice_recipient = bounce +#Pour 2bounce +#par defaut, = postmaster +2bounce_notice_recipient = bounce + + +######################## +# Section : restrictions +######################## + +# Restrictions au depart de la conversation +#par defaut, = +smtpd_client_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + cidr:$config_directory/spamd.cidr, + +# Restrictions au niveau de la commande HELO/EHLO +#par defaut, = +smtpd_helo_restrictions = + reject_invalid_hostname + +# Restrictions au niveau de la commande MAIL FROM +#par defaut, = +smtpd_sender_restrictions = + permit_mynetworks, + check_sender_access hash:$config_directory/sa-blacklist.access + +# Restrictions au niveau de la commande MAIL FROM +#par defaut, = permit_mynetworks, reject_unauth_destination +smtpd_recipient_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_unauth_destination, + check_policy_service unix:private/policyd-spf, + check_client_access hash:$config_directory/client.access_local, + check_client_access hash:$config_directory/client.access, + check_sender_access hash:$config_directory/sender.access_local, + check_sender_access hash:$config_directory/sender.access, + check_recipient_access hash:$config_directory/recipient.access_local, + check_recipient_access hash:$config_directory/recipient.access, + reject_unlisted_recipient, + reject_unknown_sender_domain, + reject_non_fqdn_sender, + reject_unauth_pipelining, + +policyd-spf_time_limit = 3600 + +header_checks = + regexp:$config_directory/header_kill_local, + regexp:$config_directory/header_kill + +transport_maps = hash:$config_directory/transport + +# Attendre la commande 'RCPT TO' avant d'evaluer les restrictions ? +# (peut poser pb avec certains clients et permet d'avoir renseignements suppl) +#par defaut, = yes +#smtpd_delay_reject = + +# Definition des plages IP appartenant a mynetworks +#par defaut, toutes les plages d'adresses IPv4 (et IPv6) des interfaces +mynetworks = 127.0.0.0/8,[::1]/128,10.0.0.0/16 + +# Exiger la commande HELO/EHLO +#par defaut, = no +smtpd_helo_required = yes + +# Exiger syntaxe conforme dans les commandes MAIL FROM ou RCPT TO +#par defaut, = no +strict_rfc821_envelopes = yes + +# Rejeter le courrier provenant d'une adresse inexistante ? +#par defaut, = no +#smtpd_reject_unlisted_sender = + +# Rejeter le courrier a destination d'une adresse inexistante ? +#par defaut, = yes +#smtpd_reject_unlisted_recipient = + + +####################### +# Section : Chiffrement +####################### + +smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem +smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key +smtpd_use_tls=yes +smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache +smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache + +# SASL +smtpd_sasl_auth_enable = yes +broken_sasl_auth_clients = yes +smtpd_sasl_type = dovecot +smtpd_sasl_path = private/auth-client + +# Amavis and OpenDKIM +content_filter = smtp-amavis:[127.0.0.1]:10024 +smtpd_milters = inet:[127.0.0.1]:54321 +non_smtpd_milters = inet:[127.0.0.1]:54321 + +{% if postfix_slow_transport_include == True %} +# Slow transports configuration +minimal_backoff_time = 2h +maximal_backoff_time = 6h +maximal_queue_lifetime = 4d +queue_run_delay = 100s +bounce_queue_lifetime = 1d +initial_destination_concurrency = 5 +default_destination_concurrency_limit = 20 +slow_destination_rate_delay = 0 +slow_destination_concurrency_limit = 1 +slow_destination_concurrency_failed_cohort_limit = 100 +slow_destination_recipient_limit = 25 +transport_maps = hash:$config_directory/transport +{% endif %} diff --git a/postfix/templates/packmail_master.cf.j2 b/postfix/templates/packmail_master.cf.j2 new file mode 100644 index 00000000..7326cb35 --- /dev/null +++ b/postfix/templates/packmail_master.cf.j2 @@ -0,0 +1,171 @@ +# +# Postfix master process configuration file. For details on the format +# of the file, see the master(5) manual page (command: "man 5 master" or +# on-line: http://www.postfix.org/master.5.html). +# +# Do not forget to execute "postfix reload" after editing this file. +# +# ========================================================================== +# service type private unpriv chroot wakeup maxproc command + args +# (yes) (yes) (no) (never) (100) +# ========================================================================== +smtp inet n - y - - smtpd +#smtp inet n - y - 1 postscreen +#smtpd pass - - y - - smtpd +#dnsblog unix - - y - 0 dnsblog +#tlsproxy unix - - y - 0 tlsproxy +submission inet n - y - - smtpd + -o syslog_name=postfix/submission + -o smtpd_tls_security_level=encrypt + -o smtpd_sasl_auth_enable=yes + -o smtpd_client_restrictions=permit_sasl_authenticated,reject + -o milter_macro_daemon_name=ORIGINATING +smtps inet n - y - - smtpd + -o syslog_name=postfix/smtps + -o smtpd_tls_wrappermode=yes + -o smtpd_sasl_auth_enable=yes + -o smtpd_client_restrictions=permit_sasl_authenticated,reject + -o milter_macro_daemon_name=ORIGINATING +#628 inet n - y - - qmqpd +pickup unix n - y 60 1 pickup +cleanup unix n - y - 0 cleanup +qmgr unix n - n 300 1 qmgr +#qmgr unix n - n 300 1 oqmgr +tlsmgr unix - - y 1000? 1 tlsmgr +rewrite unix - - y - - trivial-rewrite +bounce unix - - y - 0 bounce +defer unix - - y - 0 bounce +trace unix - - y - 0 bounce +verify unix - - y - 1 verify +flush unix n - y 1000? 0 flush +proxymap unix - - n - - proxymap +proxywrite unix - - n - 1 proxymap +smtp unix - - y - - smtp +# When relaying mail as backup MX, disable fallback_relay to avoid MX loops +relay unix - - y - - smtp + -o smtp_fallback_relay= +# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5 +showq unix n - y - - showq +error unix - - y - - error +retry unix - - y - - error +discard unix - - y - - discard +local unix - n n - - local +virtual unix - n n - - virtual +lmtp unix - - y - - lmtp +anvil unix - - y - 1 anvil +scache unix - - y - 1 scache +# +# ==================================================================== +# Interfaces to non-Postfix software. Be sure to examine the manual +# pages of the non-Postfix software to find out what options it wants. +# +# Many of the following services use the Postfix pipe(8) delivery +# agent. See the pipe(8) man page for information about ${recipient} +# and other message envelope options. +# ==================================================================== +# +# maildrop. See the Postfix MAILDROP_README file for details. +# Also specify in main.cf: maildrop_destination_recipient_limit=1 +# +maildrop unix - n n - - pipe + flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient} +# +# ==================================================================== +# +# Recent Cyrus versions can use the existing "lmtp" master.cf entry. +# +# Specify in cyrus.conf: +# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4 +# +# Specify in main.cf one or more of the following: +# mailbox_transport = lmtp:inet:localhost +# virtual_transport = lmtp:inet:localhost +# +# ==================================================================== +# +# Cyrus 2.1.5 (Amos Gouaux) +# Also specify in main.cf: cyrus_destination_recipient_limit=1 +# +#cyrus unix - n n - - pipe +# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user} +# +# ==================================================================== +# Old example of delivery via Cyrus. +# +#old-cyrus unix - n n - - pipe +# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user} +# +# ==================================================================== +# +# See the Postfix UUCP_README file for configuration details. +# +uucp unix - n n - - pipe + flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) +# +# Other external delivery methods. +# +ifmail unix - n n - - pipe + flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient) +bsmtp unix - n n - - pipe + flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient +scalemail-backend unix - n n - 2 pipe + flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension} +mailman unix - n n - - pipe + flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py + ${nexthop} ${user} + +slow unix - - n - - smtp + +policyd-spf unix - n n - 0 spawn + user=policyd-spf argv=/usr/bin/policyd-spf + +dovecot unix - n n - - pipe + flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient} + +scan unix - - y - 10 smtp +localhost:10026 inet n - y - 10 smtpd + -o content_filter= + -o local_recipient_maps= + -o relay_recipient_maps= + -o myhostname=filter.mynetwork.local + -o smtpd_helo_restrictions= + -o smtpd_client_restrictions= + -o smtpd_sender_restrictions= + -o smtpd_recipient_restrictions=permit_mynetworks,reject + -o mynetworks=127.0.0.0/8 + +smtp-amavis unix - - y - 2 lmtp + -o lmtp_data_done_timeout=1200 + -o lmtp_send_xforward_command=yes + +127.0.0.1:10025 inet n - y - - smtpd + -o content_filter= + -o smtpd_milters= + -o local_recipient_maps= + -o relay_recipient_maps= + -o smtpd_restriction_classes= + -o smtpd_delay_reject=no + -o smtpd_client_restrictions=permit_mynetworks,reject + -o smtpd_helo_restrictions= + -o smtpd_sender_restrictions= + -o smtpd_recipient_restrictions=permit_mynetworks,reject + -o smtpd_data_restrictions=reject_unauth_pipelining + -o smtpd_end_of_data_restrictions= + -o mynetworks=127.0.0.0/8 + -o strict_rfc821_envelopes=yes + -o smtpd_error_sleep_time=0 + -o smtpd_soft_error_limit=1001 + -o smtpd_hard_error_limit=1000 + -o smtpd_client_connection_count_limit=0 + -o smtpd_client_connection_rate_limit=0 + -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks + +pre-cleanup unix n - n - 0 cleanup + -o virtual_alias_maps= + -o canonical_maps= + -o sender_canonical_maps= + -o recipient_canonical_maps= + -o masquerade_domains= + -o always_bcc= + -o sender_bcc_maps= + -o recipient_bcc_maps= diff --git a/postfix/templates/virtual_aliases.cf.j2 b/postfix/templates/virtual_aliases.cf.j2 new file mode 100644 index 00000000..1a6e5f9c --- /dev/null +++ b/postfix/templates/virtual_aliases.cf.j2 @@ -0,0 +1,5 @@ +search_base = {{ ldap_suffix }} +query_filter = (&(mailacceptinggeneralid=%u@%d)(isActive=TRUE)) +result_attribute = maildrop +version = 3 +aliases_scope = sub diff --git a/postfix/templates/virtual_domains.cf.j2 b/postfix/templates/virtual_domains.cf.j2 new file mode 100644 index 00000000..97e9ebb3 --- /dev/null +++ b/postfix/templates/virtual_domains.cf.j2 @@ -0,0 +1,5 @@ +search_base = {{ ldap_suffix }} +query_filter = (&(cn=%s)(objectClass=postfixDomain)(isActive=TRUE)) +result_attribute = cn +scope = sub +version = 3 diff --git a/postfix/templates/virtual_mailboxes.cf.j2 b/postfix/templates/virtual_mailboxes.cf.j2 new file mode 100644 index 00000000..0796bdf6 --- /dev/null +++ b/postfix/templates/virtual_mailboxes.cf.j2 @@ -0,0 +1,5 @@ +search_base = {{ ldap_suffix }} +query_filter = (&(mailacceptinggeneralid=%s)(objectClass=mailAccount)(isActive=TRUE)(accountActive=TRUE)) +result_attribute = homeDirectory +scope = sub +version = 3 diff --git a/spamassasin/files/sa-update.sh b/spamassasin/files/sa-update.sh new file mode 100644 index 00000000..b138c285 --- /dev/null +++ b/spamassasin/files/sa-update.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +# Evolix sa-update, based on: +# Duncan Findlay +# duncf@debian.org + +mail=$(grep EVOMAINTMAIL /etc/evomaintenance.cf | cut -d'=' -f2) +test -x /usr/bin/sa-update || exit 0 +test -x /etc/init.d/spamassassin || exit 0 + +# If there's a problem with the ruleset or configs, print the output +# of spamassassin --lint (which will typically get emailed to root) +# and abort. +die_with_lint() { + su debian-spamd -c "spamassassin --lint -D 2>&1" + exit 1 +} + +do_compile() { +# Compile, if rules have previously been compiled, and it's possible + if [ -x /usr/bin/re2c -a -x /usr/bin/sa-compile \ + -a -d /var/lib/spamassassin/compiled ]; then + su debian-spamd -c "sa-compile --quiet" + # Fixup perms -- group and other should be able to + # read and execute, but never write. Works around + # sa-compile's failure to obey umask. + chmod -R go-w,go+rX /var/lib/spamassassin/compiled + fi +} + +# Tell a running spamd to reload its configs and rules. +reload() { + # Reload + if which invoke-rc.d >/dev/null 2>&1; then + invoke-rc.d spamassassin reload > /dev/null + else + /etc/init.d/spamassassin reload > /dev/null + fi + if [ -d /etc/spamassassin/sa-update-hooks.d ]; then + run-parts --lsbsysinit /etc/spamassassin/sa-update-hooks.d + fi +} + +# Update +umask 022 +su debian-spamd -c "sa-update --gpghomedir /var/lib/spamassassin/sa-update-keys" + +case $? in + 0) + # got updates! + su debian-spamd -c "spamassassin --lint" || die_with_lint + do_compile + reload + echo -e "Les règles SpamAsassin ont été mises à jour. Merci de reporter toute anomalie." | \ + mail -s "SpamAsassin's rules updated." $mail + ;; + 1) + # no updates + exit 0 + ;; + 2) + # lint failed! + die_with_lint + ;; + *) + echo "sa-update failed for unknown reasons" 1>&2 + ;; +esac diff --git a/spamassasin/files/spamassassin.cf b/spamassasin/files/spamassassin.cf new file mode 100644 index 00000000..821f51d4 --- /dev/null +++ b/spamassasin/files/spamassassin.cf @@ -0,0 +1,117 @@ +#required_score 5 -> assure par Amavis +report_safe 0 +#rewrite_header Subject [SPAM] -> assure par Amavis +add_header all Report _REPORT_ + +# filtre bayesien +# mkdir -p /var/spool/spam/ && chown amavis /var/spool/spam/ +use_bayes 1 +bayes_auto_learn 1 +bayes_path /var/spool/spam/bayes +bayes_file_mode 0777 + +# AWL : AutoWhitelist +# mkdir -p /var/spool/spam/ && chown amavis /var/spool/spam/ +loadplugin Mail::SpamAssassin::Plugin::AWL +use_auto_whitelist 1 +auto_whitelist_path /var/spool/spam/auto_whitelist +auto_whitelist_file_mode 0666 + +# LANG TESTS +loadplugin Mail::SpamAssassin::Plugin::TextCat +ok_languages en fr es it +ok_locales en fr es it + +score BODY_8BITS 1.500 +score CHARSET_FARAWAY 3.200 +score CHARSET_FARAWAY_HEADER 3.200 +score HTML_CHARSET_FARAWAY 0.500 +score MIME_CHARSET_FARAWAY 2.450 +score UNWANTED_LANGUAGE_BODY 2.800 + +# DCC +# use_dcc 1 => un plugin maintenant... +score DCC_CHECK 2.9 + +# RAZOR : http://razor.sourceforge.net +use_razor2 1 +score RAZOR2_CHECK 2.9 +score RAZOR2_CF_RANGE_51_100 1.3 + +# pyzor : http://pyzor.sourceforge.net/ +use_pyzor 0 + +# RBL (Realtime Blackhole List) +skip_rbl_checks 0 +score RCVD_IN_BL_SPAMCOP_NET 3 + +# misc +score HELO_DYNAMIC_IPADDR 0.3 +score BIZ_TLD 0.1 +score PRIORITY_NO_NAME 0.2 + +# disable HTML tests + +score HTML_MESSAGE 0 +score HTML_00_10 0 +score HTML_10_20 0 +score HTML_20_30 0 +score HTML_30_40 0 +score HTML_40_50 0 +score HTML_50_60 0 +score HTML_60_70 0 +score HTML_70_80 0 +score HTML_80_90 0 +score HTML_90_100 0 +#score HTML_COMMENT_8BITS 0 +score UPPERCASE_25_50 0 +score UPPERCASE_50_75 0 +score UPPERCASE_75_100 0 +score MIME_HTML_ONLY 0.1 +# From http://maxime.ritter.eu.org/Spam/user_prefs +# Trop de faux negatifs avec BAYES_(0|1|2|3|4)* +score BAYES_00 0 0 -0.01 -0.01 +score BAYES_01 0 0 -0.01 -0.01 +score BAYES_10 0 0 -0.01 -0.01 +score BAYES_20 0 0 -0.01 -0.01 +score BAYES_30 0 0 -0.01 -0.01 +score BAYES_40 0 0 -0.01 -0.01 +score BAYES_44 0 0 -0.01 -0.01 +score BAYES_50 0 0 0.1 0.1 +score BAYES_56 0 0 0.5 0.5 +score BAYES_60 0 0 1.0 1.0 +score BAYES_70 0 0 2.5 2.5 +score BAYES_80 0 0 3.5 3.5 +score BAYES_90 0 0 4.5 4.5 +score BAYES_99 0 0 8.0 8.0 + +score RCVD_IN_SORBS_DUL 0.3 +score SUBJ_ILLEGAL_CHARS 0 +score RCVD_IN_NJABL_DUL 0.3 + +score ADDRESS_IN_SUBJECT 0.1 + +score HELO_LH_HOME 1.0 + +#internal_networks 192.168.XXX/24 +trusted_networks 62.212.111.216 88.179.18.233 85.118.59.50 31.170.8.0/21 +#score ALL_TRUSTED 0.3 +score HELO_DYNAMIC_IPADDR 0.3 + +score FORGED_MUA_OUTLOOK 0.5 + +# Eudora sucks +score EXTRA_MPART_TYPE 0.1 +score MIME_BOUND_EQ_REL 0.1 +score MIME_QP_LONG_LINE 0.1 + +# SMTP senders *have* dynamic IP addresses +# A.B.C.D.dnsbl.sorbs.net -> 127.0.0.10 +score RCVD_IN_DYNABLOCK 0 +score HELO_DYNAMIC_IPADDR 0.3 +score RCVD_IN_SORBS 0.1 +score RCVD_IN_PBL 0.1 +score RCVD_IN_SORBS_DUL 0 + +# old bug... +score FH_DATE_PAST_20XX 0.0 diff --git a/spamassasin/handlers/main.yml b/spamassasin/handlers/main.yml new file mode 100644 index 00000000..7479d736 --- /dev/null +++ b/spamassasin/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart spamassassin + service: + name: spamassassin + state: restarted diff --git a/spamassasin/meta/main.yml b/spamassasin/meta/main.yml new file mode 100644 index 00000000..510b6855 --- /dev/null +++ b/spamassasin/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - { role: amavis } diff --git a/spamassasin/tasks/main.yml b/spamassasin/tasks/main.yml new file mode 100644 index 00000000..4f010650 --- /dev/null +++ b/spamassasin/tasks/main.yml @@ -0,0 +1,68 @@ +--- +- name: install SpamAssasin + apt: + name: "{{ item }}" + state: present + with_items: + - spamassassin + - evomaintenance + tags: + - spamassassin + +- name: configure SpamAssasin + copy: + src: spamassassin.cf + dest: /etc/spamassassin/local_evolix.cf + mode: "0644" + notify: restart spamassassin + tags: + - spamassassin + +- name: enable SpamAssasin + replace: + dest: /etc/default/spamassassin + regexp: 'ENABLED=0' + replace: 'ENABLED=1' + notify: restart spamassassin + tags: + - spamassassin + +- name: update ansible_mounts facts + setup: + filter: ansible_mounts + tags: + - spamassassin + +- name: mount /usr in rw + command: mount -o remount,rw /usr + args: + warn: no + changed_when: false + when: item.mount == '/usr' and item.options | match(".*ro.*") + with_items: "{{ ansible_mounts }}" + tags: + - spamassassin + +- name: copy sa-update.sh script + copy: + src: sa-update.sh + dest: /usr/share/scripts/sa-update.sh + mode: "0750" + tags: + - spamassassin + +- name: enable sa-update.sh cron + lineinfile: + dest: /etc/cron.d/sa-update + line: "42 6 5 1,4,7,10 * /usr/share/scripts/sa-update.sh" + create: yes + state: present + mode: "0640" + tags: + - spamassassin + +- name: update SpamAssasin's rules + command: /usr/share/scripts/sa-update.sh + changed_when: false + tags: + - spamassassin diff --git a/webapps/evoadmin-mail/defaults/main.yml b/webapps/evoadmin-mail/defaults/main.yml new file mode 100644 index 00000000..000be699 --- /dev/null +++ b/webapps/evoadmin-mail/defaults/main.yml @@ -0,0 +1,23 @@ +--- +general_alert_email: "root@localhost" +evoadminmail_contact_email: Null +evoadminmail_bounce_email: "{{ evoadminmail_contact_email }}" + +evoadminmail_username: evoadmin-mail +evoadminmail_home_dir: "/home/{{ evoadminmail_username }}" +evoadminmail_document_root: "{{ evoadminmail_home_dir }}/www" +evoadminmail_log_dir: "{{ evoadminmail_home_dir }}/log" +evoadminmail_scripts_dir: /usr/share/scripts/ +evoadminmail_host: "evoadminmail.{{ ansible_fqdn }}" + +evoadminmail_enable_vhost: True + +evoadminmail_tpl_servername: "{{ ansible_fqdn }}" +evoadminmail_tpl_address: "{{ ansible_default_ipv4.address }}" +evoadminmail_tpl_phpmyadmin_url: Null +evoadminmail_tpl_cgi_suffix: Null +evoadminmail_tpl_signature: evoadmin +evoadminmail_tpl_mail_from: root@localhost +evoadminmail_tpl_mail_bcc: Null +evoadminmail_tpl_mail_standard: "{{ general_alert_email }}" +evoadminmail_tpl_mail_urgent: "{{ general_alert_email }}" diff --git a/webapps/evoadmin-mail/handlers/main.yml b/webapps/evoadmin-mail/handlers/main.yml new file mode 100644 index 00000000..c4cdb576 --- /dev/null +++ b/webapps/evoadmin-mail/handlers/main.yml @@ -0,0 +1,6 @@ +--- + +- name: reload apache2 + service: + name: apache2 + state: reloaded diff --git a/webapps/evoadmin-mail/tasks/config.yml b/webapps/evoadmin-mail/tasks/config.yml new file mode 100644 index 00000000..00e342f3 --- /dev/null +++ b/webapps/evoadmin-mail/tasks/config.yml @@ -0,0 +1,17 @@ +--- + +- name: "Create /etc/evolinux" + file: + dest: "/etc/evolinux" + recurse: yes + state: directory + +#- name: Configure web-add config file +# template: +# src: web-add.conf.j2 +# dest: /etc/evolinux/web-add.conf +# +#- name: Configure web-add template file for mail +# template: +# src: web-mail.tpl.j2 +# dest: "{{ evoadminmail_scripts_dir }}/web-mail.tpl" diff --git a/webapps/evoadmin-mail/tasks/main.yml b/webapps/evoadmin-mail/tasks/main.yml new file mode 100644 index 00000000..0647bbcb --- /dev/null +++ b/webapps/evoadmin-mail/tasks/main.yml @@ -0,0 +1,19 @@ +--- + +- include: packages.yml + +- include: user.yml + +- include: config.yml + +- include: ssl.yml + +- include: web.yml + +- name: enable evoadmin-mail link in default site index + lineinfile: + dest: /var/www/index.html + state: present + regexp: "EvoAdmin-mail" + line: '
  • Interface admin mail (EvoAdmin-mail)
  • ' + insertbefore: "" diff --git a/webapps/evoadmin-mail/tasks/packages.yml b/webapps/evoadmin-mail/tasks/packages.yml new file mode 100644 index 00000000..ea9b176e --- /dev/null +++ b/webapps/evoadmin-mail/tasks/packages.yml @@ -0,0 +1,16 @@ +--- + +- include_role: + name: apt + tasks_from: evolix_public.yml + +- meta: flush_handlers + +- name: Install PHP packages + apt: + name: '{{ item }}' + state: present + with_items: + - php-pear + - php-log + - php-crypt-chap diff --git a/webapps/evoadmin-mail/tasks/remount_usr_rw.yml b/webapps/evoadmin-mail/tasks/remount_usr_rw.yml new file mode 100644 index 00000000..8c51aee2 --- /dev/null +++ b/webapps/evoadmin-mail/tasks/remount_usr_rw.yml @@ -0,0 +1,15 @@ +--- +- name: Get mount options for partitions + shell: "mount | grep 'on /usr type'" + args: + warn: no + register: mount + changed_when: False + failed_when: False + when: not ansible_check_mode + +- name: Remount /usr if it is a partition and it is not mounted in rw + command: "mount -o remount,rw /usr" + when: mount.rc == 0 and not mount.stdout_lines.0 | search("rw") + args: + warn: no diff --git a/webapps/evoadmin-mail/tasks/ssl.yml b/webapps/evoadmin-mail/tasks/ssl.yml new file mode 100644 index 00000000..3dd91590 --- /dev/null +++ b/webapps/evoadmin-mail/tasks/ssl.yml @@ -0,0 +1,24 @@ +--- + + +- name: ssl-cert package is installed + apt: + name: ssl-cert + state: present + +- name: Create private key and csr for default site ({{ ansible_fqdn }}) + command: openssl req -newkey rsa:2048 -sha256 -nodes -keyout /etc/ssl/private/{{ evoadminmail_host }}.key -out /etc/ssl/{{ evoadminmail_host }}.csr -batch -subj "/CN={{ evoadminmail_host }}" + args: + creates: "/etc/ssl/private/{{ evoadminmail_host }}.key" + +- name: Adjust rights on private key + file: + path: /etc/ssl/private/{{ evoadminmail_host }}.key + owner: root + group: ssl-cert + mode: "0640" + +- name: Create certificate for default site + command: openssl x509 -req -days 3650 -sha256 -in /etc/ssl/{{ evoadminmail_host }}.csr -signkey /etc/ssl/private/{{ evoadminmail_host }}.key -out /etc/ssl/certs/{{ evoadminmail_host }}.crt + args: + creates: "/etc/ssl/certs/{{ evoadminmail_host }}.crt" diff --git a/webapps/evoadmin-mail/tasks/user.yml b/webapps/evoadmin-mail/tasks/user.yml new file mode 100644 index 00000000..7e4cb90c --- /dev/null +++ b/webapps/evoadmin-mail/tasks/user.yml @@ -0,0 +1,113 @@ +--- + +- name: Create evoadmin account + user: + name: "{{ evoadminmail_username }}" + comment: "Evoadmin Web Account" + home: "{{ evoadminmail_home_dir}}" + shell: /bin/bash + password: "!" + +- name: Create log/ directory + file: + path: "{{ evoadminmail_home_dir}}/log" + state: directory + owner: "{{ evoadminmail_username }}" + group: "{{ evoadminmail_username }}" + mode: "0750" + +- name: Create www-evoadminmail group + group: + name: "www-{{ evoadminmail_username }}" + state: present + +- name: "Create www-evoadmin (Debian 9 or later)" + user: + name: "www-{{ evoadminmail_username }}" + home: "{{ evoadminmail_home_dir}}/www" + shell: /bin/bash + createhome: no + when: ansible_distribution_major_version | version_compare('9', '>=') + +- name: Install Git + apt: + name: git + state: present + +- name: "Clone evoadmin repository (Debian 9 or later)" + git: + repo: https://forge.evolix.org/evoadmin-mail.git + dest: "{{ evoadminmail_document_root}}" + version: master + update: yes + when: ansible_distribution_major_version | version_compare('9', '>=') + +- name: "Change perms on evoadminmail document root" + file: + dest: "{{ evoadminmail_document_root }}" + owner: "www-{{ evoadminmail_username }}" + group: "{{ evoadminmail_username }}" + recurse: yes + +- name: "Copy connect.php" + template: + src: connect.php.j2 + dest: "{{ evoadminmail_document_root }}/htdocs/config/connect.php" + owner: "www-{{ evoadminmail_username }}" + group: "{{ evoadminmail_username }}" + when: ldap_admin_password is defined + +- name: "Copy conf.php" + template: + src: conf.php.j2 + dest: "{{ evoadminmail_document_root }}/htdocs/config/conf.php" + owner: "www-{{ evoadminmail_username }}" + group: "{{ evoadminmail_username }}" + +- name: create a password for evoadmin user + command: "apg -n 1 -m 16 -M lcN" + register: evoadminmail_admin_password + changed_when: False + +- name: upload ldif for evoadmin user + template: + src: evoadmin.ldif.j2 + dest: /root/evolinux_evoadminmail_admin.ldif + mode: "0640" + +- name: inject config + command: slapadd -l /root/evolinux_evoadminmail_admin.ldif + +- name: create log file + file: + dest: /var/log/evoadmin-mail.log + state: touch + owner: "www-{{ evoadminmail_username }}" + group: "adm" + mode: "0640" + +- include: remount_usr_rw.yml + when: evoadminmail_scripts_dir | search ("/usr") + +- name: "Create {{ evoadminmail_scripts_dir }}" + file: + dest: "{{ evoadminmail_scripts_dir }}" + # recurse: yes + mode: "0700" + state: directory + +# we use a shell command to have a "changed" thet really reflects the result. +- name: Fix permissions + shell: "chmod -R --verbose u=rwX,g=rX,o= {{ item }}" + register: command_result + changed_when: "'changed' in command_result.stdout" + # failed_when: False + with_items: + - "{{ evoadminmail_home_dir}}/www" + +#- name: Add evoadmin sudoers file +# template: +# src: sudoers.j2 +# dest: /etc/sudoers.d/evoadmin +# mode: "0600" +# validate: "visudo -cf %s" diff --git a/webapps/evoadmin-mail/tasks/web.yml b/webapps/evoadmin-mail/tasks/web.yml new file mode 100644 index 00000000..e7d915a3 --- /dev/null +++ b/webapps/evoadmin-mail/tasks/web.yml @@ -0,0 +1,30 @@ +--- + +- name: "Set custom values for PHP config (Debian 9 or later)" + ini_file: + dest: /etc/php/7.0/apache2/conf.d/zzz-evolinux-custom.ini + section: PHP + option: "disable_functions" + value: "shell-exec,system,passthru,putenv,popen,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority" + notify: reload apache2 + when: ansible_distribution_major_version | version_compare('9', '>=') + +- name: Install evoadminmail VHost + template: + src: evoadminmail.conf.j2 + dest: /etc/apache2/sites-available/evoadminmail.conf + notify: reload apache2 + +- name: Enable evoadminmail vhost + command: "a2ensite evoadminmail.conf" + register: cmd_a2ensite + changed_when: "'Enabling site' in cmd_a2ensite.stdout" + notify: reload apache2 + when: evoadminmail_enable_vhost + +- name: Disable evoadminmail vhost + command: "a2dissite evoadminmail.conf" + register: cmd_a2dissite + changed_when: "'Disabling site' in cmd_a2dissite.stdout" + notify: reload apache2 + when: not evoadminmail_enable_vhost diff --git a/webapps/evoadmin-mail/templates/conf.php.j2 b/webapps/evoadmin-mail/templates/conf.php.j2 new file mode 100644 index 00000000..bac22bfd --- /dev/null +++ b/webapps/evoadmin-mail/templates/conf.php.j2 @@ -0,0 +1,56 @@ + + * @version 1.0 + */ + +define("LDAP_URI","ldap://127.0.0.1"); +$ldap_servers = array('ldap://127.0.0.1'); +define("LDAP_BASE","{{ ldap_suffix }}"); +define("LDAP_ADMIN_DN","cn=admin,{{ ldap_suffix }}"); +define("LDAP_ADMIN_PASS","{{ ldap_admin_password.stdout }}"); + +define("SUDOBIN","/usr/bin/sudo"); +define("SUDOSCRIPT","/usr/share/scripts/evoadmin.sh"); +define("SUDOPASS","xxxxxx"); + +define('SERVEUR','localhost'); +define('SERVEURPORT',3306); +define('BASE','horde'); +define('NOM', 'horde'); +define('PASSE', 'xxxx'); + +?> diff --git a/webapps/evoadmin-mail/templates/evoadmin.ldif.j2 b/webapps/evoadmin-mail/templates/evoadmin.ldif.j2 new file mode 100644 index 00000000..389fdff9 --- /dev/null +++ b/webapps/evoadmin-mail/templates/evoadmin.ldif.j2 @@ -0,0 +1,12 @@ +dn: uid=evoadmin,{{ ldap_suffix }} +uid: evoadmin +cn: Evoadmin ADM +uidNumber: 4242 +gidNumber: 4242 +homeDirectory: /dev/null +isAdmin: TRUE +mailacceptinggeneralid: evoadmin@{{ ansible_fqdn }} +objectClass: mailAccount +objectClass: organizationalRole +objectClass: posixAccount +userPassword: {{ evoadminmail_admin_password.stdout }} diff --git a/webapps/evoadmin-mail/templates/evoadminmail.conf.j2 b/webapps/evoadmin-mail/templates/evoadminmail.conf.j2 new file mode 100644 index 00000000..026fe00d --- /dev/null +++ b/webapps/evoadmin-mail/templates/evoadminmail.conf.j2 @@ -0,0 +1,58 @@ + + ServerName {{ evoadminmail_host }} + Redirect permanent / https://{{ evoadminmail_host }}/ + + + + + # FQDN principal + ServerName {{ evoadminmail_host }} + #ServerAlias {{ evoadminmail_host }} + + # Repertoire principal + DocumentRoot {{ evoadminmail_document_root }}/htdocs/ + + # SSL + SSLEngine on + SSLCertificateFile /etc/ssl/certs/{{ evoadminmail_host }}.crt + SSLCertificateKeyFile /etc/ssl/private/{{ evoadminmail_host }}.key + SSLProtocol all -SSLv2 -SSLv3 + + # Propriete du repertoire + + #Options Indexes SymLinksIfOwnerMatch + Options SymLinksIfOwnerMatch + AllowOverride AuthConfig Limit FileInfo + Require all granted + + + # user - group (thanks to sesse@debian.org) + AssignUserID www-{{ evoadminmail_username }} {{ evoadminmail_username }} + + # LOG + CustomLog /var/log/apache2/access.log combined + CustomLog {{ evoadminmail_log_dir }}/access.log combined + ErrorLog {{ evoadminmail_log_dir }}/error.log + + # AWSTATS + SetEnv AWSTATS_FORCE_CONFIG {{ evoadminmail_username }} + + # REWRITE + UseCanonicalName On + RewriteEngine On + RewriteCond %{HTTP_HOST} !^{{ evoadminmail_host }}$ + RewriteRule ^/(.*) https://%{SERVER_NAME}/$1 [L,R] + + # PHP + #php_admin_flag engine off + #AddType text/html .html + #php_admin_flag display_errors On + #php_flag short_open_tag On + #php_flag register_globals On + #php_admin_value memory_limit 256M + #php_admin_value max_execution_time 60 + #php_admin_value upload_max_filesize 8M + #php_admin_flag allow_url_fopen Off + php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f www-{{ evoadminmail_username }}" + php_admin_value open_basedir "none" + diff --git a/webapps/evoadmin-mail/templates/sudoers.j2 b/webapps/evoadmin-mail/templates/sudoers.j2 new file mode 100644 index 00000000..4dfd71c1 --- /dev/null +++ b/webapps/evoadmin-mail/templates/sudoers.j2 @@ -0,0 +1,3 @@ +User_Alias EVOADMIN = www-evoadmin +Cmnd_Alias EVOADMIN_WEB = {{ evoadmin_scripts_dir | mandatory }}/web-*.sh, {{ evoadmin_scripts_dir | mandatory }}/ftpadmin.sh +EVOADMIN ALL=NOPASSWD: EVOADMIN_WEB diff --git a/webapps/evoadmin-mail/templates/web-add.conf.j2 b/webapps/evoadmin-mail/templates/web-add.conf.j2 new file mode 100644 index 00000000..86eabd29 --- /dev/null +++ b/webapps/evoadmin-mail/templates/web-add.conf.j2 @@ -0,0 +1,2 @@ +CONTACT_MAIL="{{ evoadmin_contact_email or general_alert_email | mandatory }}" +WWWBOUNCE_MAIL="{{ evoadmin_bounce_email or general_alert_email | mandatory }}" diff --git a/webapps/evoadmin-mail/templates/web-mail.tpl.j2 b/webapps/evoadmin-mail/templates/web-mail.tpl.j2 new file mode 100644 index 00000000..262995c3 --- /dev/null +++ b/webapps/evoadmin-mail/templates/web-mail.tpl.j2 @@ -0,0 +1,86 @@ +From: {{ evoadmin_tpl_mail_from }} +To: RCPTTO +Bcc: {{ evoadmin_tpl_mail_bcc }} +Subject: Parametres hebergement web : LOGIN + +Bonjour, + +Votre compte d'hebergement web a ete cree. + +********************************** +* CONNEXION SFTP/SSH +********************************** + +NOM DU SERVEUR : {{ evoadmin_tpl_servername }} +USER : LOGIN +PASSWORD : PASSE1 + +***************************************** +* Details sur l'environnement Apache/PHP +***************************************** + +URL du site : +http://{{ evoadmin_tpl_servername }} + +URL des stats : +http://{{ evoadmin_tpl_servername }}/cgi-RANDOM/awstats.pl +(acces par IP ou login a demander !) + +Repertoire de connexion : HOME_DIR/LOGIN/ +Repertoire pour site web : HOME_DIR/LOGIN/www/ + +Apache/PHP tourne en www-LOGIN:LOGIN c'est-a-dire qu'il a acces +uniquement *en lecture* aux differents fichiers/repertoires +(a condition d'avoir 'g=rx' sur les repertoires et 'g=r' sur les +fichiers ce qui est le comportement par defaut). + +Lorsqu'on a besoin d'autoriser *l'ecriture* pour certains +fichiers/repertoires, il suffit d'ajouter le droit 'g+w'. + +*********************************** +* MySQL +*********************************** + +SERVEUR : 127.0.0.1 +PORT DU SERVEUR : 3306 +USER : LOGIN +PASSWORD : PASSE2 +NOM BASE : DBNAME +URL interface d'admin : +{{ evoadmin_tpl_phpmyadmin_url }} + +*********************************** +* Rappels divers +*********************************** + +Votre nom de domaine doit etre configure pour pointer +sur l'adresse IP {{ evoadmin_tpl_address }} (enregistrement DNS A) +ou etre un alias de {{ evoadmin_tpl_servername }} (enregistrement DNS CNAME). + +Si vous avez besoin de faire des tests, vous devez +ajouter la ligne suivante au fichier "/etc/hosts" sous Linux/Unix +ou au fichier "system32\drivers\etc\hosts" sous Windows NT/XP : +{{ evoadmin_tpl_address }} {{ evoadmin_tpl_servername }} + +Attention, par defaut, toutes les connexions vers l'exterieur +sont bloquees. Si vous avez besoin de recuperer des donnees +a l'exterieur (flux RSS, BDD externe, etc.), contactez nous +afin de mettre en oeuvre les autorisations necessaires. + +Afin de securiser au maximum le serveur, certaines URL +particulieres sont non autorisees pour eviter diverses +attaques (XSS, robots, trojans, injections, etc.). +Exemple d'URL refusee : +http://{{ evoadmin_tpl_servername }}/cmd32.exe +En cas de soucis avec votre application, prevenez-nous. + +Si vous desirez mettre en place des parametres particuliers +pour votre site (PHP, etc.) ou pour tout autre demande (scripts en crontab, +etc.), n'hesitez pas a nous contacter a l'adresse +{{ evoadmin_tpl_mail_standard }} (ou {{ evoadmin_tpl_mail_urgent }} si votre demande est +urgente). + + +Cordialement, +-- +{{ evoadmin_tpl_signature }} diff --git a/webapps/evoadmin-web/tasks/web.yml b/webapps/evoadmin-web/tasks/web.yml index 0944c2cd..59c41582 100644 --- a/webapps/evoadmin-web/tasks/web.yml +++ b/webapps/evoadmin-web/tasks/web.yml @@ -6,7 +6,7 @@ section: PHP option: "disable_functions" value: "shell-exec,system,passthru,putenv,popen" - notify: reload apache + notify: reload apache2 when: ansible_distribution_release == "jessie" - name: "Set custom values for PHP config (Debian 9 or later)" @@ -15,7 +15,7 @@ section: PHP option: "disable_functions" value: "shell-exec,system,passthru,putenv,popen" - notify: reload apache + notify: reload apache2 when: ansible_distribution_major_version | version_compare('9', '>=') - name: Install evoadmin VHost diff --git a/webapps/roundcube/defaults/main.yml b/webapps/roundcube/defaults/main.yml new file mode 100644 index 00000000..5e0c1a81 --- /dev/null +++ b/webapps/roundcube/defaults/main.yml @@ -0,0 +1,4 @@ +--- +roundcube_host: "roundcube.{{ ansible_fqdn }}" +roundcube_imap_host: "localhost" +roundcube_imap_port: 143 diff --git a/webapps/roundcube/handlers/main.yml b/webapps/roundcube/handlers/main.yml new file mode 100644 index 00000000..bdba6e6b --- /dev/null +++ b/webapps/roundcube/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart imapproxy + systemd: + name: imapproxy + state: restarted diff --git a/webapps/roundcube/tasks/main.yml b/webapps/roundcube/tasks/main.yml new file mode 100644 index 00000000..37ef1afe --- /dev/null +++ b/webapps/roundcube/tasks/main.yml @@ -0,0 +1,104 @@ +--- +- name: configure roundcube-core + debconf: + name: roundcube-core + question: "{{ item.key }}" + value: "{{ item.value }}" + vtype: "{{ item.type }}" + with_items: + - { key: 'roundcube/database-type', type: 'select', value: 'sqlite3' } + - { key: 'roundcube/db/basepath', type: 'string', value: '/var/lib/roundcube/' } + tags: + - roundcube + +- name: install Roundcube + apt: + name: "{{ item }}" + state: present + with_items: + - imapproxy + - roundcube + - roundcube-sqlite3 + - roundcube-plugins + - php-net-sieve + - php-zip + tags: + - roundcube + +- name: configure imapproxy imap host + lineinfile: + dest: /etc/imapproxy.conf + regexp: "^server_hostname" + line: "server_hostname {{ roundcube_imap_host }}" + notify: restart imapproxy + tags: + - roundcube + +- name: configure imapproxy imap port + lineinfile: + dest: /etc/imapproxy.conf + regexp: "^server_port" + line: "server_port {{ roundcube_imap_port }}" + notify: reload imapproxy + tags: + - roundcube + +- name: enable and start imapproxy + service: + name: imapproxy + state: started + enabled: True + tags: + - roundcube + +- name: configure roundcube imap host + lineinfile: + dest: /etc/roundcube/config.inc.php + regexp: "\\$config\\['default_host'\\]" + line: "$config['default_host'] = array('127.0.0.1');" + tags: + - roundcube + +- name: configure roudcube imap port + lineinfile: + dest: /etc/roundcube/config.inc.php + regexp: "\\$config\\['default_port'\\]" + insertafter: "\\$config\\['default_host'\\]" + line: "$config['default_port'] = 1143;" + tags: + - roundcube + +- name: configure managesieve plugin + copy: + src: /usr/share/roundcube/plugins/managesieve/config.inc.php.dist + dest: /etc/roundcube/plugins/managesieve/config.inc.php + mode: "0644" + remote_src: True + tags: + - roundcube + +- name: enable default plugins + replace: + dest: /etc/roundcube/config.inc.php + regexp: "^\\$config\\['plugins'\\] = array\\($" + replace: "$config['plugins'] = array('zipdownload','managesieve'" + tags: + - roundcube + +- name: deploy roundcube vhost + template: + src: apache2.conf.j2 + dest: /etc/apache2/sites-available/rouncube.conf + mode: "0640" + notify: reload apache2 + tags: + - roundcube + +- name: enable roundcube vhost + file: + src: /etc/apache2/sites-available/rouncube.conf + dest: /etc/apache2/sites-enabled/rouncube.conf + state: link + notify: reload apache2 + tags: + - roundcube diff --git a/webapps/roundcube/templates/apache2.conf.j2 b/webapps/roundcube/templates/apache2.conf.j2 new file mode 100644 index 00000000..47865c01 --- /dev/null +++ b/webapps/roundcube/templates/apache2.conf.j2 @@ -0,0 +1,46 @@ + + ServerName {{ roundcube_host }} + Redirect permanent / https://{{ roundcube_host }} + + + + + # FQDN principal + ServerName {{ roundcube_host }} + + # Repertoire principal + DocumentRoot /var/lib/roundcube/ + + # Return 503 if imapproxy doesn't run + + Redirect 503 / + + + Include /etc/roundcube/apache.conf + + # LOG + CustomLog /var/log/apache2/access.log vhost_combined + CustomLog /var/lib/roundcube/logs/access.log combined + ErrorLog /var/lib/roundcube/logs/error.log + + # REWRITE + UseCanonicalName On + RewriteEngine On + RewriteCond %{HTTP_HOST} !^{{ roundcube_host }}$ + RewriteRule ^/(.*) http://%{SERVER_NAME}/$1 [L,R] + + # PHP + #php_admin_flag engine off + #AddType text/html .html + #php_admin_flag display_errors On + #php_flag short_open_tag On + #php_flag register_globals On + #php_admin_value memory_limit 256M + #php_admin_value max_execution_time 60 + #php_admin_value upload_max_filesize 8M + #php_admin_flag allow_url_fopen Off + php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f www-roundcube" + php_admin_value error_log "/home/roundcube/log/php.log" + #php_admin_value open_basedir "/usr/share/php:/home/roundcube:/tmp" + +