gpt4 book ai didi

python 扭曲 : Is it possible to reload certificates on the fly?

转载 作者:太空宇宙 更新时间:2023-11-03 13:20:00 28 4
gpt4 key购买 nike

我有一个简单的 Web 服务器,它通过 HTTPS 提供内容:

sslContext = ssl.DefaultOpenSSLContextFactory(
'/home/user/certs/letsencrypt-privkey.pem',
'/home/user/certs/letsencrypt-fullchain.pem',
)
reactor.listenSSL(
port=https_server_port,
factory=website_factory,
contextFactory=sslContext,
interface=https_server_interface
)
do_print(bcolors.YELLOW + 'server.py | running https server on ' + https_server_interface + ':' + str(https_server_port) + bcolors.END)

是否可以即时重新加载证书(例如通过调用类似 https://example.com/server/reload-certificates 的路径并让它执行一些代码)或者我需要做什么才能完成它?

我想避免重启 Python 进程。

最佳答案

可以通过多种方式实现。 Daniel F 的回答非常好,展示了一种用于动态重新配置服务器的良好通用技术。

这里有一些更具体的 Twisted 中的 TLS 支持技术。

首先,您可以从 DefaultOpenSSLContextFactory 实例重新加载 OpenSSL“上下文”对象。当需要重新加载证书时,运行:

sslContext._context = None
sslContext.cacheContext()

cacheContext 调用将创建一个新的 OpenSSL 上下文,并在此过程中重新读取证书文件。这确实有依赖私有(private)接口(interface) (_context) 及其与非真正公共(public)接口(interface) (cacheContext) 交互的缺点。

您还可以实现您自己的 DefaultOpenSSLContextFactory 版本,这样您就不必依赖这些东西。 DefaultOpenSSLContextFactory 并没有做太多事情。这是完全删除缓存行为的复制/粘贴/编辑:

class DefaultOpenSSLContextFactory(ContextFactory):
"""
L{DefaultOpenSSLContextFactory} is a factory for server-side SSL context
objects. These objects define certain parameters related to SSL
handshakes and the subsequent connection.
"""
_context = None

def __init__(self, privateKeyFileName, certificateFileName,
sslmethod=SSL.SSLv23_METHOD, _contextFactory=SSL.Context):
"""
@param privateKeyFileName: Name of a file containing a private key
@param certificateFileName: Name of a file containing a certificate
@param sslmethod: The SSL method to use
"""
self.privateKeyFileName = privateKeyFileName
self.certificateFileName = certificateFileName
self.sslmethod = sslmethod
self._contextFactory = _contextFactory

def getContext(self):
"""
Return an SSL context.
"""
ctx = self._contextFactory(self.sslmethod)
# Disallow SSLv2! It's insecure! SSLv3 has been around since
# 1996. It's time to move on.
ctx.set_options(SSL.OP_NO_SSLv2)
ctx.use_certificate_file(self.certificateFileName)
ctx.use_privatekey_file(self.privateKeyFileName)

当然,这会为每个可能不需要的连接重新加载证书文件。您可以添加自己的缓存逻辑,并使用适合您的证书刷新系统的控制界面。这也有一个缺点,即 DefaultOpenSSLContextFactory 并不是一个非常好的 SSL 上下文工厂。它不遵循 TLS 配置的当前最佳实践。

所以您可能真的想改用 twisted.internet.ssl.CertificateOptions。这有一个类似的 _context 缓存,您可以清除它:

sslContext = CertificateOptions(...) # Or PrivateCertificate(...).options(...)
...
sslContext._context = None

当它发现它是 None 时,它会自动重新生成上下文,所以至少你不必以这种方式调用 cacheContext。但是您又依赖于私有(private)接口(interface)。

另一种与 Daniel F 的建议更相似的技术是为已经在监听 的套接字提供一个新工厂。这避免了 stopListeninglistenSSL 之间的短暂服务中断。这将是这样的:

from twisted.protocols.tls import TLSMemoryBIOFactory

# DefaultOpenSSLContextFactory or CertificateOptions or whatever
newContextFactory = ...
tlsWebsiteFactory = TLSMemoryBIOFactory(
newContextFactory,
isClient=False,
websiteFactory,
)

listeningPortFileno = sslPort.fileno()
websiteFactory.sslPort.stopReading()
websiteFactory.sslPort = reactor.adoptStreamPort(
listeningPortFileno,
AF_INET,
tlsWebsiteFactory,
)

这基本上只是让 react 堆停止为具有过时配置的旧 sslPort 提供服务,并告诉它开始为新工厂上该端口的底层套接字提供服务事件。在这种方法中,您必须下降到级别稍低的 TLS 接口(interface),因为您不能采用“TLS 端口”,因为没有这样的东西。相反,您采用 TCP 端口并应用必要的 TLS 包装自己(这正是 listenSSL 在幕后为您所做的)。

请注意,此方法比其他方法有一些限制,因为并非所有反应器都提供 filenoadoptStreamPort 方法。如果您想在支持它的地方使用它并在其他地方优雅地降级,您可以测试各种对象提供的接口(interface)。

另请注意,由于 TLSMemoryBIOFactory 是它始终在幕后工作的方式,您还可以调整它的私有(private)接口(interface),如果您有对它的引用:

tlsMemoryBIOFactory._connectionCreator = IOpenSSLServerConnectionCreator(
newContextFactory,
)

它将开始使用它来建立新的连接。但是,再次,私有(private)...

关于 python 扭曲 : Is it possible to reload certificates on the fly?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57812501/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com