目前,我的spring-boot应用程序连接到本地MongoDB时没有凭据。为了能够在客户处安装它,我需要提供为DB连接使用用户名和密码的能力。我使用的是application.properties文件,它目前只包含与数据库相关的这3行:
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=myApp
会有这两个额外的:
spring.data.mongodb.username
spring.data.mongodb.password
但当然,我不想在这个文件中有纯文本的密码,或者更糟的是,在我们的git中。一种选择是将它们作为一个参数和一个启动脚本提供,但在流程细节中,它将以纯文本的形式可读。
我在使用Jaypt的属性文件中看到了一些加密,但我不明白这种方法在我的情况下是如何工作的。我从来没有明确使用这些属性,因为它们是由spring自动获取来进行连接的。
什么是最安全的方法?
TL;DR
这取决于您的安全/风险状况,哪种方法是可以接受的。
较长的读数
你的问题是:什么是最安全的方法?
这个问题的一个简单答案是,不要将密码存储在任何地方,而是让操作员输入密码。显然,这不是你想要的答案,因为对于数据中心的服务器,甚至是云中的虚拟机,这种方法是不可行的。
为了了解什么方法足够安全,哪种方法是可以接受的,了解你的组织背景、它接受风险的意愿以及由此产生的后果(即处理机密的要求)是很重要的。这种评估可能会导致,对于一个组织来说,以纯文本存储凭据可能很好(因为环境是安全的,或者暴露的秘密的威胁很低),而其他组织则需要通过适当的密钥管理和审计进行加密。
您已经描述了在Git中存储凭据不是一个合适的选项。所以我认为你正在寻找一种以某种方式保护实际秘密的方法。保护可以发生在不同的级别:
- 在应用访问控制的受保护位置存储机密
- 受访问保护的主机上的环境变量
- 受权限保护的受访问控制的文件
- 以加密形式存储机密
- 对值进行加密并将其存储在文件中。在这里,您需要考虑谁有权访问此文件以及密钥管理。介绍一类鸡和蛋问题
- 对值进行加密并将其存储在内存中。不过,您需要解决关键管理问题
- 正在从受信任的源检索机密
- 证书由操作人员输入(不太可行)
- 要求服务为您提供凭证。远程服务保护机密,并允许您/您的应用程序请求机密
还有更多的可能性,但让我们暂时坚持下去。与上述可能性相关联的一个方面是将凭证从源传输到目标目的地。传输通常跨越一对多方,这些方中的每一方都需要以某种方式得到信任(即,您必须确保某一方不会泄露您的凭据)。这种模式也被称为信任链。如果信任链中的每一跳都是已知的,为了不暴露您的凭据,那么您可以对此上下文使用特定的保护模式。如果你发现了一个增加暴露风险的薄弱环节(例如公用文件夹、操作员查找),那么你需要根据自己的需求再次提高保护级别。
话虽如此,让我们看看Spring Boot有哪些应用机密保护的可能性:
环境变量
您可以使用环境变量或系统属性存储配置。波动性方面不同于持久性(例如,基于文件的)存储。可以在应用程序启动之前/启动时设置变量。
环境变量示例:
export SPRING_DATA_MONGODB_USERNAME=…
export SPRING_DATA_MONGODB_PASSWORD=…
java -jar my-app.jar
系统属性示例:
java -jar my-app.jar -Dspring.data.mongodb.username=… -Dspring.data.mongodb.password=…
java -jar my-app.jar --spring.data.mongodb.username=… --spring.data.mongodb.password=…
请注意,环境变量/命令行可以通过/proc
文件系统和ps
等工具进行内省
有关更多详细信息,请参阅外部化配置的参考文档。
加密配置属性
Spring Cloud为单个属性提供加密支持。可以使用不同的密钥和密钥类型(对称、非对称)加密选定的属性。这种方法允许您选择应该加密的属性,而无需加密整个文件。
环境变量示例:
应用程序属性
spring.data.mongodb.password={cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ
请注意,这种方法引入了物业密钥管理的要求。
有关更多详细信息,请参阅有关Spring Cloud Config Encryption and Decryption的参考文档。
应用程序控制的机密
Spring Boot中的配置属性从Environment
获得,并由PropertySource
s提供。在启动Spring Boot之前,您可以贡献属性或整个PropertySource
。
添加PropertySource
:的示例
SpringApplication app = new SpringApplication(DemoApplication.class);
app.addInitializers(new ApplicationContextInitializer<ConfigurableApplicationContext>() {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.getEnvironment().getPropertySources().addFirst(…);
}
});
app.run(args);
添加属性的示例:
SpringApplication app = new SpringApplication(DemoApplication.class);
app.setDefaultProperties(Collections.singletonMap("spring.data.mongodb.password", "…"));
app.run(args);
远程配置属性
Spring Cloud Config允许您集中Spring Cloud Config Server提供的配置。属性不再存储在本地,而是由配置服务提供,该服务的安全性与应用程序保护级别不同。要设置SpringCloudConfigServer,您需要一个额外的服务,并在应用程序中集成客户端依赖关系。
请注意,这种方法并不能解决整体问题,只是将其转移到其他人的责任中。
有关更多详细信息,请参阅Spring Cloud Config Server上的参考文档。
使用秘密管理
如果你能负担得起秘密管理,如HashiCorp Vault、CredHub、Azure KeyVault、Kubernetes Secrets,那么你可以利用你的平台/秘密管理系统的功能对你的凭据进行保护。
秘密管理系统通常为您处理加密、审核和访问控制。这些系统保存凭证的加密副本。一旦您请求凭据(通常通过TLS安全连接),系统就会检查您/您的应用程序是否被允许访问该机密。
其中一些系统还提供动态秘密。根据需要为特定应用程序实例生成动态机密。如果您的应用程序想要连接到MongoDB,机密管理系统将创建一个凭据对,并将这些凭据对服务器到您的应用软件。当您的应用程序停止时,机密管理系统将吊销凭据。
有关更多详细信息,请参阅Spring Cloud Vault上的参考文档。
@mp911de:答案的一个附录
Spring Boot中还有第二个文件选项:您可以提供一个额外的文件来覆盖标准配置,方法是向文件提供ENV变量SPRING_CONFIG_ADDITIONAL_LOCATION
,或者将其添加为类似spring.config.additional-location
的命令属性,请参阅应用程序属性文件。
这可以让您有机会通过一些基于文件的秘密部署来添加凭据(例如,用作卷Mounts的Kubernetes秘密、基于Puppet/Chef/Ansible的秘密部署等)。