2014-10-02 91 views
4

我正在嘗試創建一個t.w.c.BrowserLikePolicyForHTTPS作爲ContextFactory用於t.w.c.Agent。我爲所有希望Agent與之通信的服務器使用內部CA,所以我希望能夠告訴加載CA證書(PEM格式)並將其用作BrowserLikePolicyForHTTPS的trustRoot參數。我已閱讀文檔並查看源代碼,但我不知道我應該提供什麼作爲參數。我試圖提供PyOPenSSL X509對象,但我得到一個錯誤:扭曲的Python如何使用自定義的trustRoot創建twisted.web.client.BrowserLikePolicyForHTTPS?

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

我可以在代碼中看到的那個t.i._sslverify莫名其妙OpenSSLCertificateAuthorities得到適應IOpenSSLTrustRoot,但它是不是真的我清楚這是如何發生。

我知道股票代理沒有做任何證書檢查。我正在使用treq的一個分支,並嘗試添加一個選項來提供自定義代理。

任何有關trustRoot參數的幫助將不勝感激。如果我正在努力解決這個問題,請讓我知道。

回答

6

在這裏你的問題凸顯了文檔中的一個可怕的監督;無論是在API文檔還是在敘述文檔中。如果讓 - 保羅不能找出這樣做的「正確方法」,那麼對於普通用戶顯然是沒有希望的。 I have filed a bug to correct this oversight

與此同時,請避免讓 - 保羅的解決方案。雖然它是功能性的,但它涉及的技術幾乎肯定會在未來的發行版中突然崩潰(正如他明確指出的那樣)。幸運的是,有支持這種方式的方法。如果您有一個備用信任根,則Certificate可用作參數trustRoot的值。您可以使用它,像這樣(我已經測試與扭曲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) 
+1

如果您有多個可選的可接受信任根,則執行此操作會稍微複雜一些,並且我還提交了一張Twisted故障單以解決此問題:https://twistedmatrix.com/trac/ticket/7671。 – Glyph 2014-10-06 23:15:11

+0

請問#7671是否也解決了將您自己的信任根與系統信任根結合在一起的問題?有些情況下我想使用OS CA捆綁軟件和我自己的CA證書。我不確定在票證中提出的解決方案是否可以解決此問題,除非您可以將路徑指定到存儲操作系統軟件包的任何位置。 – Carl 2014-10-07 17:33:49

+0

我想應該。請評論進一步討論,但:)。 (另外,如果你不介意將這個答案改爲「接受」 - 我寧願讓人們接受這個建議,而不是讓 - 保羅在這種情況下。) – Glyph 2014-10-08 05:00:26

0

IOpenSSLTrustRoot是一個無意義的API。

它本身不是一個公共接口 - 所以你不能實現你自己的接口。如果是這樣,它沒有公共方法,所以目前還不清楚如何定製它的行爲。

考慮到這個接口對安全敏感的特性,我敢打賭,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"))) 
+0

在您的最後一個例子,應該是明確使用了MyCATrustRoot類,或者是有某種神奇的適應會上? – Carl 2014-10-02 20:05:06

+0

糟糕,在代碼中犯了一個錯誤。定影。 – 2014-10-02 21:45:10

+0

此外,還有一個編輯要明確Twisted中私有接口的性質。 – 2014-10-02 22:03:54