Implement SSLContext.get_ca_certs()
I suspect this will be possible in both macOS and Windows trust store APIs.
Can you explain (like I'm 5) why this would be more complicated than calling the underlying SSLContext.get_ca_certs method? I'm on Windows, and when I do:
import ssl
ctx = ssl.create_default_context()
ctx.get_ca_certs()
I get a full list of certificates in my Windows trust store. If I do:
import ssl
import truststore
truststore.inject_into_ssl()
ctx = ssl.create_default_context()
ctx._ctx.get_ca_certs()
I get the same list. Why not pass through the get_ca_certs call the same way as, say, load_default_certs?
@FaustinCarter In Windows, that works because the default SSL context loads the CA certs from the Windows trust store: https://github.com/python/cpython/blob/9cfb4e0d1ebf2900c19ee07697818c621f46cc3d/Lib/ssl.py#L532-L534
On my Mac, import ssl; ctx = ssl.create_default_context(); ctx.get_ca_certs() returns the CA certs from the OpenSSL that Python was compiled with, not the CA certs from the OS trust store.
Wanted to also note that get_ca_certs() doesn't work the same across all platforms. It'd be nice to have it work in a similar way for all platforms. For example, OpenSSL doesn't take into account certificate directories in get_ca_certs() until /after/ a certificate has been loaded by a lookup (instead of listing all possible certificates that are candidates to be roots).
For example, OpenSSL doesn't take into account certificate directories in get_ca_certs() until /after/ a certificate has been loaded by a lookup (instead of listing all possible certificates that are candidates to be roots).
@sethmlarson I think this is true across platforms (get_ca_certs returns the certs that have been loaded into the OpenSSL context -- either explicitly loaded OR implicitly loaded from capath during a lookup). It's just that on Windows load_default_certs does some extra work to explicitly load the CA certs from the OS trust store into OpenSSL.
Thanks to you both. Very helpful discussion. It's a nice surprise to discover an instance where Windows "just works"! Usually it's the dreaded edge case that's too hard to solve!
So if I understand this correctly:
-
ssl.SSLContext.load_default_certsworks correctly on Windows and Linux -
ssl.SSLContext.get_ca_certswill return any certs that have been loaded into theSSLContextobject
So maybe a reasonable path forward is:
- For Mac, write a function that
truststore._api.SSLContext.load_default_certscan use to pull from theSecTrusttrust object and load into the underlyingssl.SSLContextobject. For Windows and Linux, drop through to the originalssl.SSLContext.load_default_certs. - Enable
truststore._api.SSLContext.get_ca_certsto call the underlyingssl.SSLContext.get_ca_certsmethod.
I guess one obvious open implementation question for 1 is: which store to pull from. By default, Windows pulls from ROOT and CA. It looks like there are a couple of options for getting certificates out of a SecTrust object:
-
SecTrustSettingsCopyCertificatespulls certs from a specific domain (user/local/system) -
SecTrustCopyAnchorCertificatespull "root" certificates -
SecTrustCopyCustomAnchorCertificatespulls "custom" certificates, whatever those are