Changeset - a822861bea4e
[Not reviewed]
roles/mail_server/molecule/default/group_vars/parameters-optional.yml
Show inline comments
 
---
 

	
 
mail_ldap_base_dn: dc=local
 
mail_ldap_url: ldap://ldap-server/
 
mail_ldap_tls_truststore: "{{ lookup('file', 'tests/data/x509/ca/chain-full.cert.pem') }}"
 
mail_ldap_postfix_password: postfixpassword
 
mail_ldap_dovecot_password: dovecotpassword
 
mail_server_minimum_tls_protocol: TLSv1.1
 
mail_server_tls_ciphers: "DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:\
 
DHE-RSA-AES256-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:\
 
ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:!aNULL:!MD5:!EXPORT"
 
mail_user: virtmail
 
mail_user_uid: 5000
 
mail_user_gid: 5000
 
imap_max_user_connections_per_ip: 2
 
imap_tls_certificate: "{{ lookup('file', 'tests/data/x509/server/{{ inventory_hostname }}_imap.cert.pem') }}"
 
imap_tls_key: "{{ lookup('file', 'tests/data/x509/server/{{ inventory_hostname }}_imap.key.pem') }}"
 
local_mail_aliases:
 
  root: "john.doe@domain1"
 
smtp_tls_certificate: "{{ lookup('file', 'tests/data/x509/server/{{ inventory_hostname }}_smtp.cert.pem') }}"
 
smtp_tls_key: "{{ lookup('file', 'tests/data/x509/server/{{ inventory_hostname }}_smtp.key.pem') }}"
 
imap_folder_separator: "."
 
smtp_rbl:
 
  - bl.spamcop.net
 
  - zen.spamhaus.org
 

	
 
mail_postmaster: "webmaster@parameters-optional"
 
smtp_allow_relay_from:
 
  - "{{ release_based_smtp_allow_relay_from[ansible_distribution_release] }}"
 
mail_message_size_limit: 20480001
 
mail_server_smtp_additional_configuration: |
 
  mail_name = MySMTP
 
  smtp_skip_5xx_greeting = no
 

	
 
# Variables dependant on distribution release.
 
release_based_smtp_allow_relay_from:
 
  bullseye: "192.168.56.41"
 
  bookworm: "192.168.56.21"
 

	
 
# common
 
ca_certificates:
 
  testca: "{{ lookup('file', 'tests/data/x509/ca/level1.cert.pem') }}"
 

	
 
# backup_client
 
enable_backup: true
 
backup_client_username: "bak-param-optional-{{ ansible_distribution_release }}"
 
backup_encryption_key: "{{ lookup('file', 'tests/data/gnupg/parameters-optional.asc') }}"
 
backup_server: ldap-server
 
backup_server_host_ssh_public_keys:
 
  - "{{ lookup('file', 'tests/data/ssh/server_rsa.pub') }}"
 
  - "{{ lookup('file', 'tests/data/ssh/server_ed25519.pub') }}"
 
  - "{{ lookup('file', 'tests/data/ssh/server_ecdsa.pub') }}"
 
backup_ssh_key: "{{ lookup('file', 'tests/data/ssh/parameters-optional' ) }}"
roles/mail_server/molecule/default/host_vars/ldap-server.yml
Show inline comments
 
---
 

	
 
# ldap_server role
 
ldap_admin_password: admin
 

	
 
ldap_server_consumers:
 
  - name: postfix
 
    password: postfixpassword
 
  - name: dovecot
 
    password: dovecotpassword
 
    state: present
 

	
 
ldap_server_domain: "local"
 
ldap_server_groups:
 
  - name: mail
 
ldap_server_organization: "Example"
 
ldap_server_tls_certificate: "{{ lookup('file', 'tests/data/x509/server/ldap-server_ldap.cert.pem') }}"
 
ldap_server_tls_key: "{{ lookup('file', 'tests/data/x509/server/ldap-server_ldap.key.pem') }}"
 

	
 
# common
 
ca_certificates:
 
  testca: "{{ lookup('file', 'tests/data/x509/ca/level1.cert.pem') }}"
 

	
 
# ldap_client
 
ldap_client_config:
 
  - comment: CA truststore
 
    option: TLS_CACERT
 
    value: /etc/ssl/certs/testca.cert.pem
 
  - comment: Ensure TLS is enforced
 
    option: TLS_REQCERT
 
    value: demand
 
  - comment: Base DN
 
    option: BASE
 
    value: dc=local
 
  - comment: URI
 
    option: URI
 
    value: ldapi:///
 

	
 
# backup_server role
 
backup_host_ssh_private_keys:
 
  rsa: "{{ lookup('file', 'tests/data/ssh/server_rsa') }}"
 
  ed25519: "{{ lookup('file', 'tests/data/ssh/server_ed25519') }}"
 
  ecdsa: "{{ lookup('file', 'tests/data/ssh/server_ecdsa') }}"
 
backup_clients:
 

	
 
  - server: param-optional-bullseye
 
    ip: 192.168.56.52
 
    public_key: "{{ lookup('file', 'tests/data/ssh/parameters-optional.pub') }}"
 

	
 
  - server: param-optional-bookworm
 
    ip: 192.168.56.32
 
    public_key: "{{ lookup('file', 'tests/data/ssh/parameters-optional.pub') }}"
roles/mail_server/molecule/default/molecule.yml
Show inline comments
 
@@ -5,164 +5,96 @@ dependency: {}
 
driver:
 
  name: vagrant
 
  safe_files:
 
    # Preserve the ClamAV database files from previous runs on the
 
    # clamav-database helper machine. Meant to avoid hitting hard
 
    # limits for database downloads and getting completely blocked.
 
    - "*/clamav-database/*"
 
  provider:
 
    name: virtualbox
 

	
 
lint:
 
  name: yamllint
 
  options:
 
    config-file: ../../.yamllint.yml
 

	
 
platforms:
 

	
 

	
 
  # Helpers
 
  # =======
 

	
 
  - name: clamav-database
 
    box: debian/bookworm64
 
    memory: 768
 
    cpus: 1
 
    provider_raw_config_args:
 
      - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']"
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.11
 
        network_name: private_network
 
        type: static
 
    config_options:
 
      synced_folder: true
 

	
 
  - name: ldap-server
 
    box: debian/bookworm64
 
    memory: 384
 
    cpus: 1
 
    provider_raw_config_args:
 
      - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']"
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.12
 
        network_name: private_network
 
        type: static
 

	
 

	
 
  # Debian 11 Bullseye
 
  # ================
 

	
 
  - name: client1-bullseye
 
    groups:
 
      - client
 
      - client-relay-allowed
 
      - bullseye
 
      - smtp-server-requiring-tls
 
    box: debian/bullseye64
 
    memory: 256
 
    cpus: 1
 
    provider_raw_config_args:
 
      - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']"
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.41
 
        network_name: private_network
 
        type: static
 

	
 
  - name: client2-bullseye
 
    groups:
 
      - client
 
      - client-relay-forbidden
 
      - bullseye
 
      - smtp-server-refusing-tls
 
    box: debian/bullseye64
 
    memory: 256
 
    cpus: 1
 
    provider_raw_config_args:
 
      - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']"
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.42
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-mandatory-bullseye
 
    groups:
 
      - parameters-mandatory
 
      - bullseye
 
    box: debian/bullseye64
 
    memory: 2048
 
    cpus: 1
 
    provider_raw_config_args:
 
      - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']"
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.51
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-optional-bullseye
 
    groups:
 
      - parameters-optional
 
      - bullseye
 
    box: debian/bullseye64
 
    memory: 2048
 
    cpus: 1
 
    provider_raw_config_args:
 
      - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']"
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.52
 
        network_name: private_network
 
        type: static
 

	
 

	
 
  # Debian 11 Bookworm
 
  # ==================
 

	
 
  - name: client1-bookworm
 
    groups:
 
      - client
 
      - client-relay-allowed
 
      - bookworm
 
      - smtp-server-requiring-tls
 
    box: debian/bookworm64
 
    memory: 256
 
    cpus: 1
 
    provider_raw_config_args:
 
      - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']"
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.21
 
        network_name: private_network
 
        type: static
 

	
 
  - name: client2-bookworm
 
    groups:
 
      - client
 
      - client-relay-forbidden
 
      - bookworm
 
      - smtp-server-refusing-tls
 
    box: debian/bookworm64
 
    memory: 256
 
    cpus: 1
 
    provider_raw_config_args:
 
      - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']"
 
    interfaces:
 
      - auto_config: true
 
        ip: 192.168.56.22
 
        network_name: private_network
 
        type: static
 

	
 
  - name: parameters-mandatory-bookworm
 
    groups:
 
      - parameters-mandatory
 
      - bookworm
 
    box: debian/bookworm64
 
    memory: 2048
 
    cpus: 1
 
    provider_raw_config_args:
 
      - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']"
 
    interfaces:
 
      - auto_config: true
roles/mail_server/molecule/default/prepare.yml
Show inline comments
 
---
 

	
 
- name: Set-up fixtures
 
  hosts: localhost
 
  connection: local
 
  gather_facts: false
 
  tasks:
 

	
 
    - name: Initialise CA hierarchy
 
      command: "gimmecert init"
 
      args:
 
        creates: ".gimmecert/ca/level1.cert.pem"
 
        chdir: "tests/data/"
 

	
 
    - name: Generate server private keys and certificates
 
      command:
 
      args:
 
        chdir: "tests/data/"
 
        creates: ".gimmecert/server/{{ item.name }}.cert.pem"
 
        argv:
 
          - "gimmecert"
 
          - "server"
 
          - "{{ item.name }}"
 
          - "{{ item.fqdn }}"
 
          - "{{ item.fqdn[:item.fqdn.rfind('-')] }}"
 
      with_items:
 
        - name: clamav-database_https
 
          fqdn: database.clamav.net
 
        - name: ldap-server_ldap
 
          fqdn: ldap-server
 

	
 
        - name: parameters-mandatory-bullseye_imap
 
          fqdn: parameters-mandatory-bullseye
 
        - name: parameters-mandatory-bullseye_smtp
 
          fqdn: parameters-mandatory-bullseye
 
        - name: parameters-optional-bullseye_imap
 
          fqdn: parameters-optional-bullseye
 
        - name: parameters-optional-bullseye_smtp
 
          fqdn: parameters-optional-bullseye
 

	
 
        - name: parameters-mandatory-bookworm_imap
 
          fqdn: parameters-mandatory-bookworm
 
        - name: parameters-mandatory-bookworm_smtp
 
          fqdn: parameters-mandatory-bookworm
 
        - name: parameters-optional-bookworm_imap
 
          fqdn: parameters-optional-bookworm
 
        - name: parameters-optional-bookworm_smtp
 
          fqdn: parameters-optional-bookworm
 

	
 
    - name: Set-up link to generated X.509 material
 
      file:
 
        src: ".gimmecert"
 
        dest: "tests/data/x509"
 
        state: link
 

	
 
