You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Azure函数应用中使用服务主体调用方身份访问受保护API

在Azure函数中以已认证服务主体调用方身份访问ARM的解决方案

方案一:调用方传递ARM访问令牌给函数应用

这是最直接的实现方式,利用服务主体本身可获取ARM令牌的特性,将令牌直接传递给函数应用使用:

  • 调用方(服务主体)通过客户端凭据流获取ARM的访问令牌:
    // 调用方Node.js代码示例
    const { ClientCredentialCredential } = require("@azure/identity");
    const credential = new ClientCredentialCredential("<租户ID>", "<服务主体Client ID>", "<服务主体密钥>");
    const armToken = await credential.getToken("https://management.azure.com/.default");
    
  • 调用函数时,将令牌放入请求的Authorization头,格式为 Bearer <arm-token>
  • 函数应用从请求头提取令牌,直接用于ARM API调用:
    // Azure函数Node.js代码示例
    module.exports = async function (context, req) {
        const armToken = req.headers.authorization?.split(' ')[1];
        if (!armToken) {
            context.res = { status: 400, body: "缺少ARM访问令牌" };
            return;
        }
    
        const armResponse = await fetch(
            "https://management.azure.com/subscriptions/{订阅ID}/resourcegroups?api-version=2021-04-01",
            { headers: { 'Authorization': `Bearer ${armToken}` } }
        );
        const armData = await armResponse.json();
        context.res = { body: armData };
    };
    
  • 核心前提:调用方服务主体需对目标ARM资源拥有对应RBAC权限(如Reader、Contributor)

方案二:函数应用通过托管标识获取调用方服务主体的ARM令牌

若无法让调用方传递令牌,可通过函数的用户分配托管标识,结合AAD权限配置,为调用方服务主体获取ARM令牌:

  1. 权限配置:给函数的用户分配托管标识授予AAD应用权限:Application.Read.All(读取服务主体信息)和DelegatedPermissionGrant.ReadWrite.All(管理委托权限),并完成管理员同意
  2. 获取调用方标识:函数从EasyAuth注入的x-ms-client-principal-id头中提取调用方服务主体的appId
  3. 请求ARM令牌并调用API:
    // Azure函数Node.js代码示例
    const { DefaultAzureCredential } = require("@azure/identity");
    const credential = new DefaultAzureCredential({ 
        managedIdentityClientId: "<用户分配托管标识的Client ID>" 
    });
    
    module.exports = async function (context, req) {
        const callerAppId = req.headers['x-ms-client-principal-id'];
        if (!callerAppId) {
            context.res = { status: 400, body: "无法获取调用方标识" };
            return;
        }
    
        const tenantId = "<租户ID>";
        // 获取Graph API令牌用于调用AAD服务
        const graphToken = await credential.getToken("https://graph.microsoft.com/.default");
        
        // 请求调用方服务主体的ARM访问令牌
        const tokenRes = await fetch(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: new URLSearchParams({
                client_id: "<函数托管标识的Client ID>",
                grant_type: "on_behalf_of",
                assertion: graphToken.token,
                requested_token_use: "on_behalf_of",
                scope: "https://management.azure.com/.default",
                subject_token: callerAppId,
                subject_token_type: "urn:ietf:params:oauth:token-type:jwt"
            })
        });
        const tokenData = await tokenRes.json();
        const armToken = tokenData.access_token;
    
        // 调用ARM API
        const armResponse = await fetch(
            "https://management.azure.com/subscriptions/{订阅ID}/resourcegroups?api-version=2021-04-01",
            { headers: { 'Authorization': `Bearer ${armToken}` } }
        );
        const armData = await armResponse.json();
        context.res = { body: armData };
    };
    
  • 注意:此方案依赖AAD OBO流对服务主体的兼容支持,需测试验证,同时要严格控制托管标识的权限范围,避免过度授权

关键注意事项

  • 两种方案都需确保调用方服务主体对目标ARM资源拥有足够的RBAC权限
  • 方案一无需函数额外配置权限,更轻量化;方案二适合无法修改调用方逻辑的场景

内容的提问来源于stack exchange,提问作者Jurjen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 19:54:41