我正在一个项目中,我们在Docker容器中连同API和数据库一起运行S3服务器(MinIO)。这三个服务运行在Docker网络上。
在Docker网络中,S3服务器以随机IP(例如172.18.0.3)出现,并且也以其容器名称可用(对于本示例,我们只说s3
)。从网络的外部,S3服务器暴露在端口9000上,但是如果直接在dev上访问,则需要使用dev机器的实际IP(例如192.168.1.5)或本地主机进行访问机。
在我的场景中,用户应用程序使用MinIO.NET库将文件发布到容器中的S3服务器,然后将记录添加到数据库中,其中包括MinIO.NET生成的预签名URL。 API监视数据库并查看添加,然后尝试使用预签名的URL来检索文件以对其进行处理。 问题在于容器网络内部和外部的主机名不同,并且由于签名不匹配,API无法检索文件。
(注意:我们正在使用S3,因为我们最终希望将其用于可能不会发生此问题的公共S3服务器上。该问题特定于开发/测试环境。)
通过阅读MinIO.NET源,我了解到问题在于用于访问S3服务器的主机名是签名的一部分。我已经考虑过以下解决问题的方法:
要求发布到S3服务器的任何人都将s3
添加到其主机文件中,以便在容器网络外部运行的MinIO客户端可以使用正确的主机名访问S3服务器。这很丑陋,无法广泛维护,并且要求人们了解如何在Windows上编辑安全文件。不好。
在MinIO.NET库中子类V4Authenticator
的子类,在生成签名时添加了某种选项来覆盖主机。 (.NET库似乎负责签名的生成,而不是MinIO服务器本身)。问题是MinIO.NET代码没有遵循DI原理,因此我最终不得不分叉整个存储库来执行此操作,因为初始化代码直接实例化了V4Authenticator对象。 (该代码确实使用了IAuthenticator接口,但是看起来好像是用于单元测试而不是用于DI的目的)
复制/粘贴生成预签名URL的代码。似乎好一点,但是该库直接对HttpRequest对象进行操作以提取标头以及签名所需的标头。再次,这可能最终需要对MinIO.NET库进行一些深度重写或修改(派生),只是为了使其公开那些HttpRequest对象供我自己的代码使用。
完全跳过MinIO.NET,仅编写我自己的库。非常繁琐且不理想,更不用说潜在的不安全感(?)
结果是我需要能够生成S3签名,但在签名期间提供一个明确的主机名。
有什么想法吗?