- name: Prepare
 
  hosts: all
 
  gather_facts: false
 
  tasks:
 
    - name: Install python for Ansible
 
      raw: test -e /usr/bin/python3 || (apt -y update && apt install -y python3-minimal)
 
      become: true
 
      changed_when: false
 

	
 
- hosts: all
 
  become: true
 
  tasks:
 

	
 
    - name: Update all caches to avoid errors due to missing remote archives
 
      apt:
 
        update_cache: true
 
      changed_when: false
 

	
 
    - name: Install tools for testing
 
      apt:
 
        name:
 
          - gnutls-bin
 
          - nmap
 
        state: present
 

	
 
- name: Set-up a local ClamAV database mirror to avoid hitting upstream rate limits
 
  hosts: clamav-database
 
  become: true
 
  tasks:
 

	
 
    - name: Install system packages for hosting the ClamAV database
 
      apt:
 
        name:
 
@@ -137,118 +128,96 @@
 

	
 
    - name: Download/update the ClamAV database files
 
      become_user: vagrant
 
      command: "/var/lib/cvdupdate/bin/cvd update"
 

	
 
    - name: Allow all users to read ClamAV database files
 
      file:
 
        path: "/vagrant/clamav-database/"
 
        mode: "g=u-w,o=u-w"
 
        recurse: true
 

	
 
    - name: Deploy nginx TLS private key
 
      copy:
 
        dest: "/etc/ssl/private/nginx_https.key"
 
        content: "{{ clamav_database_http_server_tls_key }}"
 
        mode: 0640
 
        owner: root
 
        group: root
 
      notify:
 
        - Restart nginx
 

	
 
    - name: Deploy nginx TLS certificate
 
      copy:
 
        dest: "/etc/ssl/certs/nginx_https.pem"
 
        content: "{{ clamav_database_http_server_tls_certificate }}"
 
        mode: 0644
 
        owner: root
 
        group: root
 
      notify:
 
        - Restart nginx
 

	
 
    - name: Deploy nginx configuration for serving the ClamAV database files
 
      copy:
 
        src: clamav-database-nginx.conf
 
        dest: /etc/nginx/sites-available/default
 
        owner: root
 
        group: root
 
        mode: 0644
 
      notify:
 
        - Restart nginx
 

	
 
  handlers:
 

	
 
    - name: Restart nginx
 
      service:
 
        name: nginx
 
        state: restarted
 

	
 
- hosts: bullseye
 
  become: true
 
  tasks:
 

	
 
    - name: Set-up the hosts file
 
      lineinfile:
 
        path: /etc/hosts
 
        regexp: "^{{ item.key }}"
 
        line: "{{ item.key }} {{ item.value }}"
 
        owner: root
 
        group: root
 
        mode: 0644
 
        state: present
 
      with_dict:
 
        # Force mail servers to use local ClamAV database mirror.
 
        192.168.56.11: "db.local.clamav.net database.clamav.net"
 
        192.168.56.12: "ldap-server backup-server"
 
        192.168.56.41: "client1 smtp-server-requiring-tls"
 
        192.168.56.42: "client2 smtp-server-refusing-tls"
 
        192.168.56.51: "parameters-mandatory parameters-mandatory-bullseye"
 
        192.168.56.52: "parameters-optional parameters-optional-bullseye"
 

	
 
- hosts: bookworm
 
  become: true
 
  tasks:
 

	
 
    - name: Enable TLSv1.0+ in global OpenSSL configuration file in order to be able to test the web_server_tls_protocols parameter
 
      blockinfile:
 
        path: "/etc/ssl/openssl.cnf"
 
        block: |
 
          [openssl_init]
 
          ssl_conf = ssl_sect
 

	
 
          [ssl_sect]
 
          system_default = system_default_sect
 

	
 
          [system_default_sect]
 
          MinProtocol = TLSv1.1
 
          CipherString = DEFAULT@SECLEVEL=0
 
        owner: root
 
        group: root
 
        mode: 0644
 
        state: present
 

	
 
    - name: Set-up the hosts file
 
      lineinfile:
 
        path: /etc/hosts
 
        regexp: "^{{ item.key }}"
 
        line: "{{ item.key }} {{ item.value }}"
 
        owner: root
 
        group: root
 
        mode: 0644
 
        state: present
 
      with_dict:
 
        # Force mail servers to use local ClamAV database mirror.
 
        192.168.56.11: "db.local.clamav.net database.clamav.net"
 
        192.168.56.12: "ldap-server backup-server"
 
        192.168.56.21: "client1 smtp-server-requiring-tls"
 
        192.168.56.22: "client2 smtp-server-refusing-tls"
 
        192.168.56.31: "parameters-mandatory parameters-mandatory-bookworm"
 
        192.168.56.32: "parameters-optional parameters-optional-bookworm"
 

	
 
