Docker-openldap: cannot make a secure connection: TLS: can't accept: The TLS connection was non-properly terminated..

Created on 27 Jun 2019  路  9Comments  路  Source: osixia/docker-openldap

I'm running docker-openldap on Azure k8s. I have own certificates: company CA and server certificate.
My manifest:

     containers:
        - name: openldap
          image: osixia/openldap:latest
          args:
            - "--copy-service"
          ports:
            - containerPort: 389
            - containerPort: 636
          volumeMounts:
            - name: ldap-data
              mountPath: /var/lib/ldap
            - name: ldap-config
              mountPath: /etc/ldap/slapd.d
            - name: ldap-certs
              mountPath: /container/service/slapd/assets/certs
            - name: secret-volume
              mountPath: /container/environment/01-custom
            - name: container-run
              mountPath: /container/run
      volumes:
        - name: "secret-volume"
          secret:
            secretName: "ldap-env"
        - name: container-run
          emptyDir: {}
  volumeClaimTemplates:
    - metadata:
        name: ldap-data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 1Gi
    - metadata:
        name: ldap-config
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Mi
    - metadata:
        name: ldap-certs
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Mi

From inside the openldap container:

root@openldap-0:~/tmp# ldapwhoami -x -H ldap://localhost
anonymous
root@openldap-0:~/tmp# ldapwhoami -x -H ldap://localhost -Z
ldap_start_tls: Connect error (-11)
    additional info: (unknown error code)
ldap_result: Can't contact LDAP server (-1)

And openssl:

root@openldap-0:~/tmp# openssl s_client -connect 127.0.0.1:636
CONNECTED(00000003)
depth=0 C = ..., O = Company, CN = localhost
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = ..., O = Company, CN = localhost
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/C=.../O=Company/CN=localhost
   i:/DC=.../CN=Company CA
---
Server certificate
-----BEGIN CERTIFICATE-----
...
subject=/C=.../O=Company/CN=localhost
issuer=/DC=.../CN=CA Company
---
Acceptable client certificate CA names
/C=US/O=A1A Car Wash/OU=Information Technology Dep./L=Albuquerque/ST=New Mexico/CN=docker-light-baseimage
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: RSA+SHA384:ECDSA+SHA384:RSA+SHA512:ECDSA+SHA512:RSA+SHA256:ECDSA+SHA256
Shared Requested Signature Algorithms: RSA+SHA384:ECDSA+SHA384:RSA+SHA512:ECDSA+SHA512:RSA+SHA256:ECDSA+SHA256
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3645 bytes and written 314 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 8192 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: C380C4E4790CE6D12905ECFF3263C3BCD8C606945EDD02FB2042C19CEF7E8F06
    Session-ID-ctx:
    Master-Key: 333FDFB3BC3B558B4BA2E074769091E03C2340EEB56A21F957F91934A9A0DF856F5EC944AC66E4F58828C429D63AE3DF
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1561626898
    Timeout   : 7200 (sec)
    Verify return code: 21 (unable to verify the first certificate)
    Extended master secret: yes
---
^C

I have manualy copied all certs and key to /container/service/slapd/assets/certs from Secret. My certificate is singed by self signed CA.
I had even imported CA to Debian chain and run update-ca-certificates but it didn't help me.

I've compared two output of openssl command from client session(ldap-account-manager): -connect localhost:443 vs -connect openldap:636. Webserver uses the same certificate.
For ldap:

Acceptable client certificate CA names
  /C=US/O=A1A Car Wash/OU=Information Technology Dep./L=Albuquerque/ST=New Mexico/CN=docker-light-baseimage
  Client Certificate Types: RSA sign, DSA sign, ECDSA sign
  Requested Signature Algorithms: RSA+SHA384:ECDSA+SHA384:RSA+SHA512:ECDSA+SHA512:RSA+SHA256:ECDSA+SHA256
  Shared Requested Signature Algorithms: RSA+SHA384:ECDSA+SHA384:RSA+SHA512:ECDSA+SHA512:RSA+SHA256:ECDSA+SHA256
...
  SSL handshake has read 3594 bytes and written 314 bytes
  Verification error: unable to verify the first certificate
...
      Verify return code: 21 (unable to verify the first certificate)
      Extended master secret: yes

for webserver:

No client certificate CA names sent
...
SSL handshake has read 4629 bytes and written 302 bytes
  Verification error: self signed certificate in certificate chain
