Example of including a certficate in a post request with python and http.client

dagrun picture dagrun · Feb 3, 2016 · Viewed 17.8k times · Source

I am trying to POST xml to a site using python. I have to include a certificate but am unsure of how to do this. Is it enough to specify the file path of the certificate locally on my computer?

Can anybody show my an example of how to include the certificate in the request?

import http.client, urllib.parse

xml="""<?xml version="1.0" encoding="UTF-8"?>
<home>
  <bathroom>1</bathroom>
  <kitchen>1</kitchen>
  <street>515</street>
</home>);"""

headers = {"username": "password"}

conn = http.client.HTTPSConnection("someurl.com", cert_file="D:\Users\Username\certificate.p12")
conn.request("POST", "/to/this/place", xml, headers)
response = conn.getresponse()
print(response.status, response.reason)
data = response.read()
print(data)
conn.close()

Answer

cloudpta picture cloudpta · Apr 6, 2018

I used this to avoid having clients do the pkcs12 to PEM conversion. Basically override the context class to allow it to load pkcs12 files. This works with python3

import requests
from OpenSSL import crypto

class Pkcs12Context(requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context):
    def __init__(self, method):
        super().__init__(method)
        p12 = crypto.load_pkcs12(open("/certs/client.p12", 'rb').read(), 'password')
        self.use_certificate(p12.get_certificate())
        self.use_privatekey(p12.get_privatekey())

# Monkey-patch the subclass into OpenSSL.SSL so it is used in place of the stock version
requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context = Pkcs12Context

r = requests.get('https://example.com')

print(r.text)