【问题标题】:Twisted Python How To Create a twisted.web.client.BrowserLikePolicyForHTTPS with a custom trustRoot?Twisted Python 如何使用自定义 trustRoot 创建一个 twisted.web.client.BrowserLikePolicyForHTTPS?
【发布时间】:2014-11-27 18:34:32
【问题描述】:

我正在尝试创建一个t.w.c.BrowserLikePolicyForHTTPS 以用作t.w.c.AgentContextFactory。我正在为我希望代理与之通信的所有服务器使用内部 CA,因此我希望能够告诉加载 CA 证书(PEM 格式)并将其用作BrowserLikePolicyForHTTPS 的 trustRoot 参数。我已经阅读了文档并查看了源代码,但我不知道我应该提供什么作为参数。我尝试提供 PyOPenSSL x509 对象,但出现错误:

exceptions.TypeError: ('Could not adapt', <OpenSSL.crypto.X509 object at 0x280b290>, <InterfaceClass twisted.internet._sslverify.IOpenSSLTrustRoot>)

我可以在t.i._sslverify 的代码中看到OpenSSLCertificateAuthorities 以某种方式适应了IOpenSSLTrustRoot,但我并不清楚这是如何发生的。

我知道股票代理不做任何证书检查。我正在使用 Treq 的一个分支,并正在尝试添加一个选项来提供自定义代理。

如有任何关于 trustRoot 参数的帮助,我们将不胜感激。如果我要解决这个问题,也请告诉我。

【问题讨论】:

    标签: python http ssl twisted


    【解决方案1】:

    您的问题突出了文档中的严重疏忽;在 API 文档和叙述文档中。如果 Jean-Paul 无法找出“正确的方法”来做到这一点,那么普通用户显然没有希望。 I have filed a bug to correct this oversight.

    同时,请避免使用 Jean-Paul 的解决方案。虽然它是功能性的,但它涉及的技术几乎肯定会在未来的版本中毫无预警地中断(正如他明确指出的那样)。幸运的是,有支持的方法来做到这一点。如果您有一个备用信任根,Certificate 可用作trustRoot 参数的值。你可以这样使用它(我已经用 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)
    

    【讨论】:

    • 如果您有多个备用的可接受的信任根,这样做会稍微复杂一些,我也提交了 Twisted 票证来解决这个问题:twistedmatrix.com/trac/ticket/7671
    • #7671 是否还会解决将您自己的信任根与系统信任根相结合的问题?在某些情况下,我想使用 OS CA 捆绑包以及我自己的 CA 证书。我不确定票证中建议的解决方案是否可以解决此问题,除非您可以提供存储 OS 捆绑包的路径。
    • 我想应该。不过,请对票发表评论以进行进一步讨论:)。 (此外,如果您不介意将此答案更改为“已接受” - 在这种情况下,我宁愿人们接受这个建议,而不是 Jean-Paul 的建议。)
    • 相关问题的一些讨论在这里继续:twistedmatrix.com/pipermail/twisted-web/2014-October/…
    【解决方案2】:

    IOpenSSLTrustRoot 有点废话。

    它本身不是一个公共接口——所以你不能实现你自己的。如果是,它没有公共方法,所以不清楚如何自定义它的行为。

    考虑到这个接口的安全敏感性,我敢打赌 Twisted 会竭尽全力确保你编写的任何代码都能继续工作——即使接口是私有的并且接口上只有私有方法。

    如果你编写的一些代码依赖于这个接口总是像现在一样工作,那么你至少可以发布到 Twisted 邮件列表并说出来,那里的人可能会尽量不破坏你的应用程序。

    也就是说,正如我在上面指出的,这一切都是私密的。 Twisted 的声明政策是这里不保证向后兼容。因此,风险自负。

    无论如何,你都可以这样写:

    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)
    

    然后使用MyCATrustRoot 实例作为trustRoot 的参数BrowserLikePolicyForHTTPS。确保您至少使用 Twisted 14.0.2,因为早期版本实际上忽略了您传递给 BrowserLikePolicyForHTTPStrustRoot

    例如,如果您信任的“CA”证书位于/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")))
    

    【讨论】:

    • 在您的最后一个示例中,是否应该明确使用 MyCATrustRoot 类,或者是否有某种适应魔法?
    • 另外,再进行一次编辑以明确 Twisted 中私有接口的性质。
    • 我必须使用密钥参数root_certificate_path= 提供路径,而Agent 的第一个参数是reactor,但除此之外,它似乎还有效。我接受这个作为答案。
    • 谢谢。我将更改代码以修复这两个错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 2010-09-18
    • 2021-11-30
    • 2014-11-11
    • 2014-09-07
    • 1970-01-01
    • 2017-05-18
    相关资源
    最近更新 更多