- hosts: client
 
  become: true
 
  tasks:
 

	
 
    - name: Install tool for testing SMTP capability
 
      apt:
 
        name: swaks
 
        state: present
roles/mail_server/molecule/default/tests/test_default.py
Show inline comments
 
@@ -587,212 +587,146 @@ def test_postfix_sends_mails_over_tls_when_available(host):
 
    assert "Must issue a STARTTLS command first" in send.stdout
 

	
 
    message_id = "%s@localhost" % str(uuid.uuid4())
 
    send = host.run('swaks --tls --header %s --suppress-data --to root@smtp-server-requiring-tls --server localhost', "Message-Id: <%s>" % message_id)
 
    assert send.rc == 0
 

	
 
    with host.sudo():
 
        mail_log = host.file('/var/log/mail.log')
 

	
 
        pattern = r"postfix/cleanup\[\d+\]: (?P<queue_id>[^:]+): message-id=<%s>" % message_id
 
        match_result = re.search(pattern, mail_log.content_string)
 
        assert match_result is not None
 

	
 
        queue_id = match_result.group('queue_id')
 
        pattern = r"postfix/smtp\[\d+\]: %s: to=<root@smtp-server-requiring-tls>, relay=smtp-server-requiring-tls.*, status=sent" % queue_id
 
        match_result = re.search(pattern, mail_log.content_string)
 
        assert match_result is not None, queue_id
 

	
 

	
 
def test_certificate_validity_check_configuration(host):
 
    """
 
    Tests if certificate validity check configuration file has been deployed
 
    correctly.
 
    """
 

	
 
    hostname = host.run('hostname').stdout.strip()
 

	
 
    config = host.file('/etc/check_certificate/%s_smtp.conf' % hostname)
 
    assert config.is_file
 
    assert config.user == 'root'
 
    assert config.group == 'root'
 
    assert config.mode == 0o644
 
    assert config.content_string == "/etc/ssl/certs/%s_smtp.pem" % hostname
 

	
 
    config = host.file('/etc/check_certificate/%s_imap.conf' % hostname)
 
    assert config.is_file
 
    assert config.user == 'root'
 
    assert config.group == 'root'
 
    assert config.mode == 0o644
 
    assert config.content_string == "/etc/ssl/certs/%s_imap.pem" % hostname
 

	
 

	
 
