第 2 部分:此示例方案中的身份验证需求

上一部分:简介和背景

在此示例方案中,主应用程序具有三种不同的身份验证要求:

  • 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 服务,而无需在代码或配置文件中嵌入机密。 它还允许在本地开发和云部署之间无缝切换,而无需更改身份验证逻辑。