There's isn't really a great way to solve this when you're talking about CoreOS (Fedora) and an Ubuntu/Debian guest. Fedora uses the modern standard for organizing the "trust-anchors", while Ubuntu/Debian still uses the older style. The two aren't directly compatible.
Having spent an excessively long time trying to solve the reverse of this problem (Fedora on Ubuntu), your options are:
- Get the container image to add first-class support for custom certificates to be added via environment variable (common on well crafted containers, but not going to happen for a direct Ubuntu distro image).
- Find a way to run a similar host system (usually not a viable option) and mount the host trust-anchors over the guest ones.
- Spin your own version of the image that adds the certs or support for specifying them (usually not maintainable to manage long-running fork)
- Wrap the ENTRYPOINT with a script that adds and runs the CA addition/installation from an optional extra host-mount (very problematic, see below)
- Run a/the container once with modified arguments to generate a copy of an updated trust-store in a host-mount, then host-mount that over subsequent runs of the container (do this one).
The very best option is usually to try to get the container image maintainer (or submit a PR yourself) to add support for loading extra CA certificates from an environment variable since this is a very common use case among corporate users and self-hosters. However this usually adds excessive overhead for one-shot containers that's unacceptable, and the image maintainer may have other good reasons not to do this. It also doesn't solve the problem for you in the mean time.
Changing your host and "forking" the image to spin your own also aren't great options, usually they're non-starters for deployment or maintainability reasons.
Wrapping the ENTRYPOINT is basically the equivalent of doing an ad-hoc version of modifying the container to support custom certificates, but purely from the outside of the image. It has all the same potential reasons for not doing it, and the downsides that you're doing it from outside the container, but has the benefit that you don't need to wait on an image update to do it. I would not recommend this option usually. This solution is basically to write a script you host-mount into the container that will do the CA setup, and then run whatever the ENTRYPOINT and CMDs are. However there are some major gotchas here. First, you need to customize it to specific container you're running so it runs the same entrypoint. With some scripting this can probably be determined, but you need to watch out for well-crafted containers that have an init system to handle the pid 1 problem (https://github.com/Yelp/dumb-init#why-you-need-an-init-system tl;dr: catching signals like interrupts and not losing system resources when force stopping a container requires a pid 1 init process to manage it). There are a handful of different init systems out there, and you can't wrap an init system. Additionally, if you're using Docker, you can't override entrypoints with multiple commands from the command-line. Containers with init systems like dumb-init
take an argument to the command actually being run, so the entrypoint is a list (['/usr/bin/dumb-init', '/usr/bin/my-command']
). Docker only allows multi-command entrypoints to be specified via the API, not via the command-line, so there's no way to keep the dumb-init
command and supply your own script for the second argument.
The "Best" Solution: While long running containers would strongly benefit from option #1 above, your best bet for one-shot containers and for an immediate solution is to generate a host-mount of the guest trust-anchors.
The best way is to generate a host-stored copy of what the updated container trust-anchors should look like, and mount that over the top of your container trust-store.
The most compatible way is to do this using the target container image itself, but with an override for the entrypoint, host-mounting a "cache" folder for the trust-anchors in the project workspace associated with the container. However that might not work in cloud and CI situations. An alternative option is to keep a separate container volume around that uses each of the two major trust-anchor styles (modern, e.g. Fedora, Arch, etc, and legacy, e.g. Debian, Ubuntu, etc) and is separately updated semi-regularly from a generic container image of the appropriate type. The resulting container volumes then merely becomes a volume dependency where the proper one is selected based on the target container image type.
The gist of how to generate one of these is to host-mount a script that adds the root CAs to the appropriate folder (FYI, legacy trust-anchors will search the root CA folders recursively, but modern will not), runs the trust-anchor update command, and then copies the resulting trust-anchor folders to a host-mount.
Update:
If it's still relevant, most Ubuntu container base images use cloud-init
internally (now), which has support for a lot of common things, including adding custom root CAs to the container image, e.g. they already support option 1.
https://cloudinit.readthedocs.io/en/latest/topics/examples.html#configure-an-instances-trusted-ca-certificates
I believe you can add a file mount to /etc/cloud/cloud.cfg.d/
that has YAML like in the example link and it will get picked up during container boot. You could easily generate that YAML programatically based on the the extra root CA certificates you wanted.
EDIT1: Fixed: I reversed which was host and guest from the original question. Also added update about cloud-init
.
EDIT2: Fixed style typo