0

Context

I have, for some reasons, the need to generate :

  • a root CA
  • an intermediate CA (signed by root CA)
  • a certificate (signed by intermediate CA)
  • the chain

I'm in a Dockerized environment, with 3 containers :

  • Container A : Nginx Reverse-proxy that decodes SSL (using chain + key) and forwards requests to Container B
  • Container B : Nginx (nothing special here, the responding app)
  • Container C : An application that needs to curl A (without insecure flags). I need to install intermediate CA on this one

It looks like an easy problem, but I'm stuck when Container C is based on Debian. It works like a charm on Ubuntu container for example. It also works with an Ubuntu desktop virtual machine. My intermediate CA also works on my mac using OSX keychain store.

This looks like a Debian specific issue.

How did I test

I followed several steps : - Generate the ca/certs/chain - Install the intermediate CA on my mac - curl -XGET https://service.local inside a terminal : OK

Then, using Docker, mount the intermediate CA on ubuntu, then call update-ca-certificates, and test using curl : OK

Then, using Docker, mount the intermediate CA on Debian, then call update-ca-certificates, and test using curl : KO

Scripting part

I've scripted the whole certs/ca/chain generation, no problem here, I won't go into detail unless you need them.

Docker-compose for Container C

I'm trying with different OS, that's why there are several services, and it shows I do the exact same thing between ubuntu and several versions of Debian.

I took some shortcuts by not calling update-ca-certificates ; instead I mount the file directly in /etc/ssl/certs since it's not doing much more really... For those who are wondering : I also tried to mount the file elsewhere, then call update-ca-certificates, then curl, with another version of the entrypoint, but same result at the end, it works on Ubuntu and not on Debian.

version: '2'

services:
    ubuntu:
        image : "ubuntu:16.04"
        volumes :
            - './local_ca/LOCAL_CA.crt:/etc/ssl/certs/local_ca.pem:ro'
            - './entrypoint.sh:/entrypoint.sh'
        command : 'bash -c "/entrypoint.sh"'

    debian7:
        image : "debian:wheezy"
        volumes :
            - './local_ca/LOCAL_CA.crt:/etc/ssl/certs/local_ca.pem:ro'
            - './entrypoint.sh:/entrypoint.sh'
        command : 'bash -c "/entrypoint.sh"'

    debian8:
        image : "debian:jessie"
        volumes :
            - './local_ca/LOCAL_CA.crt:/etc/ssl/certs/local_ca.pem:ro'
            - './entrypoint.sh:/entrypoint.sh'
        command : 'bash -c "/entrypoint.sh"'

    debian9:
        image : "debian:stretch"
        volumes :
            - './local_ca/LOCAL_CA.crt:/etc/ssl/certs/local_ca.pem:ro'
            - './entrypoint.sh:/entrypoint.sh'
        command : 'bash -c "/entrypoint.sh"'

entrypoint.sh

For the sake of the example, assume the IP is known and replaced in the following template :

#!/bin/bash

apt-get update
apt-get install -y curl
echo '{{ip_of_reverse_proxy}} service.local' >> /etc/hosts
curl -XGET https://service.local

As I said before, I also did a version where I call update-ca-certificates instead of mounting directly, but it didn't make any difference, it works on Ubuntu and not on Debian

docker-compose logs

Here are the output logs, truncated so that we only get the interesting part. As you can see, curl on ubuntu answers with a JSON whereas debian refuses the certificate verification since root ca is not trusted.

ubuntu_1   | {"_links":{"self":{"href":"\/"}}}

debian7_1  | curl performs SSL certificate verification by default, using a "bundle"
[...] (see debian9_1 logs)

debian8_1  | curl performs SSL certificate verification by default, using a "bundle"
[...] (see debian9_1 logs)

debian9_1  | curl: (60) SSL certificate problem: self signed certificate in certificate chain
debian9_1  | More details here: https://curl.haxx.se/docs/sslcerts.html
debian9_1  |
debian9_1  | curl performs SSL certificate verification by default, using a "bundle"
debian9_1  |  of Certificate Authority (CA) public keys (CA certs). If the default
debian9_1  |  bundle file isn't adequate, you can specify an alternate file
debian9_1  |  using the --cacert option.
debian9_1  | If this HTTPS server uses a certificate signed by a CA represented in
debian9_1  |  the bundle, the certificate verification probably failed due to a
debian9_1  |  problem with the certificate (it might be expired, or the name might
debian9_1  |  not match the domain name in the URL).
debian9_1  | If you'd like to turn off curl's verification of the certificate, use
debian9_1  |  the -k (or --insecure) option.

Questions

Question 1 : As I inject the exact same files and follow the exact same process, why does it work on ubuntu but not debian ? Aren't they sharing the same base ?

Question 2 : What's the right solution for Debian ? Do I really need to also inject and install the root CA ? (it works when I do that, but it looks weird to me since intermediate CA should be enough)

2

After further investigation, the biggest difference between ubuntu and debian is the SSL library used :

  • On Debian, curl is pre-compiled with OpenSSL
  • On Ubuntu, curl is pre-compiled with GnuTLS

I recompiled curl with GnuTLS on Debian and it works fine using only the intermediate CA.

I recompiled curl with OpenSSL on Ubuntu and now have to trust the root CA if I want my request to pass through.

0

You don't need to install any subordinate CA certificates in the relying-party (Container C).

RFC 5246 7.4.2 states that the server must provide any and all subordinate CA certificate in the form of a chain. That is, your Ngnix server in Container A must be configured to send the certificates (other than the Root CA certificate) to the client when connecting.

Only the Root CA certificate will have to be installed on the client (Container C) for it to trust the chain provided by the server.

  • It still doesn't explain why curl on ubuntu accepts the request without a trusted root CA. – NaS Sep 29 '17 at 15:28
0

Put the root CA in /etc/ssl/certs/yourCAnamehere.pem file and then run update-ca-certificates --fresh on the container C

The chain (intermediate CA aswell) is not trusted because the root CA is not trusted, by adding it to trusted CA's you should be able to perform the requests normally

  • It doesn't explain why curl on ubuntu accepts the request without a trusted root CA – NaS Sep 29 '17 at 15:27

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.