...
      Verify return code: 19 (self signed certificate in certificate chain)
      Extended master secret: no

What is wrong with my installation?

Edit:
ldapsearch and ldapwhoami works with changes in /etc/ldap/ldap.conf:

TLS_REQCERT allow | never

Web interface also works.
Can you force these settings on the server side?

Most helpful comment

So I wanted to drop a line here to follow-up on this persistent issue. The problem with client authentication with self-signed TLS certs seems to be a common problem mentioned on a number of open tickets. Assuming a docker installation LDAP_TLS_VERIFY_CLIENT=demand is default value when this environmental variable isn't included. Changing on the LDAP server the value of LDAP_TLS_VERIFY_CLIENT=demand to LDAP_TLS_VERIFY_CLIENT=try bypasses client authentication with a malformed client TLS certificate. These variable names might be slightly different with a K8 installation, however the general concept still applies.

I posted my solution for the creation of client/server/CA self-signed certs that allows for TLS authentication with server and client authentication. I've posted the solution here: https://ubuntuforums.org/showthread.php?t=2451653&p=13992175#post13992175. After generating the certificates, LDAP_TLS_VERIFY_CLIENT=demand should work.

Here is a snippet of my docker-compose.yml file for openldap and phpldapadmin:

  openldap:
    image: osixia/openldap:latest
    container_name: openldap
    restart: always
    domainname: openldap.domain.com
    networks:
      - net
    ports:
      - "389:389"
      - "636:636"
    secrets:
      - authentication_backend-ldap_secret
    environment:
      - LDAP_LOG_LEVEL=256
      - LDAP_ORGANISATION=gohilton
      - LDAP_DOMAIN=ldap.gohilton.com
      - LDAP_BASE_DN=dc=ldap,dc=gohilton,dc=com
      - LDAP_ADMIN_PASSWORD_FILE=/run/secrets/authentication_backend-ldap_secret
      - LDAP_TLS=true
      - LDAP_TLS_CRT_FILENAME=cert.pem
      - LDAP_TLS_KEY_FILENAME=key.pem
      - LDAP_TLS_CA_CRT_FILENAME=ca.pem
      - LDAP_TLS_ENFORCE=false
      #- LDAP_TLS_VERIFY_CLIENT=try
      - LDAP_TLS_VERIFY_CLIENT=demand
      - LDAP_REPLICATION=false
      - KEEP_EXISTING_CONFIG=false
      - LDAP_REMOVE_CONFIG_AFTER_SETUP=false
      - LDAP_SSL_HELPER_PREFIX=ldap
    tty: true
    command: --loglevel debug
    stdin_open: true
    volumes:
      - /var/data/ldap/db:/var/lib/ldap
      - /etc/ldap/config:/etc/ldap/slapd.d
      - /etc/docker/compose/authelia/certs/openldap3/server:/container/service/slapd/assets/certs

  phpldapadmin:
    image: osixia/phpldapadmin:latest
    container_name: phpldapadmin
    restart: unless-stopped
    hostname: phpldapadmin.domain.org
    networks:
      - net
    ports:
      - 6443:80
    depends_on:
      - openldap
    environment:
      PHPLDAPADMIN_LDAP_HOSTS: "openldap"
      PHPLDAPADMIN_HTTPS: "false"
      PHPLDAPADMIN_LDAP_CLIENT_TLS: "true"
      PHPLDAPADMIN_LDAP_CLIENT_TLS_REQCERT: "demand"
      PHPLDAPADMIN_LDAP_CLIENT_TLS_CA_CRT_FILENAME: "ca.pem"
      PHPLDAPADMIN_LDAP_CLIENT_TLS_CRT_FILENAME: "cert.pem"
      PHPLDAPADMIN_LDAP_CLIENT_TLS_KEY_FILENAME: "key.pem"
    command: --loglevel debug
    volumes:
      - /etc/docker/compose/authelia/certs/openldap3/client:/container/service/ldap-client/assets/certs

All 9 comments

Hm I seem to have the same problem.. did you find a solution?

I also have the same problem. I'm running the command in the container. Did you solve it?

Are there any intermediate certificates in the chain? If that is the case, those would have to be included in the CA crt file.

Any news about this case ? I have the same problem :/

Are there any intermediate certificates in the chain? If that is the case, those would have to be included in the CA crt file.
Currently I removed this service from our environment and temporally I cannot test it.

