首页 > 解决方案 > 微服务通信安全

问题描述

只是我在家里做的一个宠物项目,现在我大部分时间都把自己锁在室内了。话虽如此,我正试图把它和所有的花里胡哨的东西放在一起,主要是为了我可以学习一些新东西。我早在 2015 年就实现了这个版本 1,它已经像我的树莓派上的冠军一样运行了 5 年多。

对于更新版本(Angular 9/.net core 3.1),我正在考虑使用 Auth0 作为我的身份验证提供程序(但我也在考虑使用 AWS Cognito)。我已经确定了应用程序的微服务边界,并将尽可能使用 RabbitMQ 进行服务间消息传递。但是,在许多情况下,一个 MS 需要从另一个 MS 获取数据才能完成请求。本质上,在单体应用中本来就是数据库连接。我在周末做了一些阅读,发现您可以在前端、API 网关中进行连接,或者让 MS A 对 MS B 执行 REST 查询。第一个感觉有点傻,因为然后浏览器必须执行多个请求,第二个请求需要我构建一个网关(我只是打算使用 NGINX 作为反向代理)。所以我选择了第三个选项...

我的问题...

在进行服务间通信时如何处理安全性?为了方便起见,我考虑过的选项:

  1. 发出请求时将 Auth 标头从 MS A 转发到 MS B
  2. 托管一个 MS B 的内部实例,该实例不通过反向代理暴露给 Internet,并且只暴露跨微服务通信所需的功能。(不确定这个解释是否有意义)
  3. 让 MS A 从身份验证提供商(Auth0、AWS Cognito 等)请求它自己的令牌,并使用该令牌调用 MS B。

有这样做的标准方法吗?

标签: .netsecurityjwtmicroservices

解决方案


这些都是很好的问题,但不幸的是,没有“标准”的方式来做这件事。我会说您的选项将在 1 和 2 之间,每个选项的原因如下:

选项 1 - 发出请求时将 Auth 标头从 MS A 转发到 MS B

如果您要在多个不同团队中大规模应用这种做法,每个团队都拥有不同的服务,这将是最佳途径。MS B 的创建者不一定知道谁在长期调用他们,因此为了确保他们不会强加安全风险,公开其服务的最简单方法是要求可验证的 JWT。这将防止有人意外地不恰当地使用他们的服务。

选项 2 - 托管 MS B 的内部实例,该实例不通过反向代理暴露给 Internet,并且仅暴露跨微服务通信所需的功能。

您可以认为这种方法有点像网关上的 TLS 终止。您可以在每个服务中终止 TLS(如 JWT 的选项 1),或者您可以在网关处终止它,以确保来自外部世界的流量在进入之前被加密,同时允许它在墙内自由流动。网关也可以是验证和解码 JWT 的唯一责任方,然后在检查通过后允许流量在内部自由流动。

此选项对于由单个团队或开发人员维护的应用程序非常实用,因为它非常易于编排。如果每个“内部”服务都简单地响应用户 ID/主题来满足请求并相信用户 ID 是从经过验证的 JWT 中提取的,那么您可以更轻松地构建其他内部系统。此解决方案最容易上手,但如果您无法信任应用程序或团队中的其他服务或开发人员,则可能会很棘手。

选项 3 - 让 MS A 从身份验证提供商(Auth0、AWS Cognito 等)请求它自己的令牌,并使用该令牌调用 MS B

我不建议每个服务都发布它自己的 oauth 令牌。来自像 Auth0 这样的 oauth 提供者的 JWT 是发给用户的,而不是机器。

话虽如此,对云安全性的重要补充将是对所有服务之间流动的流量进行凭证并将其列入白名单。这可能是诸如 Cilium 等工具强制执行的Kubernetes NetworkPolicys之类的东西,或者它们可能是独特的 SSL 证书,旨在为堆栈中服务之间的每个关系唯一地代理通信。这种增加的安全性与您上面的问题没有任何关系,但在考虑保护云环境中的进程间通信时会提供额外的思考。


推荐阅读