Elixir :ssl certificate validation failures with custom CA bundles
0 reputation · 09 Aug 2021, 15:22 UTC
0 reputation · 09 Aug 2021, 15:22 UTC
When implementing secure connections using the :ssl module in Elixir, the runtime relies on the Erlang VM to validate certificates against the host operating system's CA store. In environments where certificates are managed via custom bundles or non-standard paths, the default validation behavior may fail to locate the necessary root certificates.
There is a design trade-off between relying on the system's default certificate store and explicitly defining cacertfile or cacerts options within the SSL configuration. Overriding these settings ensures consistency across different OS distributions but increases the maintenance burden for certificate rotation.
:ssl options?34775 reputation · 09 Aug 2021, 21:05 UTC
1. Prioritization of CA sources
cacertfile or cacerts is supplied in the SSL options, Erlang uses those PEM certificates exclusively; the system CA store is ignored.cacertfile or cacerts is specified./etc/ssl/certs on Linux, /etc/ssl/cert.pem on macOS, or the Windows store) is used.2. Updating the CA bundle dynamically
:ssl.set_options/2 on an existing listening socket. The new options will be applied to all new connections and, for listening sockets, to existing connections that are re‑accepted.:ssl.set_options/2 on the socket or forces a reconnect.priv/certs/root.pem.ssl_opts = [
cacertfile: Path.expand("priv/certs/root.pem", Mix.env() |> to_string()),
verify: :verify_peer,
depth: 5
]
:ssl.connect(:example.com, 443, ssl_opts, 5000)
FileSystem or fs to watch root.pem for changes.:ssl.set_options(socket, [cacertfile: new_path]) or simply close the socket and let the GenServer open a new one.IO.inspect(:ssl.connection_info(socket, :peer_certificate)) returns the expected cert.IO.inspect(:ssl.connection_info(socket, :peer_certificate)) before and after the reload to confirm the new CA bundle is in effect.Confirm the OTP release your node is running. The dynamic :ssl.set_options/2 approach requires OTP 20 or newer. If you’re on an earlier release, you’ll need to restart the socket or the whole node to pick up a new bundle.
Could you let me know which OTP version your application is using? That will determine whether the :ssl.set_options/2 method is available for your sockets.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.