def test_smtp_default_port_tls_version_and_ciphers(host):
 
    """
 
    Tests TLS configuration for SMTP default port (needs to be less
 
    restrictive for interoperability purposes).
 
    """
 

	
 
    distribution_release = host.ansible("setup")["ansible_facts"]["ansible_distribution_release"]
 

	
 
    if distribution_release == "bullseye":
 
        expected_tls_versions = ["TLSv1.0", "TLSv1.1", "TLSv1.2"]
 
        expected_tls_ciphers = [
 
            'TLS_DHE_RSA_WITH_AES_128_CBC_SHA',
 
            'TLS_DHE_RSA_WITH_AES_128_CBC_SHA256',
 
            'TLS_DHE_RSA_WITH_AES_128_CCM',
 
            'TLS_DHE_RSA_WITH_AES_128_CCM_8',
 
            'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256',
 
            'TLS_DHE_RSA_WITH_AES_256_CBC_SHA',
 
            'TLS_DHE_RSA_WITH_AES_256_CBC_SHA256',
 
            'TLS_DHE_RSA_WITH_AES_256_CCM',
 
            'TLS_DHE_RSA_WITH_AES_256_CCM_8',
 
            'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384',
 
            'TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256',
 
            'TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384',
 
            'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA',
 
            'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256',
 
            'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA',
 
            'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256',
 
            'TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256',
 
            'TLS_DHE_RSA_WITH_SEED_CBC_SHA',
 
            'TLS_DH_anon_WITH_AES_128_CBC_SHA',
 
            'TLS_DH_anon_WITH_AES_128_CBC_SHA256',
 
            'TLS_DH_anon_WITH_AES_128_GCM_SHA256',
 
            'TLS_DH_anon_WITH_AES_256_CBC_SHA',
 
            'TLS_DH_anon_WITH_AES_256_CBC_SHA256',
 
            'TLS_DH_anon_WITH_AES_256_GCM_SHA384',
 
            'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA',
 
            'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256',
 
            'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA',
 
            'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256',
 
            'TLS_DH_anon_WITH_SEED_CBC_SHA',
 
            'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA',
 
            'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256',
 
            'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256',
 
            'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA',
 
            'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384',
 
            'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384',
 
            'TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256',
 
            'TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384',
 
            'TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256',
 
            'TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384',
 
            'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256',
 
            'TLS_ECDH_anon_WITH_AES_128_CBC_SHA',
 
            'TLS_ECDH_anon_WITH_AES_256_CBC_SHA',
 
            'TLS_RSA_WITH_AES_128_CBC_SHA',
 
            'TLS_RSA_WITH_AES_128_CBC_SHA256',
 
            'TLS_RSA_WITH_AES_128_CCM',
 
            'TLS_RSA_WITH_AES_128_CCM_8',
 
            'TLS_RSA_WITH_AES_128_GCM_SHA256',
 
            'TLS_RSA_WITH_AES_256_CBC_SHA',
 
            'TLS_RSA_WITH_AES_256_CBC_SHA256',
 
            'TLS_RSA_WITH_AES_256_CCM',
 
            'TLS_RSA_WITH_AES_256_CCM_8',
 
            'TLS_RSA_WITH_AES_256_GCM_SHA384',
 
            'TLS_RSA_WITH_ARIA_128_GCM_SHA256',
 
            'TLS_RSA_WITH_ARIA_256_GCM_SHA384',
 
            'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA',
 
            'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256',
 
            'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA',
 
            'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256',
 
            'TLS_RSA_WITH_SEED_CBC_SHA',
 
        ]
 
    else:
 
        expected_tls_versions = ["TLSv1.0", "TLSv1.1", "TLSv1.2", "TLSv1.3"]
 
        expected_tls_ciphers = [
 
            'TLS_AKE_WITH_AES_128_GCM_SHA256',
 
            'TLS_AKE_WITH_AES_256_GCM_SHA384',
 
            'TLS_AKE_WITH_CHACHA20_POLY1305_SHA256',
 
            'TLS_DHE_RSA_WITH_AES_128_CBC_SHA',
 
            'TLS_DHE_RSA_WITH_AES_128_CBC_SHA256',
 
            'TLS_DHE_RSA_WITH_AES_128_CCM',
 
            'TLS_DHE_RSA_WITH_AES_128_CCM_8',
 
            'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256',
 
            'TLS_DHE_RSA_WITH_AES_256_CBC_SHA',
 
            'TLS_DHE_RSA_WITH_AES_256_CBC_SHA256',
 
            'TLS_DHE_RSA_WITH_AES_256_CCM',
 
            'TLS_DHE_RSA_WITH_AES_256_CCM_8',
 
            'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384',
 
            'TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256',
 
            'TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384',
 
            'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA',
 
            'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256',
 
            'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA',
 
            'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256',
 
            'TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256',
 
            'TLS_DH_anon_WITH_AES_128_CBC_SHA',
 
            'TLS_DH_anon_WITH_AES_128_CBC_SHA256',
 
            'TLS_DH_anon_WITH_AES_128_GCM_SHA256',
 
            'TLS_DH_anon_WITH_AES_256_CBC_SHA',
 
            'TLS_DH_anon_WITH_AES_256_CBC_SHA256',
 
            'TLS_DH_anon_WITH_AES_256_GCM_SHA384',
 
            'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA',
 
            'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256',
 
            'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA',
 
            'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256',
 
            'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA',
 
            'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256',
 
            'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256',
 
            'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA',
 
            'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384',
 
            'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384',
 
            'TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256',
 
            'TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384',
 
            'TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256',
 
            'TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384',
 
            'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256',
 
            'TLS_ECDH_anon_WITH_AES_128_CBC_SHA',
 
            'TLS_ECDH_anon_WITH_AES_256_CBC_SHA',
 
            'TLS_RSA_WITH_AES_128_CBC_SHA',
 
            'TLS_RSA_WITH_AES_128_CBC_SHA256',
 
            'TLS_RSA_WITH_AES_128_CCM',
 
            'TLS_RSA_WITH_AES_128_CCM_8',
 
            'TLS_RSA_WITH_AES_128_GCM_SHA256',
 
            'TLS_RSA_WITH_AES_256_CBC_SHA',
 
            'TLS_RSA_WITH_AES_256_CBC_SHA256',
 
            'TLS_RSA_WITH_AES_256_CCM',
 
            'TLS_RSA_WITH_AES_256_CCM_8',
 
            'TLS_RSA_WITH_AES_256_GCM_SHA384',
 
            'TLS_RSA_WITH_ARIA_128_GCM_SHA256',
 
            'TLS_RSA_WITH_ARIA_256_GCM_SHA384',
 
            'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA',
 
            'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256',
 
            'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA',
 
            'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256',
 
        ]
 
    expected_tls_versions = ["TLSv1.0", "TLSv1.1", "TLSv1.2", "TLSv1.3"]
 
    expected_tls_ciphers = [
 
        'TLS_AKE_WITH_AES_128_GCM_SHA256',
 
        'TLS_AKE_WITH_AES_256_GCM_SHA384',
 
        'TLS_AKE_WITH_CHACHA20_POLY1305_SHA256',
 
        'TLS_DHE_RSA_WITH_AES_128_CBC_SHA',
 
        'TLS_DHE_RSA_WITH_AES_128_CBC_SHA256',
 
        'TLS_DHE_RSA_WITH_AES_128_CCM',
 
        'TLS_DHE_RSA_WITH_AES_128_CCM_8',
 
        'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256',
 
        'TLS_DHE_RSA_WITH_AES_256_CBC_SHA',
 
        'TLS_DHE_RSA_WITH_AES_256_CBC_SHA256',
 
        'TLS_DHE_RSA_WITH_AES_256_CCM',
 
        'TLS_DHE_RSA_WITH_AES_256_CCM_8',
 
        'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384',
 
        'TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256',
 
        'TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384',
 
        'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA',
 
        'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256',
 
        'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA',
 
        'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256',
 
        'TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256',
 
        'TLS_DH_anon_WITH_AES_128_CBC_SHA',
 
        'TLS_DH_anon_WITH_AES_128_CBC_SHA256',
 
        'TLS_DH_anon_WITH_AES_128_GCM_SHA256',
 
        'TLS_DH_anon_WITH_AES_256_CBC_SHA',
 
        'TLS_DH_anon_WITH_AES_256_CBC_SHA256',
 
        'TLS_DH_anon_WITH_AES_256_GCM_SHA384',
 
        'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA',
 
        'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256',
 
        'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA',
 
        'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256',
 
        'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA',
 
        'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256',
 
        'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256',
 
        'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA',
 
        'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384',
 
        'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384',
 
        'TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256',
 
        'TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384',
 
        'TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256',
 
        'TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384',
 
        'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256',
 
        'TLS_ECDH_anon_WITH_AES_128_CBC_SHA',
 
        'TLS_ECDH_anon_WITH_AES_256_CBC_SHA',
 
        'TLS_RSA_WITH_AES_128_CBC_SHA',
 
        'TLS_RSA_WITH_AES_128_CBC_SHA256',
 
        'TLS_RSA_WITH_AES_128_CCM',
 
        'TLS_RSA_WITH_AES_128_CCM_8',
 
        'TLS_RSA_WITH_AES_128_GCM_SHA256',
 
        'TLS_RSA_WITH_AES_256_CBC_SHA',
 
        'TLS_RSA_WITH_AES_256_CBC_SHA256',
 
        'TLS_RSA_WITH_AES_256_CCM',
 
        'TLS_RSA_WITH_AES_256_CCM_8',
 
        'TLS_RSA_WITH_AES_256_GCM_SHA384',
 
        'TLS_RSA_WITH_ARIA_128_GCM_SHA256',
 
        'TLS_RSA_WITH_ARIA_256_GCM_SHA384',
 
        'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA',
 
        'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256',
 
        'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA',
 
        'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256',
 
    ]
 

	
 
    # Run the nmap scanner against the server, and fetch the results.
 
    nmap = host.run("nmap -sV --script ssl-enum-ciphers -p 25 localhost -oX /tmp/report.xml")
 
    assert nmap.rc == 0
 
    report_content = host.file('/tmp/report.xml').content_string
 

	
 
    report_root = ElementTree.fromstring(report_content)
 

	
 
    tls_versions = []
 
    tls_ciphers = set()
 

	
 
    for child in report_root.findall("./host/ports/port/script/table"):
 
        tls_versions.append(child.attrib['key'])
 

	
 
    for child in report_root.findall(".//table[@key='ciphers']/table/elem[@key='name']"):
 
        tls_ciphers.add(child.text)
 

	
 
    tls_versions.sort()
 
    tls_ciphers = sorted(list(tls_ciphers))
 

	
 
    assert tls_versions == expected_tls_versions
 
    assert tls_ciphers == expected_tls_ciphers
 

	
 

	
 
