Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rely on cert stores provided by Erlang/OTP +25 #86

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 58 additions & 15 deletions lib/rustler_precompiled.ex
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@
* `HTTPS_PROXY` or `https_proxy` - Sets the HTTPS proxy configuration.

* `HEX_CACERTS_PATH` - Sets the path for a custom CA certificates file.
If unset, defaults to `CAStore.file_path/0`.
If unset, defaults to `:public.cacerts_get/0` (OTP >= 25) if available.
In case it's running on an old OTP version, a warning is emitted.

* `MIX_XDG` - If present, sets the OS as `:linux` for the `:filename.basedir/3` when getting
an user cache dir.
Expand Down Expand Up @@ -926,21 +927,17 @@
:httpc.set_options([{:https_proxy, {{String.to_charlist(host), port}, []}}])
end

# https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/inets
# respects the user provided ca certs via Hex env var
cacertfile = System.get_env("HEX_CACERTS_PATH", CAStore.file_path())

http_options = [
ssl: [
verify: :verify_peer,
cacertfile: cacertfile |> String.to_charlist(),
# We need to increase depth because the default value is 1.
# See: https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/ssl
depth: 3,
customize_hostname_check: [
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
]
]
ssl:
[
verify: :verify_peer,
# We need to increase depth because the default value is 1.
# See: https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/ssl
depth: 3,
customize_hostname_check: [
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
]
] ++ cacerts_options()
]

options = [body_format: :binary]
Expand All @@ -957,6 +954,52 @@
end
end

# https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/inets
defp cacerts_options do
cond do
path = System.get_env("HEX_CACERTS_PATH") ->
[cacertfile: path]

certs = otp_cacerts() ->
[cacerts: certs]

true ->
warn_no_cacerts()
[]
end
end

defp otp_cacerts do
if System.otp_release() >= "25" do
# cacerts_get/0 raises if no certs found
try do
:public_key.cacerts_get()

Check warning on line 976 in lib/rustler_precompiled.ex

View workflow job for this annotation

GitHub Actions / test (1.13, 24)

:public_key.cacerts_get/0 is undefined or private
rescue
_ -> nil
end
end
end

defp warn_no_cacerts do
Logger.warning("""
No certificate trust store was found.

A certificate trust store is required in
order to download locales for your configuration.
Since rustler_precompiled could not detect a system
installed certificate trust store one of the
following actions may be taken:

1. Specify the location of a certificate trust store
by configuring it in environment variable:

export HEX_CACERTS_PATH="/path/to/cacerts.pem"

2. Use OTP 25+ on an OS that has built-in certificate
trust store.
""")
end

# Download a list of files from URLs and calculate its checksum.
# Returns a list with details of the download and the checksum of each file.
@doc false
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ defmodule RustlerPrecompiled.MixProject do
defp deps do
[
{:rustler, "~> 0.23", optional: true},
{:castore, "~> 0.1 or ~> 1.0"},
{:castore, "~> 0.1 or ~> 1.0", optional: true},
{:ex_doc, "~> 0.27", only: :dev},
{:bypass, "~> 2.1", only: :test}
]
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%{
"bypass": {:hex, :bypass, "2.1.0", "909782781bf8e20ee86a9cabde36b259d44af8b9f38756173e8f5e2e1fabb9b1", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "d9b5df8fa5b7a6efa08384e9bbecfe4ce61c77d28a4282f79e02f1ef78d96b80"},
"castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"},
"castore": {:hex, :castore, "1.0.9", "5cc77474afadf02c7c017823f460a17daa7908e991b0cc917febc90e466a375c", [:mix], [], "hexpm", "5ea956504f1ba6f2b4eb707061d8e17870de2bee95fb59d512872c2ef06925e7"},
"cowboy": {:hex, :cowboy, "2.10.0", "ff9ffeff91dae4ae270dd975642997afe2a1179d94b1887863e43f681a203e26", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
"cowlib": {:hex, :cowlib, "2.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"},
Expand Down
Loading