在此示例方案中,主应用程序具有三种不同的身份验证要求:
Azure Key Vault
应用程序必须使用 Azure Key Vault 进行身份验证才能检索调用第三方服务所需的安全存储的 API 密钥。
第三方 API
检索 API 密钥后,应用程序会使用它对外部第三方 API 进行身份验证。
Azure 队列存储
处理请求后,应用程序必须进行身份验证,以便使用 Azure 队列存储将消息入队进行异步或延迟处理。
这些任务要求应用管理三组凭据:
两个用于 Azure 资源(密钥保管库和存储)
一个用于外部服务(第三方 API)
密钥认证挑战
构建安全云应用程序需要仔细处理凭据,尤其是在涉及多个服务时。 此示例方案提出了几个关键挑战:
与 Key Vault 相关的循环依赖项
应用程序使用 Azure Key Vault 安全地存储机密,例如第三方 API 密钥或 Azure 存储凭据。 但是,若要检索这些机密,应用必须先使用 Key Vault 进行身份验证。 这会产生循环问题:应用需要凭据才能访问 Key Vault,但这些凭据必须安全地存储。 如果没有安全解决方案,这可能会导致开发环境中的硬编码凭据或不安全配置。
安全处理第三方 API 密钥
从 Key Vault 检索 API 密钥后,应用程序必须使用它来调用外部第三方服务。 必须非常小心地处理此密钥:
- 从不硬编码源代码或配置文件
- 从未记录到 stdout、stderr 或应用程序日志
- 仅保存在内存中,并在运行时访问,就在使用之前
- 请求完成后及时处理
未能遵循这些做法会增加凭据泄露或未经授权的使用的风险。
保护 Azure 队列存储凭据
若要将消息写入 Azure 队列存储,应用通常需要连接字符串或共享访问令牌。 这些凭据:
- 必须存储在安全位置,例如 Key Vault
- 不得显示在日志、堆栈跟踪或开发人员工具中
- 应仅通过安全运行时机制访问
- 如果使用托管标识,则需要适当的 RBAC 配置
环境灵活性
应用必须使用相同的代码库和最小的条件逻辑,在本地开发和云生产环境中可靠运行。
这意味着:
- 代码中没有嵌入特定于环境的机密
- 无需手动切换凭据或逻辑路径
- 跨环境一致使用基于标识的身份验证
使用 Microsoft Entra ID 进行 Azure-First 身份验证
随着云应用程序在复杂性上扩展并与更多服务集成,安全且简化的身份验证变得至关重要。 Azure 通过 Microsoft Entra ID 提供“Azure 优先”标识模型,支持统一标识管理和与 Azure 服务无缝集成,以实现安全、无凭据的身份验证。
Microsoft Entra ID 使应用能够使用托管标识安全地进行身份验证,而不是在应用程序代码中手动管理机密或嵌入凭据(这种做法容易出现安全风险)。
Microsoft Entra 托管身份的主要优势包括:
代码中没有机密
应用程序不再需要硬编码的连接字符串、客户端机密或密钥。
应用的内置标识
Azure 可以自动将托管标识分配给应用,从而允许安全访问 Key Vault、存储和 SQL 等服务,而无需其他凭据。
环境一致性
相同的代码和标识模型可在本地开发和 Azure 托管的环境中使用 Azure SDK 的 DefaultAzureCredential 工作。
环境特定的标识流
使用 Microsoft Entra ID 进行身份验证的应用程序受益于在 Azure 托管和本地开发环境中无缝工作的灵活标识模型。 此一致性是使用 Azure SDK 实现的 DefaultAzureCredential
,该 SDK 会根据环境自动选择适当的标识方法。
Azure 环境
将应用程序部署到 Azure 时:
- 托管标识会自动分配给应用程序。
- Azure 在内部处理令牌颁发和凭据生命周期 - 无需手动机密。
- 应用程序使用 Role-Based 访问控制(RBAC)或 Key Vault 访问策略来访问服务
本地开发环境
在本地开发期间:
- 服务主体充当应用的标识。
- 开发人员使用 Azure CLI(az login)、环境变量或 Visual Studio/VS Code 集成进行身份验证。
- 相同的应用程序代码无需修改即可运行,仅标识源更改。
在这两个环境中,Azure SDKs 使用 DefaultAzureCredential
,该 DefaultAzureCredential
将标识源抽象掉,并自动选择正确的方法。
安全开发的最佳做法
虽然可以将机密设置为环境变量(例如,通过 Azure 应用设置),但此方法有缺点:
- 必须在本地环境中手动复制机密。
- 泄露到源代码管理中的机密存在风险。
- 可能需要其他逻辑才能区分环境。
相反,建议的方法是:
- 使用 Key Vault 存储第三方 API 密钥和其他机密。
- 将托管标识分配给已部署的应用。
- 使用服务主体进行本地开发,并为其分配相同的访问权限。
- 在你的代码中使用
DefaultAzureCredential
来抽象身份验证逻辑。 - 避免存储或记录任何凭据。
实践中的身份验证流
下面是身份验证在运行时的工作原理:
- 代码将创建一个
DefaultAzureCredential
实例。 - 使用此凭据实例化客户端(例如 SecretClient、QueueServiceClient)。
- 当应用调用方法(例如,
get_secret()
)客户端使用凭据对请求进行身份验证。 - Azure 验证标识,并检查其是否具有执行操作的正确角色或策略。
此流可确保应用可以安全地访问 Azure 服务,而无需在代码或配置文件中嵌入机密。 它还允许在本地开发和云部署之间无缝切换,而无需更改身份验证逻辑。