def test_dovecot_warnings(host):
 
    """
 
    Tests if Dovecot is reporting any warnings.
 
    """
 

	
 
    with host.sudo():
 

	
 
        # Use invocation ID to get service logs since last restart.
 
        invocation_id = host.run("systemctl show -p InvocationID --value dovecot").stdout.strip()
 
        invocation_logs = host.run("journalctl INVOCATION_ID=%s + _SYSTEMD_INVOCATION_ID=%s", invocation_id, invocation_id)
 

	
 
        assert "doveconf: Warning" not in invocation_logs.stdout
roles/mail_server/molecule/default/tests/test_mandatory.py
Show inline comments
 
@@ -53,122 +53,108 @@ def test_dovecot_mailbox_directories(host):
 
    send = host.run('swaks --suppress-data --to jane.doe@domain2 --server localhost')
 
    assert send.rc == 0
 

	
 
    with host.sudo():
 

	
 
        for directory_path in ["/var/vmail/domain1",
 
                               "/var/vmail/domain1/john.doe",
 
                               "/var/vmail/domain1/john.doe/Maildir",
 
                               "/var/vmail/domain2",
 
                               "/var/vmail/domain2/jane.doe",
 
                               "/var/vmail/domain2/jane.doe/Maildir"]:
 

	
 
            directory = host.file(directory_path)
 

	
 
            assert directory.is_directory
 
            assert directory.user == "vmail"
 
            assert directory.group == "vmail"
 
            assert directory.mode == 0o700
 

	
 

	
 
def test_mail_owner(host):
 
    """
 
    Tests creation of mail owner group and user.
 
    """
 

	
 
    group = host.group("vmail")
 
    assert group.exists
 
    assert group.gid == 1003
 

	
 
    user = host.user("vmail")
 
    assert user.exists
 
    assert user.uid == 1003
 
    assert user.home == "/var/vmail"
 
    assert user.group == "vmail"
 
    assert user.groups == ["vmail"]
 

	
 

	
 
@pytest.mark.parametrize("port", [
 
    143,
 
    993,
 
    587,
 
])
 
