dotnet / sdk-container-builds

Libraries and build tooling to create container images from .NET projects using MSBuild
https://learn.microsoft.com/en-us/dotnet/core/docker/publish-as-container
MIT License
175 stars 30 forks source link

Feature Request: easier support for CA cert install from volume #531

Closed JeroMiya closed 5 months ago

JeroMiya commented 6 months ago

Here's my main scenario: I'm running a multi-container application locally for both local development and automated testing purposes. This typically includes an instance of identity server as well as an API and a UI container, plus the database and maybe one or two additional services. These particular builds of the application are not published for production. Typically they are running the debug configuration, for example. I just use docker compose for local development orchestration and automated testing.

Of particular note is the existence of the identity server container. It's notable because it's existence implies that containers MUST be able to make backchannel requests to each other under TLS. In a simpler scenario that did not involve backchannel communications, I could just create an nginx reverse proxy (or a YARP based equivalent) that performed SSL termination similar to a Kubernetes Ingress resource, but that is not sufficient for this scenario. For example, the API must request the discovery endpoint via https and not http. The discovery endpoint must return https urls and not http for various backchannel endpoints. In some cases, the relevant Asp.Net middleware requires https authorities, at least by default.

So given that this scenario requires encrypted backchannel communications between containers, and assume for the moment that mounting an actually valid certificate that is not self-signed is not an option for local development or automated testing, then this implies that we must install such a self-signed development certificate (in our case, one that we must generate ourselves, as the dotnet https dev-cert only works for localhost, and we must add additional domains to work within a docker virtual network). Otherwise any request from one container to another over HTTPS will fail validation.

Our current solution is to mount our development certificates into the container, and we've modified the entrypoint to:

  1. Start as the root user
  2. Run the update-ca-certificates command (we're using the alpine base images)
  3. Switch to the app user
  4. Run our app

Note that we have to run update-ca-certificates in the entrypoint, because the certificate itself is to be mounted when the container is launched. It's not available at image build time.

Now, I would love to be able to use the new SDK container builds using msbuild instead of a dockerfile. And I'd also like to switch from the alpine images to the chiseled images. But I'm not sure if that's possible. I know I can set the entrypoint, so if I stayed on the alpine images and update-ca-certificates is pre-installed, I can just continue doing what we're already doing. But I'm not sure how I would do this for the chiseled images, which do not have a root user.

I'd love for there to be an easy way to generate an image that I can dynamically mount development https certs in a consistent way across all the base images, including distro-less and rootless base images like the chiseled images. That would allow us to use the same base images for local development and automated testing that we use for production (aside from debug vs release configuration).

tmds commented 6 months ago

With .NET 8+, you can set the SSL_CERT_DIR envvar to (colon separated) directory paths.

This allows you to add additional ca certificates, like from a directory that is mounted in the container.

To include the system cert directory, add /etc/ssl/certs as one of the directories in SSL_CERT_DIR.

cc @baronfel

baronfel commented 5 months ago

@tmds's answer is exactly how I'd handle this, personally.

JeroMiya commented 5 months ago

Thanks for your quick answer! Apologies, I forgot to close this earlier. This sounds perfect!