symfony-docker icon indicating copy to clipboard operation
symfony-docker copied to clipboard

[DX] Automatically trust Caddy's internal CA locally

Open Jayfrown opened this issue 2 years ago • 6 comments

Hi!

I started using the docker-compose configuration provided by this repository in order to support Mercure in my app. After some tinkering, I got it to work within the dockerized environment.

After getting it to work, I ran into some issues regarding local development and testing. I eventually found the Mercure HubStub examples in the documentation and got local unit tests to work again.

I'm still running into an issue when running local commands that want to send real Mercure updates, because the dockerized Caddy generates a CA, and uses that CA to generate a certificate. This CA is automatically trusted in the docker container, but not in my local PHP installation. This ultimately leads to such issues:

❯ ./bin/console hautelook:fixtures:load
Careful, database will be purged. Do you want to continue y/N ?y

In Hub.php line 104:
  Failed to send an update.  

In CommonResponseTrait.php line 148:
  SSL certificate problem: unable to get local issuer certificate for "https://localhost/.well-known/mercure".  

In ErrorChunk.php line 65:
  SSL certificate problem: unable to get local issuer certificate for "https://localhost/.well-known/mercure".  

In CurlResponse.php line 338:
  SSL certificate problem: unable to get local issuer certificate for "https://localhost/.well-known/mercure".  

hautelook:fixtures:load [-b|--bundle [BUNDLE]] [--no-bundles] [-m|--manager MANAGER] [--append] [--shard SHARD] [--purge-with-truncate]

I am temporarily hacking around this by manually extracting the generated CA and inserting it into the trust store used by my local PHP installation as follows:

❯ docker compose exec caddy /bin/sh -c 'cat /data/caddy/pki/authorities/local/root.crt' >> /usr/local/etc/[email protected]/cert.pem

❯ ./bin/console hautelook:fixtures:load
Careful, database will be purged. Do you want to continue y/N ?y

However, this would be necessary each time Caddy generates a new CA.

This seems to be a DX issue users would run into when using the suggested default configuration. It could be overcome by supplying your own certificates using a static/unchanging CA, but it would be neat if we could somehow automatically trust the generated CA locally as well.

Jayfrown avatar Jan 12 '22 00:01 Jayfrown

Why don't you run your PHP commands inside the PHP containers instead of on the host?

dunglas avatar Jan 12 '22 08:01 dunglas

A work has already been started here: https://github.com/dunglas/symfony-docker/pull/106

maxhelias avatar Jan 12 '22 08:01 maxhelias

Why don't you run your PHP commands inside the PHP containers instead of on the host?

Mostly because it is what I am used to. Running it in the docker containers is (slightly) more complicated but honestly it's just a preference. I want to work locally and use docker to abstract some services, without necessarily having to adopt a docker-first work method.

#106

Thanks, that looks like it should work. I didn't know about the /data/caddy/pki/authorities/local/root.crt location -- that makes my 'solution' slightly less convoluted. (edited in original post). Perhaps this could be documented around here as well, as it is basically the same thing specifically for local PHP instead of the system trust store.

I will try the set-up with static certs created by mkcert and report back on the PR.

Jayfrown avatar Jan 12 '22 12:01 Jayfrown

ref https://github.com/dunglas/symfony-docker/pull/106#issuecomment-1011046380

Jayfrown avatar Jan 12 '22 13:01 Jayfrown

TL;DR the proposed configuration allows Caddy to use the locally generated certificate (with the CA generated by mkcert) but now that certificate isn't trusted by the docker PHP container, meaning the running app cannot send Mercure updates.

I will revert to using Caddy's internally generated CA for now, using the following commands to trust the CA within my local PHP set-up:

  1. Find the trust store used by PHP:
❯ grep "openssl.cafile.*=" $(php --ini | grep 'php.ini$' | awk '{ print $NF }') | awk '{ print $NF }'
  1. Add the CA generated by Caddy to your local PHP's trust store
❯ docker compose exec caddy /bin/sh -c 'cat /data/caddy/pki/authorities/local/root.crt' >> $trust_store_location

The generated CA seems to survive container reboots as well as rebuilds, and only seems to be re-generated if the docker volume is removed. Maybe we can document this somewhere.

Jayfrown avatar Jan 12 '22 14:01 Jayfrown

I just realized the docker PHP container is, by default, configured to send Mercure updates over HTTP instead of HTTPS.

Adding 127.0.0.1 caddy to /etc/hosts allows me to configure MERCURE_URL=http://caddy/.well-known/mercure and everything works out-of-the-box without needing to explicitly trust anything.

Jayfrown avatar Jan 12 '22 14:01 Jayfrown

Close for https://github.com/dunglas/symfony-docker/pull/106

maxhelias avatar Oct 18 '22 09:10 maxhelias