def test_imap_and_smtp_submission_tls_version_and_ciphers(host, port):
 
    """
 
    Tests if the correct TLS version and ciphers have been enabled for
 
    IMAP and SMTP submission.
 
    """
 

	
 
    distribution_release = host.ansible("setup")["ansible_facts"]["ansible_distribution_release"]
 

	
 
    if distribution_release == "bullseye":
 
        expected_tls_versions = ["TLSv1.2"]
 
        expected_tls_ciphers = [
 
            "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
            "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
        ]
 

	
 
    else:
 
        expected_tls_versions = ["TLSv1.2", "TLSv1.3"]
 
        expected_tls_ciphers = [
 
            "TLS_AKE_WITH_AES_128_GCM_SHA256",
 
            "TLS_AKE_WITH_AES_256_GCM_SHA384",
 
            "TLS_AKE_WITH_CHACHA20_POLY1305_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
            "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
        ]
 
    expected_tls_versions = ["TLSv1.2", "TLSv1.3"]
 
    expected_tls_ciphers = [
 
        "TLS_AKE_WITH_AES_128_GCM_SHA256",
 
        "TLS_AKE_WITH_AES_256_GCM_SHA384",
 
        "TLS_AKE_WITH_CHACHA20_POLY1305_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
    ]
 

	
 
    # Run the nmap scanner against the server, and fetch the results.
 
    nmap = host.run("nmap -sV --script ssl-enum-ciphers -p %s localhost -oX /tmp/report.xml", str(port))
 
    assert nmap.rc == 0
 
    report_content = host.file('/tmp/report.xml').content_string
 

	
 
    report_root = ElementTree.fromstring(report_content)
 

	
 
    tls_versions = []
 
    tls_ciphers = set()
 

	
 
    for child in report_root.findall("./host/ports/port/script/table"):
 
        tls_versions.append(child.attrib['key'])
 

	
 
    for child in report_root.findall(".//table[@key='ciphers']/table/elem[@key='name']"):
 
        tls_ciphers.add(child.text)
 

	
 
    tls_versions.sort()
 
    tls_ciphers = sorted(list(tls_ciphers))
 

	
 
    assert tls_versions == expected_tls_versions
 
    assert tls_ciphers == expected_tls_ciphers
 

	
 

	
 
def test_dovecot_postmaster(host):
 
    """
 
    Tests if Dovecot postmaster has been correctly configured.
 
    """
 

	
 
    with host.sudo():
 

	
 
        config = host.run("doveadm config")
 
        assert config.rc == 0
 
        assert "  postmaster_address = postmaster@" in config.stdout
 

	
 

	
 
def test_imap_max_user_connections_per_ip(host):
 
    """
 
    Tests if Dovecot per-user connection limit has been set-up correctly.
 
    """
 

	
 
    with host.sudo():
 

	
 
        config = host.run("doveadm config")
 

	
 
        assert config.rc == 0
 
        assert "  mail_max_userip_connections = 10" in config.stdout
 

	
roles/mail_server/molecule/default/tests/test_optional.py
Show inline comments
 
@@ -78,127 +78,111 @@ def test_dovecot_mailbox_directories(host):
 
    send = host.run('swaks --suppress-data --to jane.doe@domain2 --server localhost')
 
    assert send.rc == 0
 

	
 
    with host.sudo():
 

	
 
        for directory_path in ["/var/virtmail/domain1",
 
                               "/var/virtmail/domain1/john.doe",
 
                               "/var/virtmail/domain1/john.doe/Maildir",
 
                               "/var/virtmail/domain2",
 
                               "/var/virtmail/domain2/jane.doe",
 
                               "/var/virtmail/domain2/jane.doe/Maildir"]:
 

	
 
            directory = host.file(directory_path)
 

	
 
            assert directory.is_directory
 
            assert directory.user == "virtmail"
 
            assert directory.group == "virtmail"
 
            assert directory.mode == 0o700
 

	
 

	
 
def test_mail_owner(host):
 
    """
 
    Tests creation of mail owner group and user.
 
    """
 

	
 
    group = host.group("virtmail")
 
    assert group.exists
 
    assert group.gid == 5000
 

	
 
    user = host.user("virtmail")
 
    assert user.exists
 
    assert user.uid == 5000
 
    assert user.home == "/var/virtmail"
 
    assert user.group == "virtmail"
 
    assert user.groups == ["virtmail"]
 

	
 

	
 
@pytest.mark.parametrize("port", [
 
    143,
 
    993,
 
    587,
 
])
 
def test_imap_and_smtp_submission_tls_version_and_ciphers(host, port):
 
    """
 
    Tests if the correct TLS version and ciphers have been enabled for
 
    IMAP and SMTP submission.
 
    """
 

	
 
    distribution_release = host.ansible("setup")["ansible_facts"]["ansible_distribution_release"]
 

	
 
    if distribution_release == "bullseye":
 
        expected_tls_versions = ["TLSv1.1", "TLSv1.2"]
 
        expected_tls_ciphers = [
 
            "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
 
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
 
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
 
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
        ]
 
    else:
 
        expected_tls_versions = ["TLSv1.1", "TLSv1.2", "TLSv1.3"]
 
        expected_tls_ciphers = [
 
            "TLS_AKE_WITH_AES_128_GCM_SHA256",
 
            "TLS_AKE_WITH_AES_256_GCM_SHA384",
 
            "TLS_AKE_WITH_CHACHA20_POLY1305_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
 
            "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
 
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
 
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
 
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
        ]
 
    expected_tls_versions = ["TLSv1.1", "TLSv1.2", "TLSv1.3"]
 
    expected_tls_ciphers = [
 
        "TLS_AKE_WITH_AES_128_GCM_SHA256",
 
        "TLS_AKE_WITH_AES_256_GCM_SHA384",
 
        "TLS_AKE_WITH_CHACHA20_POLY1305_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
 
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
 
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
    ]
 

	
 
    # Run the nmap scanner against the server, and fetch the results.
 
    nmap = host.run("nmap -sV --script ssl-enum-ciphers -p %s localhost -oX /tmp/report.xml", str(port))
 
    assert nmap.rc == 0
 
    report_content = host.file('/tmp/report.xml').content_string
 

	
 
    report_root = ElementTree.fromstring(report_content)
 

	
 
    tls_versions = []
 
    tls_ciphers = set()
 

	
 
    for child in report_root.findall("./host/ports/port/script/table"):
 
        tls_versions.append(child.attrib['key'])
 

	
 
    for child in report_root.findall(".//table[@key='ciphers']/table/elem[@key='name']"):
 
        tls_ciphers.add(child.text)
 

	
 
    tls_versions.sort()
 
    tls_ciphers = sorted(list(tls_ciphers))
 

	
 
    assert tls_versions == expected_tls_versions
 
    assert tls_ciphers == expected_tls_ciphers
 

	
 

	
 