So I had the same problem, and at least in my case what it turned out to be is the olcTLSVerifyClient configuration being set to "demand" in the container -- I changed it to "try" and everything sorted right out. This is because I wasn't using a cert with the _client_ which "demand" requires. TLS_REQCERT makes no difference in that case because that's about whether the _server_ is required to have verifiable certs. Anyway, yes, changed that, worked like a charm.

So I wanted to drop a line here to follow-up on this persistent issue. The problem with client authentication with self-signed TLS certs seems to be a common problem mentioned on a number of open tickets. Assuming a docker installation LDAP_TLS_VERIFY_CLIENT=demand is default value when this environmental variable isn't included. Changing on the LDAP server the value of LDAP_TLS_VERIFY_CLIENT=demand to LDAP_TLS_VERIFY_CLIENT=try bypasses client authentication with a malformed client TLS certificate. These variable names might be slightly different with a K8 installation, however the general concept still applies.

I posted my solution for the creation of client/server/CA self-signed certs that allows for TLS authentication with server and client authentication. I've posted the solution here: https://ubuntuforums.org/showthread.php?t=2451653&p=13992175#post13992175. After generating the certificates, LDAP_TLS_VERIFY_CLIENT=demand should work.

Here is a snippet of my docker-compose.yml file for openldap and phpldapadmin:

  openldap:
    image: osixia/openldap:latest
    container_name: openldap
    restart: always
    domainname: openldap.domain.com
    networks:
      - net
    ports:
      - "389:389"
      - "636:636"
    secrets:
      - authentication_backend-ldap_secret
    environment:
      - LDAP_LOG_LEVEL=256
      - LDAP_ORGANISATION=gohilton
      - LDAP_DOMAIN=ldap.gohilton.com
      - LDAP_BASE_DN=dc=ldap,dc=gohilton,dc=com
      - LDAP_ADMIN_PASSWORD_FILE=/run/secrets/authentication_backend-ldap_secret
      - LDAP_TLS=true
      - LDAP_TLS_CRT_FILENAME=cert.pem
      - LDAP_TLS_KEY_FILENAME=key.pem
      - LDAP_TLS_CA_CRT_FILENAME=ca.pem
      - LDAP_TLS_ENFORCE=false
      #- LDAP_TLS_VERIFY_CLIENT=try
      - LDAP_TLS_VERIFY_CLIENT=demand
      - LDAP_REPLICATION=false
      - KEEP_EXISTING_CONFIG=false
      - LDAP_REMOVE_CONFIG_AFTER_SETUP=false
      - LDAP_SSL_HELPER_PREFIX=ldap
    tty: true
    command: --loglevel debug
    stdin_open: true
    volumes:
      - /var/data/ldap/db:/var/lib/ldap
      - /etc/ldap/config:/etc/ldap/slapd.d
      - /etc/docker/compose/authelia/certs/openldap3/server:/container/service/slapd/assets/certs

  phpldapadmin:
    image: osixia/phpldapadmin:latest
    container_name: phpldapadmin
    restart: unless-stopped
    hostname: phpldapadmin.domain.org
    networks:
      - net
    ports:
      - 6443:80
    depends_on:
      - openldap
    environment:
      PHPLDAPADMIN_LDAP_HOSTS: "openldap"
      PHPLDAPADMIN_HTTPS: "false"
      PHPLDAPADMIN_LDAP_CLIENT_TLS: "true"
      PHPLDAPADMIN_LDAP_CLIENT_TLS_REQCERT: "demand"
      PHPLDAPADMIN_LDAP_CLIENT_TLS_CA_CRT_FILENAME: "ca.pem"
      PHPLDAPADMIN_LDAP_CLIENT_TLS_CRT_FILENAME: "cert.pem"
      PHPLDAPADMIN_LDAP_CLIENT_TLS_KEY_FILENAME: "key.pem"
    command: --loglevel debug
    volumes:
      - /etc/docker/compose/authelia/certs/openldap3/client:/container/service/ldap-client/assets/certs

I am also facing this issue. Here is another report on serverfault.

ldapsearch from within the container works:

ldapsearch -x -H ldaps://DOMAIN [...]

but fails from outside.

I've tried setting LDAP_TLS_VERIFY_CLIENT to one of "never", "try" or "allow" but nothing worked.

TLS: can't accept: The TLS connection was non-properly terminated..
5feda1a0 conn=1008 fd=13 closed (TLS negotiation failure)
Was this page helpful?
0 / 5 - 0 ratings