我正在编写一个基于spring-boot的微服务,该服务将部署在GKE上。要配置服务帐户凭据,我确实看到有多个选项可用。什么是可用的最优选且可能更安全的选项。我已经尝试了以下方法,请建议的其他方法
- 带有spring.cloud.gcp.credentials.location的CredentialsProvider接口
- spring.cloud.gcp.credentials.encoded-key
- GCP秘密管理员
在云环境中,通常最安全、管理开销最小的最佳选择是使用云提供商的相应服务——在您的情况下,它将是Secret Manager。当然,如果您计划不将您的应用程序与特定的云提供商捆绑在一起,或者也不满足预处理环境,那么您可以使用第三方秘密管理提供商,如HashiCorp Vault。
然而,即使使用Secret Manager,如果您直接与API交互,您也必须提供密钥来调用API,这会产生另一个问题。一般建议的解决方案是使用应用程序身份验证作为服务帐户,并直接与此处概述的Secret manager交互。或者,还有其他方法可以使用CSI驱动程序在GKE卷上安装Secret Manager的Secrets,如下所述。
运行一个安全的集群和容器应用程序是一个关键要求,这里有关于GKE安全强化的进一步建议,其中也包括Secret管理。更具体地,您可以查看";CIS GKE基准建议:6.3.1";
虽然@Shailendra为您提供了一个很好的解决方案,但在使用GKE时,您可以将敏感信息存储为Kubernetes机密。
Kubernetes和GKE文档都提供了几个创建秘密的示例。
稍后,您可以以多种方式使用配置的机密,在简单的用例中,将其用作应用程序中可以使用的环境变量。请参阅这篇文章。
Spring Cloud Kubernetes项目为使用这些机密作为属性源提供了支持。
这种方法允许您使用minikube
或kind
在本地测试应用程序部署,然后将相同的工件部署到云提供商。此外,它是云提供商不可知的,因为您正在使用开箱即用的Kubernetes工件。
恐怕我们过于专注于为您提供进一步的替代方案,以至于最后我们实际上没有回答您的问题。
之前,我会给你使用Kubernetes Secrets的建议,它仍然很好,但请允许我稍后再谈。
根据您尝试设置的不同属性,您正在尝试代表您的应用程序配置凭据,以便与GCP中部署的其他服务进行交互。
为此,您首先需要的是一个服务帐户。
简言之,服务帐户是一个聚集了多个权限的软件工件。
该服务帐户稍后可以分配给某个GCP资源,分配给某一GCP服务,并且它将允许该资源在与其他GCP资源和服务交互时继承或代表执行配置的权限。
每个服务帐户都将有一组相关的密钥,用于识别服务帐户,即您试图保持安全的信息。
有不同类型的服务帐户,主要是默认服务帐户,由GCP在您启用或使用某些谷歌云服务时创建-一个用于计算引擎,一个用于应用程序引擎-以及用户定义的。
您可以修改与这些服务帐户关联的权限:需要记住的重要事项是始终遵循最小权限原则,只授予服务帐户执行任务所需的权限,而不授予其他权限。
默认情况下,GKE集群将使用默认的计算引擎服务帐户及其定义的作用域。这些权限将由您的pod在联系其他服务时继承。
因此,一个可能的选择就是为GKE配置一个合适的服务帐户,并在代码中使用这些权限。
您可以使用默认的计算引擎服务帐户,但是,如GCP文档中描述如何加强集群安全时所示:
每个GKE节点都有一个与其关联的身份和访问管理(IAM)服务帐户。默认情况下,节点将获得计算引擎默认服务帐户,您可以通过导航到云控制台的IAM部分找到该帐户。默认情况下,此帐户具有广泛的访问权限,使其对各种应用程序都很有用,但它的权限比运行Kubernetes Engine集群所需的权限更多您应该创建并使用最低特权服务帐户来运行GKE集群,而不是使用计算引擎默认服务帐户
因此,您可能需要创建一个具有最低权限的服务帐户来运行集群(和)应用程序。上述链接提供了所有必要的信息。
作为替代方案,您可以为您的应用程序配置不同的服务帐户,这就是您可以使用Kubernetes Secrets的可能替代方案。
请:
-
不要直接提供您自己的
CredentialsProvider
实现,我认为与其他解决方案相比,它不会为您带来任何额外的好处。 -
如果要使用
spring.cloud.gcp.credentials.location
配置属性,请创建一个Kubernetes机密并将其公开为文件,然后将此属性的值设置为该文件位置。 -
以一种非常相似的方式,使用Kubernetes Secrets,例如本文中的示例,您可以在环境变量
GOOGLE_APPLICATION_CREDENTIALS
下公开服务帐户凭据,Spring GCP和不同的GCP客户端库都会查找该变量,以获得所需的凭据。 -
我不会使用配置属性
spring.cloud.gcp.credentials.encoded-key
,在我看来,这种方法使密钥更适合威胁——可能你必须处理VCS问题,等等。 -
秘密经理。。。正如我所说,这是一个合适的解决方案,正如@Shailendra在他的回答中所指出的那样。
-
纪尧姆提供的选择也非常好。
首选的方法很难回答。取决于你的意愿。。。
就我个人而言,我更喜欢保持高级别的安全性,这与服务帐户身份验证有关,漏洞可能是一场灾难。
所以,太保守秘密了,我宁愿没有秘密。既不在K8S秘密中,也不在秘密管理器中!问题解决了!!
您可以使用ADC(应用程序默认凭据)实现这一点。但是,像这样,开箱即用,ADC使用节点标识。这里的问题是,如果在同一个节点上运行多个pod,那么所有pod都将具有相同的标识,从而具有相同的权限。
一个很酷的功能是使用Workload Identity。它允许您将服务帐户与K8S部署绑定。ADC原理是相同的,只是它在pod级别绑定,而不是在节点级别(创建了一个拦截ADC请求的代理)
如果您的应用程序在GCP上运行,首选方式是使用Google GCP客户端提供的默认凭据。使用默认凭据提供程序时,客户端将使用与您的应用程序关联的服务帐户。