Use :public_key.cacerts_get for OTP 25+
yordis opened this issue · 6 comments
**Is your feature request related to a problem?
When calling :ldclient_config.tls_basic_options()
is giving us the following warning:
[warning] TLS options are falling back to using the certifi store.
This means the OS certificate store was not in the default location (/etc/ssl/certs/ca-certificates.crt).
Please specify a custom location. You can use tls_ca_certfile_options, or fully specify the tls_options.
You may see this warning in development on Mac/Windows.
I understand the warning is expected in development for Mac/Wins, but the situation could be improve for OTP 25+
Describe the solution you'd like
Use :public_key.cacerts_get()
for OTP 25+ when calling :ldclient_config.tls_basic_options()
or even better, add sensitive SSL options by default here
erlang-server-sdk/src/ldclient_config.erl
Line 130 in 124544e
Describe alternatives you've considered
Maintain sensitive configuration in our end:
[
verify: :verify_peer,
cacerts: :public_key.cacerts_get(),
depth: 3,
customize_hostname_check: [
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
]
]
I do not consider a security expert myself so having a sensitive default that I do not mess around with is really valuable.
Additional context
Add any other context about the feature request here.
Hello @yordis,
I will take a look at :public_keycacerts_get
to see if I can cleanly incorporate it into the fallback chain (it appears that this is something that can still fail/be empty). Generally speaking the problems have been maintaining both compatibility for customers using the SDK as well as compatibility with a wide range of OTP versions.
My experience so far is that there have not been any defaults which I would be comfortable enabling. It is paramount that the defaults don't prevent a connection that was working from continuing to work, and most any defaults could result in that situation. OTP has been gradually improving on this front, but I think for production environments some care needs to be taken to ensure you are comfortable with the TLS configuration.
Additionally I want to make sure when you use our basic options they are not too lenient. Meaning that an invalid expired certificate does fail to connect, that only reasonable secure ciphters are supporte, etc., which it takes a surprising number of options to ensure happens.
Thank you,
Ryan
Filed internally as 226320
Feedback from the SRE team (and myself) is that they would rather control the certificates using the VM/Container than rely on libraries. They are a cadence for the Containers to be updated and whatnot.
Yes, and we have a helper method that accepts the path to the store and uses the same other options as the basic_options, but doesn't attempt auto-detection of your store location. -spec tls_ca_certfile_options(CaStorePath :: string())
which is what the warning is attempting to direct you to. Generally you should be using your system store, or a specific store with only certs you trust, so we produce that warning. You provide the path to the store you want to use, and the SDK will use it.
The fallback to certifi is just for when we couldn't figure out any certificates, and you didn't specifically say which ones to use. This will remain with :public_key:cacerts_get
in the case that no certs are returned.
For instance, with public_key:cacerts_get
a static list of locations is also being used:
linux_paths() ->
["/etc/ssl/certs/ca-certificates.crt", %% Debian, Ubuntu, Gentoo
"/etc/pki/tls/certs/ca-bundle.crt", %% Fedora, RHEL 6, Amazon Linux
"/etc/ssl/ca-bundle.pem", %% OpenSUSE
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", %% CentOS, RHEL 7
"/etc/ssl/cert.pem" %% Alpine Linux
].
Source location: https://github.com/erlang/otp/blob/1cfee42abc140e91f00f23b628728b42b93b6efd/lib/public_key/src/pubkey_os_cacerts.erl#L185C8-L185C8
So, if your linux configuration doesn't have them in the same location as one of those, then it would still need to be manually specified.
So, for instance, if you are using Alpine images right now, then you would use: ldclient_config:tls_ca_certfile_options("/etc/ssl/cert.pem" )
which would have all the same basic options, assuming you are happy with those, and it would use the store from that location.
Thank you,
Ryan
Related to https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/ssl
Do you have any opinions about using the following config in OTP25+
[
verify: :verify_peer,
cacerts: :public_key.cacerts_get(),
depth: 3,
customize_hostname_check: [
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
]
]
Also, I gather some feedback from the Erlang Ecosystem Foundation:
Bram Verburg:
Setting ciphers used to be important in older OTP versions, especially in servers, as by default it enabled a lot of legacy/unsafe ciphers. In newer OTP versions the standard list is quite safe and it is often not necessary to override it
That seems reasonable.
Personally I am most comfortable when I have verified that at least some bad cases do fail. Being as positive cases pass even without TLS.
For instance doing a couple httpc requests with your config to known bad endpoints. I would have recommended badssl.com, but unfortunately it seems to have become unmaintained as some of the "good" configurations now have expired certs.
@kinyoklion any thoughts about #114