-
-
Notifications
You must be signed in to change notification settings - Fork 14.8k
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
SSL certificates: figure out how libs/apps find them by default #8247
Comments
I found an excellent email exchange on the openssl mailing list: https://mta.openssl.org/pipermail/openssl-users/2015-December/002553.html. Basically, we need
At the moment, openssl is broken without SSL_CERT_FILE because it has no default trust store. (Technically it is false, openssl trust store defaults to /nix/store/-openssl-version/etc/ssl/cert.pem, which does not exist 😈)
Option 2 is straightforward, but we can do better than that! So we need to ship openssl with sane defaults. --- a/pkgs/development/libraries/openssl/default.nix
+++ b/pkgs/development/libraries/openssl/default.nix
@@ ... @@ stdenv.mkDerivation rec {
configureFlags = [
"shared"
"--libdir=lib"
- "--openssldir=etc/ssl"
+ "--openssldir=etc/ssl/openssl"
] ++ stdenv.lib.optionals withCryptodev [
"-DHAVE_CRYPTODEV"
"-DUSE_CRYPTODEV_DIGESTS"
];
@@ ... @@ stdenv.mkDerivation rec {
postInstall = ''
# If we're building dynamic libraries, then don't install static
# libraries.
if [ -n "$(echo $out/lib/*.so $out/lib/*.dylib $out/lib/*.dll)" ]; then
rm "$out/lib/"*.a
fi
# remove dependency on Perl at runtime
rm -r $out/etc/ssl/misc $out/bin/c_rehash
+
+ # Setup default ssl files location
+ # The openssl subdir is a trick to avoid infinite loops when building the environment without cacert.
+ mv $out/etc/ssl/openssl/* $out/etc/ssl
+ rmdir $out/etc/ssl/openssl
+ ln -s /etc/ssl/ $out/etc/ssl/openssl
+ ln -s /etc/ssl/certs/ca-certificates.crt $out/etc/ssl/cert.pem
''; @vcunat, Anything against this patch ? |
This is a small memo to understand how apps work with ssl files. Nix and NixOS are missing strong guidelines on how to find and manage the default trust store. Due to this confusion, several issues were raised on this mailing list and on GitHub. These issues concern
These issues arises because there is no consensus on where to find the default, system-wide trusted certificates. There are four ways that applications can use to locate the default trust database:
Most distros try to configure and patch the programs that use certificates to use their main trust store. # Excerpt from nix-profile.sh.in :
# Set $SSL_CERT_FILE so that Nixpkgs applications like curl work.
if [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch
export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
elif [ -e /etc/ssl/certs/ca-bundle.crt ]; then # Old NixOS
export SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
elif [ -e /etc/pki/tls/certs/ca-bundle.crt ]; then # Fedora, CentOS
export SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt
elif [ -e "$NIX_LINK/etc/ssl/certs/ca-bundle.crt" ]; then # fall back to cacert in Nix profile
export SSL_CERT_FILE="$NIX_LINK/etc/ssl/certs/ca-bundle.crt"
elif [ -e "$NIX_LINK/etc/ca-bundle.crt" ]; then # old cacert in Nix profile
export SSL_CERT_FILE="$NIX_LINK/etc/ca-bundle.crt"
fi This is extremely important for Nix itself to work properly as derivations and nix archives are downloaded using HTTPS. As this variable only affects OpenSSL, the other security libraries and applications are left guessing for the right path to use and often fail. On NixOS, the situation is completely reversed. However, making derivations depend on cacert is not a good idea because
For these reasons NixOS uses the path However, this global environment is not available to systemd units, which is the reason why so many users hit the mailing list with the issue of a command working perfectly well in their shell and failing when started in a unit. Now, on NixOS we do not need the flexibility to change the trust store, because we "know" that it will be My proposal is therefore to make all the crypto libraries look for a default trust database in This proposal requires subtle patches to nixpkgs. As an example, git needs no patching, because it relies on the default trust store provided by libcurl. The current Use $SSL_CERT_FILE to get the CA certificates.
diff -ru -x '*~' LWP-Protocol-https-6.02-orig/lib/LWP/Protocol/https.pm LWP-Protocol-https-6.02/lib/LWP/Protocol/https.pm
--- LWP-Protocol-https-6.02-orig/lib/LWP/Protocol/https.pm 2011-03-27 13:54:01.000000000 +0200
+++ LWP-Protocol-https-6.02/lib/LWP/Protocol/https.pm 2011-10-07 13:23:41.398628375 +0200
@@ -21,6 +21,11 @@
}
if ($ssl_opts{SSL_verify_mode}) {
unless (exists $ssl_opts{SSL_ca_file} || exists $ssl_opts{SSL_ca_path}) {
+ if (defined $ENV{'SSL_CERT_FILE'}) {
+ $ssl_opts{SSL_ca_file} = $ENV{'SSL_CERT_FILE'};
+ }
+ }
+ unless (exists $ssl_opts{SSL_ca_file} || exists $ssl_opts{SSL_ca_path}) {
eval {
require Mozilla::CA;
}; In this case, the Perl module does not rely on any default trust store, and requires the Finally, we may want to patch derivations providing their own trust store to use the system one, or not. |
Contrary to what the name of the PR implies, it does not kill |
My issue with the current merged patch is that we removed the support of SSL_CERT_FILE from cURL and provided a default location for the trust store. I made more moderate patches on my own repo at https://github.com/layus/nixpkgs/tree/fix-openssl-defaults. |
What if the default trust store was /nix/etc/ssl/cert.pem (or something under /nix) ? That's a path that we control on all systems. During install it could then be symlinked to the target OS's trust store. Before install it could also be pre-seeded with enough certs for nix to fetch stuff from the hydra cache. On OSX the situation would be a bit more complicated because they store their certs in another format called the Keychain and it's all over the place. Homebrew's install of openssl solves the issue by generating their own cert.pem. I suppose that file needs to be kept in sync with the Keychain but again it could be put under /nix/etc/ssl/cert.pem. The issue with relying on the SSL_CERT_FILE is that it might not be available when running |
Looks like a great idea to me. You simply set the right symlink at install time. And it works equally well for Nix and NixOS. Perfect ! Does Windows support this ? |
I haven't looked at Windows in details because it's not an official Nix target. Windows itself has it's own CA store like OSX and we would need an export script to generate the PEM file. It's possible that Cygwin and friends already deal with the issue. The day where we want to support Window I expect the target to be Windows+Cygwin or Windows+MinGW, ... |
I'm not certain if someone actually wants to control the trust store globally for all nix stuff but separately from the OS. It seems enough to me to use the OS trust store as the default and allow overriding it by an env var. BTW, rather than |
Using /nix/var/nix/profiles/default/etc/ssl/ might work if nix-env detects the location of the trust store. |
also of note, setting SSL_CERT_FILE globally or per-service doesn't work in the case of php-fpm, it scrubs the env on startup by default, so it has to be entered into the php.ini file, or compiled in as a default |
@layus thank you it's really helpful to have a birdeye view to make sense of it.. |
The real solution is to use the platform trust stores, but not all upstream projects support all platforms. The second best solution is to periodically run something like https://github.com/raggi/openssl-osx-ca/blob/master/bin/openssl-osx-ca which dumps the trust store into a properly formatted file. I am a big fan of storing global state in So I propose that from now on all Nix-related global state is stored under |
Any new on this? There's a couple of related issues, with various workarounds. |
Could you describe your specific issue, possibly in a new thread ? Link it to this thread, and tag me if needed. The current state should be OK for most use cases. |
I want to bring up an issue when the user has custom root certificates installed. My setup is NixOS with extra certificates defined by IssueThere are two certificate bundles that are currently used in Nixpkgs:
Find usages: [~/projects/nixos/nixpkgs]$ nix-shell -p ag --run 'ag /etc/ssl/certs/ca-bundle.crt pkgs'
[~/projects/nixos/nixpkgs]$ nix-shell -p ag --run 'ag /etc/ssl/certs/ca-certificates.crt pkgs' The problem with the first, The second approach, constant I experience problems with packages that use Proposed solution with managed bundle under the |
@4e6 You are right that ${cacert}/etc/ssl/certs/ca-bundle.crt should not be used. It forces a rebuild of the package everytime a certificate changes. That being said, /etc/ssl/certs/ca-certificates.crt should not be used directly, only as a fallback if NIX_SSL_CERT_FILE is not set. In all cases, NIX_SSL_CERT_FILE should be observed by nix packages. This is the new standard as per NixOS/nix@fb2dd32. A migration has started with the new commit 942dbf8 @edolstra We should probably make an announcement on the mailing list about how to manage certificates. Using NIX_SSL_CERT_FILE is quite a big change and may break many configurations. |
I marked this as stale due to inactivity. → More info |
Still important to me |
Finally #96763 made it into unstable. We now have all nss-based application using p11-kit and reading certificates from the system-wide trust store! |
…and this change needed to be turned off specifically for Firefox due to #126065 — the current form of p11-kit integration is not enough for Firefox, because the Mozilla code relies on the |
The solution should be to change |
The requests library defaults to using the certificates from the certifi library when not otherwise specified. If I understand the discussion at NixOS#8247 correctly, we should instead patch it so that it follows the following priority order: 1. the path pointed to by the environment variable $NIX_SSL_CERT_FILE 2. /etc/ssl/certs/ca-certificates.crt 3. whatever it was doing before (in this case, using certifi) This commit implements that.
The requests library defaults to using the certificates from the certifi library when not otherwise specified. If I understand the discussion at #8247 correctly, we should instead patch it so that it follows the following priority order: 1. the path pointed to by the environment variable $NIX_SSL_CERT_FILE 2. /etc/ssl/certs/ca-certificates.crt 3. whatever it was doing before (in this case, using certifi) This commit implements that.
The requests library defaults to using the certificates from the certifi library when not otherwise specified. If I understand the discussion at #8247 correctly, we should instead patch it so that it follows the following priority order: 1. the path pointed to by the environment variable $NIX_SSL_CERT_FILE 2. /etc/ssl/certs/ca-certificates.crt 3. whatever it was doing before (in this case, using certifi) This commit implements that.
Anything happening with this? I have a company cert that I need java to accept. If there is a workaround to that I can make a separate ticket. |
Was there ever any documentation produced about what the right pattern is? I see a lot of uses of If I understand it correctly |
One particular example is |
Yes, it's still not at all unified even in the perspective of static vs. OS-provided. Apparently different packages/maintainers differ in opinion here. |
For some options already discussed see #8121 (comment).
The text was updated successfully, but these errors were encountered: