Changeset - 8d272d91d3d2
[Not reviewed]
0 7 1
Branko Majic (branko) - 3 years ago 2021-01-19 23:02:21
branko@majic.rs
MAR-165: Deploy Diffie-Helman parameters for LDAP server in the ldap_server role:

- Not relevant for Debian Strech because of a bug in the OpenLDAP
version it ships with.
- This should allow use of DHE ciphers with LDAP server.
- Generated DH parameters only help pick one of the parameters from
RFC-7919 (based on the size of generated ones).
- Make the cipher test lists distro-specific due to differences
between supported algorithms in respective GnuTLS versions.
8 files changed with 155 insertions and 31 deletions:
0 comments (0 inline, 0 general)
docs/releasenotes.rst
Show inline comments
 
@@ -5,6 +5,15 @@ Release notes
 
NEXT RELEASE
 
------------
 

	
 
**Breaking changes**
 

	
 
* ``ldap_server`` role
 

	
 
  * Use 2048-bit Diffie-Hellman parameters for relevant TLS
 
    ciphers. This could introduce incompatibility with older
 
    clients/servers trying to connect to the LDAP server. This change
 
    is applicable only under Debian Buster.
 

	
 
**New features/improvements:**
 

	
 
* All roles
 
@@ -19,6 +28,12 @@ NEXT RELEASE
 

	
 
**Bug fixes:**
 

	
 
* ``ldap_server`` role
 

	
 
  * Allow use of DHE TLS ciphers by generating the necessary
 
    Diffie-Hellman parameters. This bug fix is applicable only under
 
    Debian Buster.
 

	
 
* ``wsgi_website_`` role
 

	
 
  * When the virtual environment is created, the ``setuptools`` and
docs/rolereference.rst
Show inline comments
 
@@ -764,7 +764,13 @@ Parameters
 
     Under Debian Stretch, the DHE ciphers are not usable due to a bug
 
     present in OpenLDAP 2.4.44. See
 
     https://bugs.launchpad.net/ubuntu/+source/openldap/+bug/1656979
 
     for details.
 
     for details. DHE ciphers are usable under Debian Buster.
 

	
 
     It should be also noted that under Debian Buster, slapd will not
 
     use the DH parameters generated by the role, but will instead use
 
     them to pick one of the recommended DH parameters from `RFC-7919
 
     <https://www.ietf.org/rfc/rfc7919.txt>`_. This is based on the
 
     size of role-generated parameters.
 

	
 
  TLS ciphers to enable on the LDAP server. This should be a GnuTLS-compatible
 
  cipher specification that should also include what TLS protocol versions
roles/ldap_server/molecule/default/prepare.yml
Show inline comments
 
@@ -142,12 +142,10 @@
 
        path: "/bin/ss"
 
        state: absent
 

	
 
    - name: Install netstat utility
 
    - name: Install tools for testing
 
      apt:
 
        name: net-tools
 
        state: present
 

	
 
    - name: Install nmap utility for testing TLS
 
      apt:
 
        name: nmap
 
        name:
 
          - net-tools
 
          - nmap
 
          - gnutls-bin
 
        state: present
roles/ldap_server/molecule/default/tests/test_default.py
Show inline comments
 
@@ -230,3 +230,24 @@ def test_ldap_tls_certificate_file(host):
 
        assert cert.group == 'root'
 
        assert cert.mode == 0o644
 
        assert cert.content_string == open('tests/data/x509/server/%s_ldap.cert.pem' % inventory_hostname).read()
 

	
 

	
 
def test_ldap_server_dh_parameter_file(host):
 
    """
 
    Tests if the Diffie-Hellman parameter file has been generated
 
    correctly.
 
    """
 

	
 
    hostname = host.run('hostname').stdout.strip()
 
    dhparam_file_path = '/etc/ssl/private/%s_ldap.dh.pem' % hostname
 

	
 
    with host.sudo():
 
        dhparam_file = host.file(dhparam_file_path)
 
        assert dhparam_file.is_file
 
        assert dhparam_file.user == 'root'
 
        assert dhparam_file.group == 'openldap'
 
        assert dhparam_file.mode == 0o640
 

	
 
        dhparam_info = host.run("openssl dhparam -noout -text -in %s", dhparam_file_path)
 

	
 
        assert "DH Parameters: (2048 bit)" in dhparam_info.stdout
roles/ldap_server/molecule/default/tests/test_default_buster.py
Show inline comments
 
new file 100644
 
import os
 

	
 
import testinfra.utils.ansible_runner
 

	
 

	
 
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
 
    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-*-buster64')
 

	
 

	
 
