How to send a HTTP request with client certificate + private key + password/secret in Python 3
When we need to create a HTTP client that communicates with a HTTP server through certificate-based authentication, we will typically have to download a certificate, in .pem
format, from the server.
After we had downloaded the .pem
file, the HTTP client will use the private key and certificate to authenticate itself with the HTTP server. Sometimes, the HTTP client will need to decrypt the private key with a password/secret first.
So with a .pem
file and a password/secret, how can you create a HTTP client in Python 3 to send a HTTP request to the HTTP server?
In case you need it, this post shows how to send a HTTP request with client certificate + private key + password/secret in Python 3.
Creating the sample Python 3 code that send a HTTP Post request to a HTTP endpoint with client certificate + private key + password/secret
Let's assume that there is an HTTP endpoint at https://example.com/a/http/url that authenticates clients with client certificates and receives HTTP Post requests.
In addition to that, the .pem
file is named as a_certificate_file.pem
and the certificate secret is your_certificate_secret.
Given these points, you can create a Python 3 file in the same folder as the .pem
file with the following content to send a HTTP Post request to that HTTP endpoint:
import http.client import json import ssl # Defining certificate related stuff and host of endpoint certificate_file = 'a_certificate_file.pem' certificate_secret= 'your_certificate_secret' host = 'example.com' # Defining parts of the HTTP request request_url='/a/http/url' request_headers = { 'Content-Type': 'application/json' } request_body_dict={ 'Temperature': 38, 'Humidity': 80 } # Define the client certificate settings for https connection context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) context.load_cert_chain(certfile=certificate_file, password=certificate_secret) # Create a connection to submit HTTP requests connection = http.client.HTTPSConnection(host, port=443, context=context) # Use connection to submit a HTTP POST request connection.request(method="POST", url=request_url, headers=request_headers, body=json.dumps(request_body_dict)) # Print the HTTP response from the IOT service endpoint response = connection.getresponse() print(response.status, response.reason) data = response.read() print(data)
Understanding the sample Python 3 code that send a HTTP Post request to a HTTP endpoint with client certificate + private key + password/secret
First of all, we indicate that we wish to use some functionalities from http.client, json and ssl modules:
import http.client import json import ssl
After that, we define some variables for certificate related stuff, host of endpoint and parts of the HTTP request:
# Defining certificate related stuff and host of endpoint certificate_file = 'a_certificate_file.pem' certificate_secret= 'your_certificate_secret' host = 'example.com' # Defining parts of the HTTP request request_url='/a/http/url' request_headers = { 'Content-Type': 'application/json' } request_body_dict={ 'Temperature': 38, 'Humidity': 80 }
Once we had defined the variables, we create a ssl.SSLContext
object and load the certificate chain with what we have from the server:
# Define the client certificate settings for https connection context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) context.load_cert_chain(certfile=certificate_file, password=certificate_secret)
Given that we have the SSL context, we then create a http.client.HTTPSConnection
object for sending HTTP requests to the server:
# Create a connection to submit HTTP requests connection = http.client.HTTPSConnection(host, port=443, context=context)
At this point of time, we can then use the http.client.HTTPSConnection
object to send a HTTP request to the server endpoint:
# Use connection to submit a HTTP POST request connection.request(method="POST", url=request_url, headers=request_headers, body=json.dumps(request_body_dict))
Finally, we simply print some parts of the HTTP response that the server returns back to our client:
# Print the HTTP response from the IOT service endpoint response = connection.getresponse() print(response.status, response.reason) data = response.read() print(data)