【问题标题】:SSL options for Raven Twisted integrationRaven Twisted 集成的 SSL 选项
【发布时间】:2016-03-30 08:41:23
【问题描述】:

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

【问题讨论】:

    标签: python ssl twisted raven


    【解决方案1】:

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

    事实证明,您可以使用自定义方案注册自己的 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
            )
    

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

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

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

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

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

    这行得通。

    【讨论】:

      猜你喜欢
      • 2013-10-04
      • 2019-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-24
      • 2020-12-18
      • 1970-01-01
      • 2018-03-18
      相关资源
      最近更新 更多