Usando certificados de cliente con urllib2

Necesito crear un canal seguro entre mi servidor y un servicio web remoto. Usaré HTTPS con un certificado de cliente. También necesitaré validar el certificado presentado por el servicio remoto.

  1. ¿Cómo puedo usar mi propio certificado de cliente con urllib2?

  2. ¿Qué debo hacer en mi código para garantizar que el certificado remoto sea correcto?

Aquí hay un error en el bugtracker oficial de Python que parece relevante y tiene un parche propuesto.

Debido a que la respuesta de alex es un enlace, y el código en esa página está mal formateado, solo voy a poner esto aquí para la posteridad:

import urllib2, httplib class HTTPSClientAuthHandler(urllib2.HTTPSHandler): def __init__(self, key, cert): urllib2.HTTPSHandler.__init__(self) self.key = key self.cert = cert def https_open(self, req): # Rather than pass in a reference to a connection class, we pass in # a reference to a function which, for all intents and purposes, # will behave as a constructor return self.do_open(self.getConnection, req) def getConnection(self, host, timeout=300): return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert) opener = urllib2.build_opener(HTTPSClientAuthHandler('/path/to/file.pem', '/path/to/file.pem.') ) response = opener.open("https://example.org") print response.read() 

Según la respuesta de Antoine Pitrou al problema vinculado en la respuesta de Hank Gay, esto se puede simplificar un poco (a partir de 2011) mediante el uso de la biblioteca ssl incluida:

 import ssl import urllib.request context = ssl.create_default_context() context.load_cert_chain('/path/to/file.pem', '/path/to/file.key') opener = urllib.request.build_opener(urllib.request.HTTPSHandler(context=context)) response = opener.open('https://example.org') print(response.read()) 

(Código de Python 3, pero la biblioteca ssl también está disponible en Python 2).

La función load_cert_chain también acepta un parámetro de contraseña opcional, lo que permite el cifrado de la clave privada.