Twisted Python ¿Cómo crear un twisted.web.client.BrowserLikePolicyForHTTPS con un trustRoot personalizado?

Estoy tratando de crear un twcBrowserLikePolicyForHTTPS para usarlo como ContextFactory para un twcAgent . Estoy usando una CA interna para todos los servidores con los que quiero que se comunique el Agente, por lo que me gustaría poder indicarle que cargue el certificado CA (formato PEM) y lo use como el argumento BrowserLikePolicyForHTTPS para BrowserLikePolicyForHTTPS . He leído los documentos y he mirado la fuente, pero no tengo idea de lo que se supone que debo proporcionar como argumentos. Intenté proporcionar un objeto PyOPenSSL x509, pero obtengo un error:

 exceptions.TypeError: ('Could not adapt', , ) 

Puedo ver en el código en ti_sslverify que OpenSSLCertificateAuthorities alguna manera se adapta a IOpenSSLTrustRoot , pero no está realmente claro cómo sucede esto.

Sé que el agente de valores no realiza ninguna verificación de certificados. Estoy trabajando con una bifurcación de treq y estoy experimentando con agregar una opción para proporcionar un Agente personalizado.

Cualquier ayuda con el argumento trustRoot sería apreciada. Si estoy haciendo esto de la manera más difícil, hágamelo saber también.

Su pregunta aquí destaca un terrible descuido en la documentación; tanto en la documentación de la API, como en la documentación narrativa de. Si Jean-Paul no puede descubrir la “manera correcta” de hacer esto, entonces claramente no hay esperanza para un usuario regular. He archivado un error para corregir esta supervisión .

Mientras tanto, por favor, evite la solución de Jean-Paul. Si bien es funcional, involucra técnicas que casi seguramente se romperán sin previo aviso en futuras versiones (como lo señala claramente). Por suerte hay formas compatibles de hacer esto. Si tiene una única raíz de confianza alternativa, el Certificate se puede usar como un valor para el parámetro trustRoot . Puedes usarlo así (he probado el siguiente ejemplo con Twisted 14.0.2):

 from __future__ import print_function from twisted.web.client import Agent, BrowserLikePolicyForHTTPS from twisted.internet.task import react from twisted.internet.ssl import Certificate from twisted.internet.protocol import Protocol from twisted.python.filepath import FilePath from twisted.internet.defer import inlineCallbacks, Deferred @inlineCallbacks def main(reactor): customPolicy = BrowserLikePolicyForHTTPS( Certificate.loadPEM(FilePath("your-trust-root.pem").getContent()) ) agent = Agent(reactor, customPolicy) response = yield agent.request( "GET", "https://your-web-site.example.com/" ) done = Deferred() class CaptureString(Protocol): def dataReceived(self, data): print("Received:", data) def connectionLost(self, reason): done.callback(None) response.deliverBody(CaptureString()) yield done react(main) 

IOpenSSLTrustRoot es un poco de una API sin sentido.

No es una interfaz pública en sí misma, por lo que no puede implementar la suya propia. Si lo fuera, no tiene métodos públicos, por lo que no está claro cómo puede personalizar su comportamiento de todos modos.

Teniendo en cuenta la naturaleza sensible a la seguridad de esta interfaz, apuesto a que Twisted hará todo lo posible para asegurarse de que cualquier código que escriba continúe funcionando, aunque la interfaz es privada y solo hay métodos privados en la interfaz.

Si escribes un código que depende de que esta interfaz funcione siempre como funciona ahora, es probable que puedas al menos publicar en la lista de correo Twisted y decirlo, y la gente probablemente intentará no interrumpir tu aplicación.

Dicho esto, como señalé anteriormente, cada parte de esto es privada. La política declarada de Twisted es que aquí no hay garantías de compatibilidad con versiones anteriores. Así que proceda bajo su propio riesgo.

En cualquier caso, puedes escribir algo como esto:

 from zope.interface import implementer from characteristic import attributes from twisted.internet._sslverify import IOpenSSLTrustRoot @implementer(IOpenSSLTrustRoot) @attributes(["root_certificate_path"]) class MyCATrustRoot(object): def _addCACertsToContext(self, context): context.load_verify_locations(self.root_certificate_path) 

Luego use una instancia de MyCATrustRoot como el argumento BrowserLikePolicyForHTTPS para BrowserLikePolicyForHTTPS . Asegúrese de usar al menos Twisted 14.0.2 porque las versiones anteriores en realidad ignoraron el trustRoot que pasó a BrowserLikePolicyForHTTPS .

Por ejemplo, si su certificado “CA” de confianza está en /foo/ca.pem :

 from twisted.web.client import BrowserLikePolicyForHTTPS, Agent from twisted.internet import reactor agent = Agent(reactor, BrowserLikePolicyForHTTPS( MyCATrustRoot(root_certificate_path="/foo/ca.pem")))