def test_ldap_server_uses_correct_dh_parameters(host):
 
    """
 
    Tests if the LDAP server uses the generated Diffie-Hellman
 
    parameter.
 
    """
 

	
 
    # Technically we should be testing here against deployed DH
 
    # parameters file, however... When linked against GnuTLS, slapd
 
    # seems to only take into account the size of pointed-to DH
 
    # parameters, and then picks one of the parameters from the
 
    # RFC-7919 (https://www.ietf.org/rfc/rfc7919.txt)
 
    # instead. Therefore we list here the 2048-bit DH parameter from
 
    # the RFC instead.
 
    expected_dhparam = """-----BEGIN DH PARAMETERS-----
 
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
 
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
 
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
 
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
 
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
 
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
 
-----END DH PARAMETERS-----"""
 

	
 
    connection = host.run("gnutls-cli --no-ca-verification --starttls-proto=ldap --port 389 "
 
                          "--priority 'NONE:+VERS-TLS1.2:+CTYPE-X509:+COMP-NULL:+SIGN-RSA-SHA384:+DHE-RSA:+SHA384:+AEAD:+AES-256-GCM' --verbose localhost")
 

	
 
    output = connection.stdout
 
    begin_marker = "-----BEGIN DH PARAMETERS-----"
 
    end_marker = "-----END DH PARAMETERS-----"
 
    used_dhparam = output[output.find(begin_marker):output.find(end_marker) + len(end_marker)]
 

	
 
    assert used_dhparam == expected_dhparam
roles/ldap_server/molecule/default/tests/test_mandatory.py
Show inline comments
 
@@ -78,16 +78,24 @@ def test_tls_version_and_ciphers(host):
 
    # @TODO: Under Debian Stretch, the DHE ciphers are not usable due
 
    # to a bug present in OpenLDAP 2.4.44. See
 
    # https://bugs.launchpad.net/ubuntu/+source/openldap/+bug/1656979
 
    # for details. It should be possible to fix this problem once
 
    # switch to buster is mad.e
 
    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",
 
    ]
 
    # for details.
 
    expected_tls_ciphers = {
 
        "stretch": [
 
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
        ],
 
        "buster": [
 
            "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"]
 

	
 
    # Run the nmap scanner against the LDAP server, and fetch the
 
    # results.
 
@@ -110,7 +118,7 @@ def test_tls_version_and_ciphers(host):
 
    tls_ciphers = sorted(list(tls_ciphers))
 

	
 
    assert tls_versions == expected_tls_versions
 
    assert tls_ciphers == expected_tls_ciphers
 
    assert tls_ciphers == expected_tls_ciphers[distribution_release]
 

	
 

	
 
def test_ssf_configuration(host):
roles/ldap_server/molecule/default/tests/test_optional.py
Show inline comments
 
@@ -82,17 +82,32 @@ def test_tls_version_and_ciphers(host):
 
    # https://bugs.launchpad.net/ubuntu/+source/openldap/+bug/1656979
 
    # for details. It should be possible to fix this problem once
 
    # switch to buster is mad.e
 
    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_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",
 
    ]
 
    expected_tls_ciphers = {
 
        "stretch": [
 
            "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",
 
        ],
 
        "buster": [
 
            "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
 
            "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
 
            "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_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_SHA",
 
            "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"]
 

	
 
    # Run the nmap scanner against the LDAP server, and fetch the
 
    # results.
 
@@ -115,7 +130,7 @@ def test_tls_version_and_ciphers(host):
 
    tls_ciphers = sorted(list(tls_ciphers))
 

	
 
    assert tls_versions == expected_tls_versions
 
    assert tls_ciphers == expected_tls_ciphers
 
    assert tls_ciphers == expected_tls_ciphers[distribution_release]
 

	
 

	
 
def test_ssf_configuration(host):
roles/ldap_server/tasks/main.yml
Show inline comments
 
@@ -91,6 +91,20 @@
 
  command: "ldapadd -H ldapi:/// -Q -Y EXTERNAL -f /etc/ldap/schema/misc.ldif"
 
  when: not ldap_misc_schema_present.stdout
 

	
 
# Technically, the only thing this does is pick the size of DH
 
# parameters to use, with GnuTLS (against which slapd is linked
 
# against under Debian) picking a matching DH parameter from RFC-7919
 
# (https://www.ietf.org/rfc/rfc7919.txt).
 
- name: Generate the LDAP server Diffie-Hellman parameter
 
  openssl_dhparam:
 
    owner: root
 
    group: openldap
 
    mode: 0640
 
    path: "/etc/ssl/private/{{ ansible_fqdn }}_ldap.dh.pem"
 
    size: 2048
 
  notify:
 
    - Restart slapd
 

	
 
- name: Deploy LDAP TLS private key
 
  template:
 
    src: "ldap_tls_key.j2"
 
@@ -160,6 +174,13 @@
 
    values: "/etc/ssl/private/{{ ansible_fqdn }}_ldap.key"
 
    state: exact
 

	
 
- name: Configure DH parameter
 
  ldap_attr:
 
    dn: cn=config
 
    name: olcTLSDHParamFile
 
    values: "/etc/ssl/private/{{ ansible_fqdn }}_ldap.dh.pem"
 
    state: exact
 

	
 
- name: Configure TLS cipher suites
 
  ldap_attr:
 
    dn: cn=config
0 comments (0 inline, 0 general)