Raven Twisted集成的SSL选项



My Sentry实例位于代理后面,该代理要求我使用客户端证书进行身份验证。如何制作使用Raven成功传递此代理的Twisted应用程序?我在raven.transport.transport中看不到任何允许我指定客户端证书、密钥和信任链的内容。我有什么选择?

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

事实证明,您可以使用自定义方案注册自己的Transport类。要使用客户端机密(证书、密钥、链),您必须将它们指定为Sentry DSN url的查询参数,如:

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

然后将这些参数传递给kwargs中的Transport构造函数。对于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
        )

然后您可以使用以下功能来构建您喜欢的Agent实例:

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客户端实例之前,您可以为您的自定义方案注册Transport类:

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

这是有效的。

相关内容

  • 没有找到相关文章

最新更新