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

SSL_CERT_FILE should be in systemd.globalEnvironment (See #8247 instead) #8486

Closed
layus opened this issue Jun 24, 2015 · 11 comments
Closed

SSL_CERT_FILE should be in systemd.globalEnvironment (See #8247 instead) #8486

layus opened this issue Jun 24, 2015 · 11 comments
Labels
0.kind: enhancement Add something new 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS

Comments

@layus
Copy link
Member

layus commented Jun 24, 2015

Any service that uses SSL will need this variable.
A look to the current usage shows that SSL_CERT_FILE is indeed imported in some service files, but not correctly defined (search for environment.SSL_CERT_FILE).

One would expect

{
    # ...
    environment = {
      inherit (config.environment.variables) SSL_CERT_FILE;
    };
}

instead of { environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt"; }.

currently, the only environment variable in globalEnvironment is TZDIR. It seems to me that SSL_CERT_FILE is just as "global" as TZDIR.

I am ready to submit a pull-request if this sounds acceptable.

[EDIT] s/TZ_DATA/TZDIR/

@vcunat vcunat added 0.kind: enhancement Add something new 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS labels Jun 25, 2015
@vcunat
Copy link
Member

vcunat commented Jun 25, 2015

Sounds reasonable to me. Related: #8247.

@edolstra
Copy link
Member

I'm not sure. In general, the global systemd environment should be kept small, just like the default $PATH should be kept small, for these reasons:

  • Any change to a global dependency will cause all services to be restarted by switch-to-configuration. And most services don't actually use SSL_CERT_FILE.
  • For reproducibility, implicit dependencies should be minimized, so global dependencies should be used sparingly.

@layus
Copy link
Member Author

layus commented Jun 26, 2015

Any change to a global dependency will cause all services to be restarted by switch-to-configuration. And most services don't actually use SSL_CERT_FILE.

For reproducibility, implicit dependencies should be minimized, so global dependencies should be used sparingly.

In this particular case, the value of SSL_CERT_FILE is not supposed to change. It is a static path, independent of the cacert & co derivations. Therefore not a real dependency.
Just like TZDIR; both are just strings.

I stumbled into this problem when trying to write a systemd service+timer for urlwatch (python2), and could not understand why certificate validation failed in the service while it worked perfectly from the shell.

This is indeed a problem with SSL_CERT_FILE and how packages find certificates.
Current uses of SSL_CERT_FILE in services environment fix the problem python has finding certificates, other tools seem not to require SSL_CERT_FILE.

Bottom line: We better first take a decision about cacert and SSL_CERT_FILE (secure enough, etc...) and then come back to this issue later.
What do you think ?

@zimbatm
Copy link
Member

zimbatm commented Jan 17, 2016

In this particular case, the value of SSL_CERT_FILE is not supposed to change. It is a static path, independent of the cacert & co derivations.

Why isn't that path hard-coded in the executable then ? I'm asking because this SSL_CERT_FILE environment variable is causing issues on Darwin.

@vcunat
Copy link
Member

vcunat commented Jan 18, 2016

I thought the point of $SSL_CERT_FILE is that you can easily override it globally when on non-NixOS with different default location of the file.

@zimbatm
Copy link
Member

zimbatm commented Jan 18, 2016

In general I think that it's preferable to have a single central CA store per system in order to have consistent access to SSL resources. For example if my organisation depends on a self-generated CA for internal services, the sysadmin/user wants to be able to install it once per machine. If we introduce our own SSL_CERT_FILE it means that maybe Safari is going to work but then when the developer goes in the shell and runs curl it's not going to work.

The SSL_CERT_FILE is only installed when the nss-cacert package is installed so I removed it for now.

@layus
Copy link
Member Author

layus commented Jan 28, 2016

Okay, I think I figured out the bottom of this issue.

The normal behaviour is to have the path to the SSL_CERT_FILE hardcoded into the executable.
This leaves SSL_CERT_FILE to modify the behaviour of some invocations.

However, python has has no hardcoded path, hence the need to always have SSL_CERT_FILE defined in its environment for ssl to work properly.

Proof (kinda :-))

$ echo $SSL_CERT_FILE 
/etc/ssl/certs/ca-certificates.crt
$ readlink /etc/ssl/certs/ca-certificates.crt
/etc/static/ssl/certs/ca-certificates.crt
$ readlink /etc/static/ssl/certs/ca-certificates.crt
/nix/store/vnwwmdmw1895ilipj5lykps83hfrdyhp-ca-bundle.crt
$ python3                                                                                                                                   
Python 3.4.4 (default, Dec 21 2015, 06:01:07) 
[GCC 4.9.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(
    cafile='/etc/ssl/certs/ca-certificates.crt',
    capath='/nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/etc/ssl/certs',
    openssl_cafile_env='SSL_CERT_FILE',
    openssl_cafile='/nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/etc/ssl/cert.pem',
    openssl_capath_env='SSL_CERT_DIR',
    openssl_capath='/nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/etc/ssl/certs')
$ unset SSL_CERT_FILE
$ python3
Python 3.4.4 (default, Dec 21 2015, 06:01:07) 
[GCC 4.9.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(
    cafile=None,
    capath='/nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/etc/ssl/certs',
    openssl_cafile_env='SSL_CERT_FILE',
    openssl_cafile='/nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/etc/ssl/cert.pem',
    openssl_capath_env='SSL_CERT_DIR',
    openssl_capath='/nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/etc/ssl/certs')

By the way, /nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/etc/ssl/cert.pem does not even exist in /nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/.

$ tree /nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/etc 
/nix/store/ik8d2g12y2hj5y4k32ca3cgm53v3h0va-openssl-1.0.1q/etc
└── ssl
    ├── certs
    ├── openssl.cnf
    └── private

Similar issue happened on other linux distros.
This question on StackExchange refers to a FreeBSD issue similar to ours, and containing more explanations on how python finds SSL files.

@zimbatm, it seems you are right, this should be hardcoded in the executable, but how ?
For now, python cannot work without SSL_CERT_FILE, unless recently fixed ?
There is also the possibility that python uses other environment variables to make SSL work.

So, how the hell do apps find their SSL config ? (#8247)
@vcunat, how can I help with #8247 ?

cc @4levels, for the similar issue reported on the mailing list

@layus
Copy link
Member Author

layus commented Jan 28, 2016

I am now able to tell where openssl finds its default certificates.

Python relies on openssl defaults when using the ssl module.
The default value comes from X509_CERT_FILE defined by https://github.com/openssl/openssl/blob/master/crypto/include/internal/cryptlib.h.

If we want to define once and for all the certificate store store, whe should probably modify it.

That being said, the variable is set to SSLCERTS:cert.pem, so we need to reverse engineer the build scripts to find an entry point. This may not be sane :-).

As a side note, the requests module is unaffected because it comes with its own certificates...

@layus layus changed the title [nixos] SSL_CERT_FILE should be in systemd.globalEnvironment SSL_CERT_FILE should be in systemd.globalEnvironment Jan 28, 2016
@vcunat
Copy link
Member

vcunat commented Jan 28, 2016

@vcunat, how can I help with #8247 ?

I don't really know. I just felt there's not a clear consensus how to approach these issues and so we aren't very consistent in that.

@zimbatm
Copy link
Member

zimbatm commented Jan 29, 2016

In NixOS, security.pki.certificateFiles is available to configure /etc/ssl/certs/ca-bundle.crt so we should probably re-use that instead of propagating SSL_CERT_FILE everywhere. On other platforms we should re-use the host's CA store whenever possible because not using the same set means that nix-installed programs will fail differently and it causes confusion to the users.

One issue right now is that security.pki.certificateFiles is blank by default and should probably be pre-polutated with a sensible default instead. (actually it already does the right thing). Then patch openssl and friend and remove all the SSL_CERT_FILE hacks.

@layus
Copy link
Member Author

layus commented Feb 22, 2016

Closing this issue as this is probably not the best way to go, and too keep the discussion in #8247.

@layus layus closed this as completed Feb 22, 2016
@layus layus changed the title SSL_CERT_FILE should be in systemd.globalEnvironment SSL_CERT_FILE should be in systemd.globalEnvironment (See #8247 instead) Mar 2, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
0.kind: enhancement Add something new 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS
Projects
None yet
Development

No branches or pull requests

4 participants