你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。

在 Azure 容器应用上配置 Functions 主机密钥存储

函数 访问密钥 是 Functions 运行时用来保护 HTTP 触发的终结点的身份验证令牌。 当调用方调用 HTTP 函数时,它将密钥作为 ?code= 查询参数或 x-functions-key 标头包含。 运行时验证密钥并授权或拒绝请求。

访问密钥与 应用级机密不同。 访问密钥可保护 谁可以调用函数,而应用级机密保护 函数连接到的内容。

何时使用访问密钥

Scenario 为何访问密钥合适
第三方 Webhook GitHub、Stripe 或 Twilio 等提供程序通过 URL 和密钥调用你的函数。 访问密钥直接进入预期的 ?code= 模式。
服务间调用 后端服务 A 通过 HTTP 调用函数 B。 共享密钥比为仅限内部调用设置Microsoft Entra应用注册更简单。
事件网格订阅 事件网格使用平台自动管理 的系统密钥 来验证和调用函数终结点。
开发/测试身份验证 在开发过程中,无需配置完整的 OAuth/OIDC 即可进行基本身份验证。 密钥访问提供了一种低摩擦的身份验证入口,无需配置标识。
迁移兼容性 现有Azure Functions应用已使用访问密钥。 迁移到容器应用时,需要相同的基于密钥的认证方式,以避免中断调用方。

注释

对于面向用户的 API、零信任工作负载或每用户授权方案,请使用 Microsoft Entra ID/OAuth 2.0 而不是访问密钥。 访问密钥是共享机密,没有标识级审核线索。

Prerequisites

访问密钥类型

Functions 运行时管理四种类型的密钥:

密钥类型 Scope Purpose
主密钥 (_master) 整个函数应用 对所有功能和管理/admin/*终端的管理员级别访问权限。 无法撤销,仅轮换。
主机密钥 (default + 自定义) 整个函数应用 授权对应用中任何 HTTP 触发的函数的调用。
函数键 (default + 自定义) 单个函数 授权对一个特定函数的调用。 提供比主机密钥更精细的控制。
系统密钥 扩展端点 由平台扩展使用,例如事件网格 Webhook 订阅和 Durable Functions。 自动管理。

选择存储后端

设置 AzureWebJobsSecretStorageType 环境变量以控制运行时保留访问密钥的位置。 Azure 容器应用支持三个生产级后端。

后端 设置值 自动生成密钥 外部依赖项 最适用于
容器应用密钥存储 containerapps 否 - 你将密钥预配为容器应用机密 None 大多数工作负荷(建议)
Azure 密钥保管库 keyvault 否 - 手动创建触发器 密钥保管库 实例 集中式治理、合规性审核
Azure Blob 存储 blob 是的 存储帐户 旧版应用或现有 AzureWebJobsStorage 帐户

请牢记以下后台的考虑因素:

  • 运行时不会自动选择容器应用的秘密存储。 如果你没有设置AzureWebJobsSecretStorageType或设置为未识别值,函数主机会在可用时AzureWebJobsStorage使用 Blob 存储。
  • 保持 AzureWebJobsStorage 配置以支持存储健康检查和依赖存储的功能。
  • 不要将 AzureWebJobsSecretStorageType 设置为 files. 容器应用文件系统是短暂的,因此当应用扩展到零、重启或部署新版本时,存储在该后端的密钥会丢失。

机密名称模式

存储密钥的命名约定取决于存储后端。

容器应用密钥存储使用不同的习惯用法。 Functions 主机从位于 /run/secrets/functions-keys/ 的卷装载文件中读取密钥。 每个文件使用 虚线 名称(例如 host.master),但容器应用机密名称仅允许 小写字母数字字符和短划线。 当装载机密卷时,必须将 path 字段显式设置为 Functions 主机所期望的带点文件名(例如 secretRef: host-master → path: host.master)。 平台不执行任何自动名称转换。

密钥类型 容器应用机密名称(短划线) 卷装载 path(点)
主密钥 host-master host.master
默认主机密钥 host-function-default host.function.default
自定义主机密钥 host-function-<name> host.function.<name>
特定函数的默认函数键 functions-<functionname>-default functions.<functionName>.default
特定函数的自定义函数键 functions-<functionname>-<keyname> functions.<functionName>.<keyName>
系统密钥 host-systemkey-<extension> host.systemKey.<extension>

小窍门

进行故障排除时,请在后端存储中搜索这些模式,以验证密钥是否已正确配置。

配置容器应用机密存储

建议使用容器应用的密钥存储作为后端。 密钥保留在容器应用平台中,无需外部存储或密钥保管库。 Azure 资源管理器活动日志跟踪对机密和环境变量的更改。

使用此后端,Functions 主机从装载在 /run/secrets/functions-keys/ 位置的卷读取密钥。 主机 不会自动生成密钥。 必须将每个密钥都创建为容器应用机密,并且平台将它们装载为主机可读取的文件。

重要

容器应用机密存储从主机角度来看为只读。 主机读取已装载的密钥文件,但永远不会写入这些文件。 如果缺少所需的密钥,主机不会自动生成它。

步骤 1:设置存储类型

  1. 在 Azure 门户中转到 Functions 容器应用。

  2. 在 “设置”下,选择 “环境变量”。

  3. 选择 “添加”,然后输入以下值:

    财产 价值
    名称 AzureWebJobsSecretStorageType
    价值 containerapps
  4. 选择“ 保存”,然后选择“ 应用” 以确认更改。

步骤 2:生成和存储访问密钥机密

生成密钥值并将其存储为容器应用机密。 至少需要 主密钥 和 默认主机密钥。

  1. 在 Functions 容器应用中的 “设置”下,选择“ 机密”。

  2. 选择 “添加” 并输入以下值:

    财产 价值
    名称 host-master
    类型 容器应用机密
    价值 随机生成的键值。
  3. 选择 并添加。

  4. 使用其他随机生成的值针对 host-function-default 重复此操作。

  5. 若要添加每函数密钥,请添加一个名为 functions-<functionname>-default (全部小写)的机密。

注释

容器应用机密名称仅允许小写字母数字字符和短划线。 必须将卷配置中的 path 字段显式设置为 Functions 主机期望的带点文件名(例如 secretRef: host-master → path: host.master)。 如果没有显式 path,磁盘上的文件将保留包含虚线的名称,Functions 主机将无法找到密钥。

步骤 3:配置卷装载

在 /run/secrets/functions-keys/ 将机密装载为文件。

  1. 在 Functions 容器应用中的 “应用程序”下,选择 “修订”和“副本”。

  2. 选择“创建新修订版”。

  3. 在缩放和存储卷选项卡中的存储卷下,选择添加。

  4. 输入以下值:

    财产 价值
    卷类型 机密
    名称 functions-keys
  5. 对于每个机密,请将 Path 字段设置为 Functions 主机所需的点文件名(例如,设置为 host-master 路径 host.master和 host-function-default 路径 host.function.default)。

  6. 选择 并添加。

  7. 在“ 容器 ”选项卡中,选择容器,然后选择“ 编辑”。

  8. 选择“卷装载”选项卡,然后选择“添加”。

  9. 输入以下值:

    财产 价值
    卷名称 functions-keys
    装载路径 /run/secrets/functions-keys
  10. 选择“ 保存”,然后选择“ 创建 ”以部署新修订。

步骤 4:验证

应用重启后,确认密钥正常工作:

az containerapp function keys list \
  --resource-group "<RESOURCE_GROUP>" \
  --name "<FUNCTIONS_APP_NAME>" \
  --key-type hostKey

您还可以检查应用程序日志中的消息 Resolved secret storage provider ContainerAppsSecretsRepository,以确认主机正在使用 Container Apps 的机密存储。

旋转密钥

若要轮换密钥,请更新容器应用机密并重启应用:

NEW_KEY=$(openssl rand -hex 32)

az containerapp secret set \
  --resource-group "<RESOURCE_GROUP>" \
  --name "<FUNCTIONS_APP_NAME>" \
  --secrets "host-function-default=$NEW_KEY"

az containerapp revision restart \
  --resource-group "<RESOURCE_GROUP>" \
  --name "<FUNCTIONS_APP_NAME>" \
  --revision "<REVISION_NAME>"

注释

所有副本共享相同的挂载机密。 重启后,每个副本都会获取更新的键值。

配置 密钥保管库 或 Blob 存储 作为存储

密钥保管库后端将访问密钥存储为密钥保管库机密,提供企业级审核和访问控制。

  1. 创建密钥保管库(如果你还没有,请创建一个)

    az keyvault create \
      --name "<KEYVAULT_NAME>" \
      --resource-group "<RESOURCE_GROUP>" \
      --location "<LOCATION>"
    
  2. 在容器应用上启用托管标识(如果尚未启用):

    az containerapp identity assign \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --system-assigned
    
  3. 向托管标识授予 密钥保管库 Secrets Officer 角色。 运行时需要读取和写入访问权限才能创建和管理密钥:

    PRINCIPAL_ID=$(az containerapp show \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --query identity.principalId \
      --output tsv)
    
    KEYVAULT_ID=$(az keyvault show \
      --name "<KEYVAULT_NAME>" \
      --query id \
      --output tsv)
    
    az role assignment create \
      --role "Key Vault Secrets Officer" \
      --assignee "$PRINCIPAL_ID" \
      --scope "$KEYVAULT_ID"
    
  4. 设置存储类型和密钥保管库 URI:

    对于系统分配的标识:

    az containerapp update \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --set-env-vars \
        "AzureWebJobsSecretStorageType=keyvault" \
        "AzureWebJobsSecretStorageKeyVaultUri=https://<KEYVAULT_NAME>.vault.azure.net"
    

    对于用户分配的身份标识,还设置客户端 ID:

    az containerapp update \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --set-env-vars \
        "AzureWebJobsSecretStorageType=keyvault" \
        "AzureWebJobsSecretStorageKeyVaultUri=https://<KEYVAULT_NAME>.vault.azure.net" \
        "AzureWebJobsSecretStorageKeyVaultClientId=<USER_ASSIGNED_IDENTITY_CLIENT_ID>"
    
  5. 通过列出密钥触发密钥创建:

    az containerapp function keys list \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --key-type hostKey
    

管理访问密钥

无论后端如何,都使用以下命令列出、创建和删除访问密钥:

注释

至少保持一个副本运行以执行这些密钥管理操作。

  • 列出所有主机密钥:

    az containerapp function keys list \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --key-type hostKey
    
  • 列出主密钥:

    az containerapp function keys list \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --key-type masterKey
    
  • 创建或覆盖自定义主机密钥:

    az containerapp function keys set \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --key-name "MyCustomKey" \
      --key-value "<YOUR_KEY_VALUE>" \
      --key-type hostKey
    
  • 显示一个具体的密钥:

    az containerapp function keys show \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --key-name "<KEY_NAME>" \
      --key-type hostKey
    
  • 删除主机密钥:

    az containerapp function keys delete \
      --resource-group "<RESOURCE_GROUP>" \
      --name "<FUNCTIONS_APP_NAME>" \
      --key-name "MyCustomKey" \
      --key-type hostKey
    

使用访问密钥调用函数

将密钥作为查询参数或请求标头传递。

# Query parameter
curl "https://<FUNCTIONS_APP_URL>/api/<FUNCTION_NAME>?code=<HOST_KEY>"

# Header
curl "https://<FUNCTIONS_APP_URL>/api/<FUNCTION_NAME>" \
  -H "x-functions-key: <HOST_KEY>"