def test_dovecot_postmaster(host):
 
    """
 
    Tests if Dovecot postmaster has been correctly configured.
 
    """
 

	
 
    with host.sudo():
 

	
 
        config = host.run("doveadm config")
 

	
 
        assert config.rc == 0
 
        assert "  postmaster_address = webmaster@parameters-optional" in config.stdout
 

	
 

	
 
def test_imap_max_user_connections_per_ip(host):
 
    """
 
    Tests if Dovecot per-user connection limit has been set-up correctly.
 
    """
 

	
 
    with host.sudo():
 

	
 
        config = host.run("doveadm config")
 

	
 
        assert config.rc == 0
 
        assert "  mail_max_userip_connections = 2" in config.stdout
roles/mail_server/templates/main.cf.j2
Show inline comments
 
# See /usr/share/postfix/main.cf.dist for a commented, more complete
 
# version.
 

	
 

	
 
# General settings
 
# ================
 

	
 
# Internet hostname of this mail system.
 
myhostname = {{ inventory_hostname }}
 

	
 
# Under Debian, when a file name is specified, the first line of the
 
# file be used as the SMTP server name.
 
myorigin = /etc/mailname
 

	
 
# Text shown to connecting clients as part of SMTP greeting.
 
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
 

	
 
# Listen on all network interfaces and all protocols.
 
inet_interfaces = all
 
inet_protocols = all
 

	
 
# Fall-back to using native lookups (/etc/hosts etc) if DNS lookup
 
# fails. Useful for local overrides of mail servers.
 
smtp_host_lookup = dns, native
 

	
 
# Recipient delimeter for separating user name from its extension.
 
recipient_delimiter = +
 

	
 
# Deliver undeliverable bounces to domain's postmaster. Helps with application
 
# misconfigurations.
 
notify_classes = resource, software, 2bounce
 

	
 
# Explicitly set maximum allowed mail size that should be accepted.
 
message_size_limit = {{ mail_message_size_limit }}
 

	
 
# Disable output of Postfix README file paths when invoking postconf.
 
readme_directory = no
 

	
 
{% if ansible_distribution_release != 'bullseye' %}
 
# Use whitelist/blacklist instead of allowlist/denylist in log
 
# entries.
 
respectful_logging = no
 
{% endif %}
 

	
 
# Compatibility level for default values. For more details, see:
 
#     https://www.postfix.org/COMPATIBILITY_README.html
 
compatibility_level = 3.6
 

	
 

	
 
# Local mailbox delivery
 
# ======================
 

	
 
# List of domains for local transport deliveries.
 
mydestination = {{ inventory_hostname }}, {{ inventory_hostname_short }}, localhost.localdomain, localhost
 

	
 
# Alias maps for local deliveries (to system accounts).
 
alias_maps = hash:/etc/aliases
 

	
 
# Alias database that gets updated when invoking "newaliases" command.
 
alias_database = hash:/etc/aliases
 

	
 
# Disable size limits for local user mailboxes.
 
mailbox_size_limit = 0
 

	
 
# Disable use of biff service for new mail notifications to local
 
# users (improves performance).
 
biff = no
 

	
 

	
 
# Virtual mailbox delivery
 
# ========================
 

	
 
# Deliver mails via Dovecot LDA for virtual domains.
 
virtual_transport = dovecot
 

	
 
# Maximum number of recipients per message delivery.
 
dovecot_destination_recipient_limit = 1
 

	
 
# LDAP directory look-ups for domains, mailboxes and aliases.
 
virtual_mailbox_domains = ldap:/etc/postfix/ldap-virtual-mailbox-domains.cf
 
virtual_mailbox_maps = ldap:/etc/postfix/ldap-virtual-mailbox-maps.cf
 
virtual_alias_maps = ldap:/etc/postfix/ldap-virtual-alias-maps.cf
 

	
 

	
 
# Remote mailbox delivery
 
# =======================
 

	
 
# List of trusted networks allowed to relay mail through this system.
 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128{% for network in smtp_allow_relay_from  %} {{ network }}{% endfor %}
 

	
 
# Allow relaying only from trusted networks. Do not relay mails for
0 comments (0 inline, 0 general)