python - Raven Twisted 集成的 SSL 选项

标签 python ssl twisted raven

我的 Sentry 实例位于需要我使用客户端证书进行身份验证的代理后面。如何使我的 Twisted 应用程序使用 Raven 成功通过此代理?我在 raven.transport.Transport 中看不到任何可以让我指定客户端证书、 key 和信任链的东西。我有哪些选择?

最佳答案

好的,我找到了。不是最干净的解决方案,但它有效。

事实证明,您可以使用自定义方案注册自己的传输类。要使其与客户端 secret (证书、 key 、链)一起使用,您必须将它们指定为 Sentry DSN url 的查询参数,例如:

https://url/project?client_cert=f1&client_key=f2

等等。然后将这些参数传递给 kwargs 中的传输构造函数。对于 Twisted v. 16.0.0,这可能看起来像这样:

class InstancePolicy(BrowserLikePolicyForHTTPS):

    def __init__(self, trustRoot=None,
            client_cert=None, client_key=None, client_trust_chain=None,
            server_ca_cert=None):
        if None in (client_cert, client_key):
            raise ValueError('When using client side SSL both certificate and key are required')
        super(InstancePolicy, self).__init__(trustRoot)
        self.client_cert_file = client_cert
        self.client_key_file = client_key
        self.client_trust_chain_file = client_trust_chain
        self.server_ca_cert_file = server_ca_cert

    @property
    def trust_source(self):
        src = self._trustRoot
        if self.server_ca_cert_file is not None:
            src = ssl.Certificate.loadPEM(FilePath(self.server_ca_cert_file).getContent())
        return src

    def creatorForNetloc(self, hostname, port):
        if self.client_cert_file is not None:
            key_pair = ssl.KeyPair.load(FilePath(self.client_key_file).getContent(), crypto.FILETYPE_PEM)
            client_cert = ssl.PrivateCertificate.load(FilePath(self.client_cert_file).getContent(),
                key_pair, crypto.FILETYPE_PEM)
        else:
            client_cert = None
        extra = {}
        if self.client_trust_chain_file is not None:
            chain = [ssl.Certificate.loadPEM(str(x)) for x in pem.parse_file(self.client_trust_chain_file)]
            extra['extraCertificateOptions'] = dict(extraCertChain=[x.original for x in chain])
        return ssl.optionsForClientTLS(
            hostname.decode('ascii'),
            trustRoot=self.trust_source,
            clientCertificate=client_cert,
            **extra
        )

然后你可以使用下面的函数来构建你喜欢的代理实例:

def make_agent(reactor, policy=None):
    kw = {}
    if policy is not None:
        kw['contextFactory'] = policy
    return Agent(reactor, pool=HTTPConnectionPool(reactor), **kw)

使用这些组件,您现在可以定义自己的传输子类:

class TwistedHTTPSClientSSLTransport(TwistedHTTPTransport):
    scheme = ['twisted_clientssl+https']

    def __init__(self, parsed_url, *args, **kwargs):
        client_cert = kwargs.pop('client_cert', None)
        client_key = kwargs.pop('client_key', None)
        client_trust_chain = kwargs.pop('client_trust_chain', None)
        server_ca_cert = kwargs.pop('server_ca_cert', None)
        super(TwistedHTTPSClientSSLTransport, self).__init__(parsed_url, *args, **kwargs)
        policy = InstancePolicy(client_cert=client_cert,
            client_key=client_key, client_trust_chain=client_trust_chain,
            server_ca_cert=server_ca_cert)
        from twisted.internet import reactor
        self._agent = make_agent(reactor, policy)

现在在创建 Raven Client 实例之前,您可以为您的自定义方案注册您的传输类:

for sc in TwistedHTTPSClientSSLTransport.scheme:
    Client.register_scheme(sc, TwistedHTTPSClientSSLTransport)

这行得通。

关于python - Raven Twisted 集成的 SSL 选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36303761/

相关文章:

java - SSLHandshakeException - %% 无效 : [Session-1, SSL_RSA_WITH_3DES_EDE_CBC_SHA]

java - 禁止 Java (JSSE) 中的 SSL 重新握手?

python - Twisted Python 和 TLS - 客户端代码需要什么来握手? (我以为只是公钥!)

python - 扭曲: `defer.execute` 和 `threads.deferToThread` 之间的区别

php - 如何使用 Git 在开发和生产环境中分发 Thrift 生成的代码?

python - 解析证书的 keyid - Python

python - 在 python 中生成分形

java - 将证书与 https url 相关联

mysql - 使用 twisted.enterprise.adbapi 从简单的 SELECT 获取数据

python - Django 似乎在缓存 datetime.now()