什么是机密?如何在 Java 中处理它们?
机密是指不应与外界共享的字符串,可以是数据库密码、专用加密密钥、个人访问令牌等。 为增强安全性,许多人还会考虑应将可以帮助攻击者的任何内容视为机密:例如,生产数据库的 URL。 你的数据库不应是可公开访问的。 基本原理是,此类信息本质上是敏感的,代码中提供的信息越少越好。
什么是零信任和零机密?
零信任的概念是,不应盲目信任任何人,并且不应允许任何人在未经验证和授权的情况下访问公司资源。
此概念也适用于 Web 应用程序:它们不应在其代码或其最终二进制文件中存储机密。 我们称之为“零机密”。
机密应由外部系统管理,使用严格的访问规则和验证,以降低攻击风险。
不要将机密放入 Git 存储库
即使你的 Git 存储库是专用的,在源代码中放置任何机密也是一种不好的做法:
- 有权访问你的存储库的任何人都会知道你的敏感数据
- 有权访问你的应用程序二进制文件的任何人都可以从中提取机密
此外,机密存储到 Git 存储库中后,攻击者始终可以通过查看存储库的历史记录来找到它(经过长时间后,机密可能被遗忘)。
不应将任何机密存储在源代码存储库中,即使这样做似乎是可行的。 若要避免此问题,可以使用自动工具定期检查存储库,如果自动工具发现密码或数据库 URL 错误地存储,将发送警告。
使用环境变量
管理机密的最简单解决方案是使用环境变量。 环境变量具有以下优点:
- 易于使用
- 适用于所有系统(甚至本地系统)
- 大家都知道它们及其工作原理
但是,它们的安全性不够:系统上的所有进程都可以读取它们,并且可以在 Java 系统上使用 Java 管理扩展 (JMX) 轻松公开它们。
因此,环境变量通常被视为零信任的第一步:它们比直接将机密存储在源代码中更安全,但它们缺乏管理功能,攻击者很容易访问它们。
使用 Kubernetes 机密
Kubernetes 具有 secrets
概念,这是另一种不错的解决方案。 可以在应用程序的文件系统上将这些机密作为文件加载:Java 程序可以在启动时读取该文件以访问这些机密。 Spring Frameworks 等工具甚至有对此机制的标准支持,使它们可以通过简单、高效的方式使用这些机密。
此机制比环境变量更安全,因为这些文件只能由需要它们的进程读取。 它们还受益于丰富的 Kubernetes 生态系统,它们可由各种管理工具(包括云提供商提供的工具)进行管理。
尽管 Kubernetes 机密是针对 Kubernetes 的不错解决方案,但它们也仅适用于 Kubernetes,并且缺乏高级管理功能,具体取决于用于管理 Kubernetes 基础结构的工具。
使用机密存储
机密存储(如 Hashicorp Vault 或 Azure Key Vault)是用于管理机密的专用软件。 它提供丰富的管理系统来为用户授权、轮换安全密钥,并验证哪些应用程序可以访问哪些机密。
它们还提供外部 API,以便可以在任何系统上使用。 例如,可以对所有 Azure 服务(包括虚拟机、Azure 应用服务、Azure Kubernetes 服务或 Azure Spring Apps)使用 Azure Key Vault。
机密存储是用于管理机密的最安全的解决方案,但需要使用专用工具。