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)