From a48e04e52b25b33b0cf0f34dd9cfc5a3b40496c4 2024-03-01 00:29:54 From: Branko Majic Date: 2024-03-01 00:29:54 Subject: [PATCH] MAR-192: Added support for Debian 12 Bookworm to mail_server role: - Allow use of older versions of TLS on Bookworm for testing of related optional parameters. - Install the IMAP CLI testing tool under its own virtual environment in order to avoid warnings and errors when trying to install it globally under Debian 12 Bookworm. - Update the lists of expected TLS protocols and ciphers. --- diff --git a/docs/rolereference.rst b/docs/rolereference.rst index 729504be223f3db66f30b8764f8a2966dbec32fc..23831697ffb639cc3aee97f10f722ab415d2973d 100644 --- a/docs/rolereference.rst +++ b/docs/rolereference.rst @@ -1251,6 +1251,7 @@ Distribution compatibility Role is compatible with the following distributions: - Debian 11 (Bullseye) +- Debian 12 (Bookworm) Examples diff --git a/roles/mail_server/meta/main.yml b/roles/mail_server/meta/main.yml index 3a808145d86f3114c4cb22cc42d1e1e02831d7a5..801285713126ac21553e83ee04c15c2bcbcfa9f3 100644 --- a/roles/mail_server/meta/main.yml +++ b/roles/mail_server/meta/main.yml @@ -17,3 +17,4 @@ galaxy_info: - name: Debian versions: - 11 + - 12 diff --git a/roles/mail_server/molecule/default/group_vars/parameters-optional.yml b/roles/mail_server/molecule/default/group_vars/parameters-optional.yml index 61f2866d22c853195c887f707ef4fb2ac3c37141..8453b04069f82b09cb18fdb21f8fad323d51f125 100644 --- a/roles/mail_server/molecule/default/group_vars/parameters-optional.yml +++ b/roles/mail_server/molecule/default/group_vars/parameters-optional.yml @@ -35,6 +35,7 @@ mail_server_smtp_additional_configuration: | # Variables dependant on distribution release. release_based_smtp_allow_relay_from: bullseye: "192.168.56.41" + bookworm: "192.168.56.21" # common ca_certificates: diff --git a/roles/mail_server/molecule/default/host_vars/ldap-server.yml b/roles/mail_server/molecule/default/host_vars/ldap-server.yml index 3e24e9c959626e6b52cd2dcc816ddf4e6c467c6f..9b8ed2cf29c69a47f379949880bb526be0be1221 100644 --- a/roles/mail_server/molecule/default/host_vars/ldap-server.yml +++ b/roles/mail_server/molecule/default/host_vars/ldap-server.yml @@ -46,3 +46,7 @@ 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') }}" diff --git a/roles/mail_server/molecule/default/molecule.yml b/roles/mail_server/molecule/default/molecule.yml index e0645d4a568b0cbd6838f67648a84a72461030c1..0cf54af4c396f00127374d8472c7c6120fba31c2 100644 --- a/roles/mail_server/molecule/default/molecule.yml +++ b/roles/mail_server/molecule/default/molecule.yml @@ -24,7 +24,7 @@ platforms: # ======= - name: clamav-database - box: debian/bullseye64 + box: debian/bookworm64 memory: 512 cpus: 1 provider_raw_config_args: @@ -38,7 +38,7 @@ platforms: synced_folder: true - name: ldap-server - box: debian/bullseye64 + box: debian/bookworm64 memory: 256 cpus: 1 provider_raw_config_args: @@ -118,6 +118,74 @@ platforms: 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 + ip: 192.168.56.31 + network_name: private_network + type: static + + - name: parameters-optional-bookworm + groups: + - parameters-optional + - bookworm + box: debian/bookworm64 + memory: 2048 + cpus: 1 + provider_raw_config_args: + - "customize ['modifyvm', :id, '--paravirtprovider', 'minimal']" + interfaces: + - auto_config: true + ip: 192.168.56.32 + network_name: private_network + type: static + + provisioner: name: ansible playbooks: diff --git a/roles/mail_server/molecule/default/prepare.yml b/roles/mail_server/molecule/default/prepare.yml index 51f28bdf518207435a35dc6c5655b3a2b7f748fc..ef47bf6dae35eb45fcf6e05fb1e3ce0236c61c2c 100644 --- a/roles/mail_server/molecule/default/prepare.yml +++ b/roles/mail_server/molecule/default/prepare.yml @@ -38,6 +38,15 @@ - 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" @@ -195,24 +204,95 @@ 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 SWAKS for testing SMTP capability + - name: Install tool for testing SMTP capability apt: name: swaks state: present - - name: Install pip - apt: - name: python3-pip - state: present + - name: Install tool for testing IMAP + block: - - name: Install IMAP CLI tool - pip: - name: Imap-CLI==0.7 - state: present + - name: Install required system packages + apt: + name: python3-venv + state: present + + - name: Set-up dedicated Python virtual environment for running the tool + command: "python3 -m venv /opt/imap-cli" + args: + creates: /opt/imap-cli/bin/python + + - name: Install IMAP CLI + pip: + name: + - Imap-CLI==0.7 + - six + state: present + virtualenv: /opt/imap-cli + + - name: Set-up symlinks for running the tool + file: + src: "/opt/imap-cli/bin/{{ item }}" + dest: "/usr/local/bin/{{ item }}" + owner: root + group: root + state: link + with_items: + - imapcli + - imap-cli-flag + - imap-cli-delete + - imap-cli-copy + - imap-api + - imap-shell + - imap-notify + - imap-cli-status + - imap-cli-search + - imap-cli-read + - imap-cli-list - name: Install tool for testing SIEVE apt: diff --git a/roles/mail_server/molecule/default/tests/test_default.py b/roles/mail_server/molecule/default/tests/test_default.py index df02ca9dffe1b9e34e166dabc5ec4c210f2386b5..768f1a18edab2efc2e4162726f235ac09d63688e 100644 --- a/roles/mail_server/molecule/default/tests/test_default.py +++ b/roles/mail_server/molecule/default/tests/test_default.py @@ -632,10 +632,11 @@ def test_smtp_default_port_tls_version_and_ciphers(host): restrictive for interoperability purposes). """ - expected_tls_versions = ["TLSv1.0", "TLSv1.1", "TLSv1.2"] + distribution_release = host.ansible("setup")["ansible_facts"]["ansible_distribution_release"] - expected_tls_ciphers = { - "bullseye": [ + 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', @@ -696,9 +697,69 @@ def test_smtp_default_port_tls_version_and_ciphers(host): 'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256', 'TLS_RSA_WITH_SEED_CBC_SHA', ] - } - - distribution_release = host.ansible("setup")["ansible_facts"]["ansible_distribution_release"] + 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', + ] # 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") @@ -720,7 +781,7 @@ def test_smtp_default_port_tls_version_and_ciphers(host): tls_ciphers = sorted(list(tls_ciphers)) assert tls_versions == expected_tls_versions - assert tls_ciphers == expected_tls_ciphers[distribution_release] + assert tls_ciphers == expected_tls_ciphers def test_dovecot_warnings(host): diff --git a/roles/mail_server/molecule/default/tests/test_mandatory.py b/roles/mail_server/molecule/default/tests/test_mandatory.py index 39d9494dde9d131af102e39a1733c35329a44581..483d3a33af05b74b19da6852627b2f7465e29800 100644 --- a/roles/mail_server/molecule/default/tests/test_mandatory.py +++ b/roles/mail_server/molecule/default/tests/test_mandatory.py @@ -98,16 +98,32 @@ def test_imap_and_smtp_submission_tls_version_and_ciphers(host, port): IMAP and SMTP submission. """ - 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", - ] + 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", + ] # 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)) diff --git a/roles/mail_server/molecule/default/tests/test_optional.py b/roles/mail_server/molecule/default/tests/test_optional.py index 80e2045fe0b9ba99aa8fac60a308ba2ba832c166..732c7f93d8e3d14e4f1a9ded2e8d1a1d2652f235 100644 --- a/roles/mail_server/molecule/default/tests/test_optional.py +++ b/roles/mail_server/molecule/default/tests/test_optional.py @@ -123,19 +123,37 @@ def test_imap_and_smtp_submission_tls_version_and_ciphers(host, port): IMAP and SMTP submission. """ - 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", - ] + 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", + ] # 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))