-
-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
Consider using system trust stores by default in 3.0.0. #2966
Comments
I think the system trust stores (or not) essentially boils down to whether you want requests to act the same across platforms, or whether you want it to act in line with the platform it is running on. I do not think that either of these options are wrong (or right), just different trade offs. I think that it's not as simple on Windows as it is on Linux or OSX (although @tiran might have a better idea). I think that Windows doesn't ship with all of the certificates available and you have to do something (use WinHTTP?) to get it to download any additional certificates on demand. I think that means that a brand new Windows install, if you attempt to dump the certificate store will be missing a great many certificates. On Linux, you still have the problem that there isn't one single set location for the certificate files, the best you can do is try to heuristically guess at where it might be. This gets better on Python 2.7.9+ and Python 3.4+ since you can use I assume the fall back to certifi ensures that things will still work correctly on platforms that either don't ship certificates at all, or don't ship them by default and they aren't installed? If so, that's another possible niggle here that you'd want to think about. Some platforms, like say FreeBSD, don't ship them by default at all. So it's possible that people will have a requests using thing running just fine without the FreeBSD certificates installed, and they then install them (explicitly or implicitly) and suddenly they trust something different and the behavior of the program changes. Anyways, the desire seems reasonable to me and, if all of the little niggles get worked out, it really just comes down to a question of if requests wants to fall on the side of "fitting in" with a particular platform, or if it wants to prefer cross platform uniformity. |
I wouldn't say that either option is completely wrong, but I do think that using the platform trust store is significantly right-er, due to the availability of tooling to adjust trust roots on the platform and the relative unavailability of any such tooling for requests or certifi. If you go into Keychain Access to add an anchor (or the Windows equivalent) nothing about requests makes it seem like it would be special, that it would be using a different set of trust roots than you had already configured for everything else. |
It depends if your audience are people who are familiar with a particular platform or not. I have no idea how to manage the trust store on Windows but I know how to manage the trust store for requests because requests currently chooses being internally consistent cross platform over being externally consistent with any particular platform. IOW this change makes it easier for people who are familiar with the system the software is running on at the cost of people who are not. Sent from my iPhone
|
In the abstract, I disagree. Of course, we may have distribution or build toolchain issues which make people have to care about this fact, but if it works properly ( |
It forces them to learn the differences of every platform they are running on. Sent from my iPhone
|
So I am in favour of using the system store in general because in most cases [outside of dev] if you're relying on requests or a similar library you're going to expect it to work similar to the rest of the system/tooling. Asking someone to learn the tooling for the system they are deploying on is not unreasonable. If an application uses requests and needs to trust a specific cert (end-user story here), it is usual that it'll handle the installation for that platform at install time (aka OS X or Windows). From a developer perspective, it becomes a little more difficult but still not insurmountable as long as we approach this in a way that the developer has clear methods to continue with the same behaviour as today. As discussed in IRC, perhaps the easiest method to ensure sanity is to really finish up and polish certitude(? was this the tool discussed?) so we can encapsulate the platform/system-specifics clearly and try and ensure requests logic is the same on all of the platforms. |
How so? By default, it ought to get the trust roots you expect on every platform. It's not like I need to learn new and exciting things when I launch Safari vs. IE just to type |
You are right about this. I have verified it on my nearly-pristine Windows VM; in a Python prompt, I do: >>> import wincertstore
>>> print(len(list(wincertstore.CertSystemStore("ROOT")))) and get "21". Visit some HTTPS websites, up-arrow/enter in the python interpreter, and now I get "23". |
There's some technical documentation here: |
And some more explanation here: |
Frustratingly, I can't find an API that just tells it to grab the certificate store; it seems that verifying a certificate chain that you don't have the root to is the only way that it adds certificates, and it adds them one at a time as necessary. It baffles me that Microsoft seems to consider storage for certificates a scarce resource. |
After hours of scouring MSDN, I give up. Hopefully someone else can answer this question: https://stackoverflow.com/questions/34732586/is-there-an-api-to-pre-retrieve-the-list-of-trusted-root-certificates-on-windows |
In my experience with pip, which attempts to discover the system store and if it can't find it falls back to a bundled copy, I have had to learn how the system store works on platforms that I have no intention on ever running. This is for a fairly simple method of detection (look for file systems) but it absolutely ends up that way. The simple fact is, in my experience most people have absolutely no idea how their system manages a trust store (and if it manages a trust store or not). Sent from my iPhone
|
Look for files on the system* |
FWIW, If I could prevent downstream redistributors from forcing pip to use the system store, I would revert the change to look in system locations immediately and only ever use a bundled copy. The UX of that tends to be so much nicer, the only reason we started to trust the system trust stores is because redistributors do patch pip to use the system trust store, so you end up in a situation where people get different trust stores based on where their copy of pip came from (which is likely also a concern for requests). As an additional datapoint, if I remember correctly, the browsers which are not shipped with the OS tend to not use the system trust store either. According to Chrome's Root Certificate Policy they will use the system trust store on OSX and on Windows but they won't use it on Linux. I believe that even where Chrome does use the system store, they still layer their own trust ontop of that to allow them to blacklist certificates if need be. I assume this capability is in place because they do not wholly trust the OS trust stores to remove compromised certificates. If I recall correctly, Firefox does not use the system trust store at all on any OS. Another question is what even is the "root trust store" on a Linux. The closest that you can get is wherever the system provided OpenSSL (assuming they even provide OpenSSL) is configured to point to. However AFAIK there is no way to determine if you're using a system provided OpenSSL or a copy that someone installed (perhaps via Anaconda?), the additional copy may have stale certificates or no certificates available. If it's stale certificates, then you've successfully lowered the security of requests user's by attempting to follow the system trust store. If it's an empty trust store, how do you determine the difference between "empty because I trust nothing" and "empty because my copy of OpenSSL isn't shipping them" or do I have to manage the certificates I trust using my OS, unless I want to trust nothing then I have to manage the certificates I trust using requests? I've also found that talks about trying to use the platform certificate trust store on Linux (see here). I've not personally verified the information in this article, however it makes me feel very wary about trying to make using the system trust store anything but an exercise in frustration. |
I think our current approach is the correct one, considering who Requests was built for. That being said, it wouldn't hurt to add more documentation/functionality around using system certs for "advanced" users. |
I think talking about configurability is maybe a red herring. It's useful – necessary even – in certain circumstances, but users who know they need that can usually figure it out. The more significant issue is that trust root database updates, especially for end-user client software, are both infrequent and extremely important to do in a timely manner. |
@glyph I think you may have hit the nail on the head there. That is a significant reason (and addresses the other issues outlined) to use a more centralized location for the cert store. |
The flip side is that you have trust stores like Debian which trusted CACert for a long time, and still trusts SPI even though neither of those have gone through any sort of real audit that you'd expect for a trusted CA. |
As I understand it, Microsoft trusts their own CA, too, and Apple trusts theirs. SPI is just Debian's version of that, isn't it? |
SPI isn't run by Debian, it's a third party organization similar to that of the Software Freedom Conservancy that Debian happens to be a member of. It'd be more like Microsoft and Apple trusting the CA of their datacenter just because they happened to use them as their data center. In addition, I'm pretty sure that Apple and Microsoft have both passed a WebTrust audit for their root CAs. |
To be fair to Debian, I think the current plan is to stop using SPI certificates for their infrastructure and switch to more generally trusted certificates and then stop including SPI and switch to using just the Mozilla bundle without any additions. That being said, is it even true that they are shipping updates to them? Looking at packages.debian.org for the ca-certificates packages it shows that the versions there are:
I haven't looked at the actual contents of these packages, but the version numbers lead me to believe that they are not infact keeping the ca-certificates package up to date. In addition to that, looking at the open bugs for ca-certificates there are bugs like #721976 which means that the ca-certificates store includes roots which are not valid for validating servers and are only valid for other topics (like email) which means you can't actually use the current ca-certificate package without massaging it to remove those certificates yourself. Another issue #808600 has Comodo requesting a removal of a particular root that they no longer consider to be inscope for the CAB That's just from spending a little bit of time looking at one, fairly popular, distribution. I imagine the long tail of the issues with the system provided bundle gets worse the further away from the popular distributions you get. It's not clear to me that it's a reasonable assumption that the certificates included in any random OS are going to be properly maintained. The other elephant in the room is we're just assuming that because an update is available to their ca-certificates package that someone is going to have pulled it in. As far as I know, most (if not all?) of the Linux systems do not automatically update by default and require configuration to start to do so. There is likely to be a bigger chance of this with Docker in the picture. On the flip side, I think people generally try to update to the latest versions of their dependencies when working on a project. |
Debian's cert bundle is almost certainly like ubuntu's, which does not update to the Mozilla bundle that removed 1024-bit roots in order to avoid the pain like that which hit certifi. All of the out-of-date cert bundles are OpenSSL pre 1.0.2, which means they cannot correctly build the cert chain to a cross-signed root without having the 1024-bit cross-signing root still present. I suspect that's the real concern there. |
Maybe they should stop shipping an OpenSSL that can't correctly validate certificate chains. |
I reached out to Kurt Roebx about backporting the fixes for that, he said On Wed, Jan 13, 2016 at 7:27 AM, Donald Stufft [email protected]
"I disapprove of what you say, but I will defend to the death your right to |
So, what if we made the behaviour of looking at the system CA bundle an extra, e.g., |
I believe this is behaviour specific to OpenSSL. We really don't need apps re-implementing this logic, it's only going to further confuse things. |
... and that's how we ended up with |
Since it hasn't been brought up here yet, @sethmlarson and @davisagli have started to write a library to verify certificates using OS trust stores: https://github.com/sethmlarson/truststore |
Sam Morris schreef op do 21-04-2022 om 08:30 [+0000]:
> However, it is recommended that applications look into the
> environment variable $SSL_CERT_FILE / $SSL_CERT_DIR instead and
> only use /etc/ssl/certs/ca-certificates.crt and /etc/ssl/certs as
> fallbacks. That way, the user can override which certificates to
> trust without having to have root access or play container tricks.
I believe this is behaviour specific to OpenSSL. We really don't need
apps re-implementing this logic, it's only going to further confuse
things.
There is also a proposal to add this GnuTLS, though it needs some more
work: <https://gitlab.com/gnutls/gnutls/-/merge_requests/1541>.
`$SSL_CERT_DIR`/`SSL_CERT_FILE` is also implemented by some non-OpenSSL
applications, e.g. the web APIs of Guile respect `$SSL_CERT_FILE` /
`$SSL_CERT_FILE` IIRC.
The idea is not to have applications re-implement this logic, but to
put it in a standard-ish library like 'requests' (maybe internally
using OpenSSL's functions to discover the certificate store). That
way, it only has to be implemented in a limited number of locations
and applications can just tell the library to discover things
appropriately.
Greetings,
Maxime.
|
FWIW Python's ssl module, Golang's crypto/x509 package, and others support SSL_CERT_FILE / DIR as well. |
Note just letting underlying crypto cert store do its stuff and not even try to pass it cert path is by far sanest approach with both OpenSSL and GnuTLS and allows them to do whatever makes sense on the system (including integrating with p11-kit). |
I agree that having a consistent set of environment variables
(SSL_CERT_FILE / DIR) is nice, but having the libraries simply "do the
right thing" with no extra configuration is better.
…On Thu, Apr 21, 2022, 09:41 Seppo Yli-Olli ***@***.***> wrote:
Note just letting underlying crypto cert store do its stuff and not even
try to pass it cert path is by far sanest approach with both OpenSSL and
GnuTLS and allows them to do whatever makes sense on the system (including
integrating with pqq-kit).
—
Reply to this email directly, view it on GitHub
<#2966 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAOT5FUGWP65WD76IZEHMC3VGFLJ5ANCNFSM4BYJ37NQ>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Pip is experimenting with using the truststore package to solve this exact problem. Unfortunately, per the documentation for that package, using it with requests is not as easy! |
From trust store's documentation. Also how dare a library that existed before |
To be fair, that is the problem with all API's. No one can predict the future hence all API's must be designed with deprecations, changes and removals in mind. |
Yes, in an ideal world that would have happened. The last time requests made a backwards incompatible change, even with deprecation warnings, it was very poorly received and the abuse towards the maintained was unacceptable |
No activity in almost a year - is this dead? |
Truststore already allows you to use system trust stores with Requests, if you need support now: https://truststore.readthedocs.io |
@Lukasa @sethmlarson I think there needs to be a better way to pass in SSLContext objects into I know development is limited on the repo, but it would really help many ssl/certificate issues. |
Please consider using urllib3 directly or switching to HTTPX, which is what I've done everywhere I can. Either option is fine and is preferable to the current state of things. The only thing that potentially may be lost is a reduced number of plugins. |
This is already possible to do using Truststore without a backwards incompatible change and is happening in the places where Requests is used like pip, PDM, etc. We recommend folks use Truststore instead of waiting for Requests to do this for them. |
It's been raised repeatedly, mostly by people using Linux systems, that it's annoying that requests doesn't use the system trust store and instead uses the one that certifi ships. This is an understandable position. I have some personal attachment to the certifi approach, but the other side of that argument definitely has a reasonable position too. For this reason, I'd like us to look into whether we should use the system trust store by default, and make certifi's bundle a fallback option.
I have some caveats here:
Right now it seems like the best route to achieving this would be to use certitude. This currently has support for dynamically generating the cert bundle OpenSSL needs directly from the system keychain on OS X. If we added Linux and Windows support to that library, we may have the opportunity to switch to using certitude.
Given @kennethreitz's bundling policy, we probably cannot unconditionally switch to certitude, because certitude depends on cryptography (at least on OS X). However, certitude could take the current privileged position that certifi takes, or be a higher priority than certifi, as an optional dependency that is used if present on the system.
Thoughts? This is currently a RFC, so please comment if you have opinions. /cc @sigmavirus24 @alex @kennethreitz @dstufft @glyph @reaperhulk @morganfainberg
The text was updated successfully, but these errors were encountered: