I am using the python request module to makes a POST call:
import requests
response = requests.post( foo_url,
json={"foo":"bar"},
headers=foo_headers,
verify='/path/to/cert' )
This works fine. Though is it possible to use the value of the certificate directly instead of the path to the file that contains the certificate?
TLDR: The answer is definitively "no, the cert must be in a file on disk." And the reason why is because OpenSSL is awful.
requests
is based on urllib3
, which is based on ssl
. requests
takes your top-level cert
parameter and splits it up into parameters named cert_file
and key_file
, which get passed to urllib3
. urllib3
passes them on, untouched, to ssl
. And ssl
expects them to be filenames.
The specific culprit at the bottom of the Python stack is SSLContext.load_cert_chain
from the ssl
module. It depends on _SSLContext
, which is written in C. The C code for _SSLContext.load_cert_chain
is here. And you can see, it really truly 100% needs a filesystem path! Ugh!
The culprit at the bottom of the C stack is OpenSSL's SSL_CTX_use_certificate_chain_file
, which has this signature:
int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
There are ways of building a cert chain in OpenSSL that don't involve "just open a file and read it in," but they're vastly more complicated, which I guess is why Python ssl
doesn't use them... and that explains why urllib3
doesn't use them, and that explains why requests
doesn't use them.