推荐超级课程:
@TOC
此方法允许您使用托管身份(Managed Identity)调用Function App触发器,以增强安全性
1. 背景介绍
许多企业不愿使用应用密钥来调用Function App触发器,因为他们担心这些固定字符串可能会被暴露。
此方法允许您使用托管身份来调用Function App触发器,以增强安全性。
我将提供Bash和Node.js的示例。
2. 设置
- 创建一个Linux Python 3.11 Function App
1.1. 配置身份验证以阻止未经身份验证的调用者,同时允许Web应用的托管身份进行身份验证。
— | — |
身份提供商 | 微软 |
为您的应用程序及其用户选择一个租户 | Workforce配置 |
应用注册类型 | 创建 |
名称 | \[自动生成\] |
客户端密钥过期 | \[适合您的业务目的\] |
支持的账户类型 | 任何Microsoft Entra目录 - 多租户 |
客户端应用程序要求 | 允许来自任何应用程序的请求 |
身份要求 | 允许来自任何身份的请求 |
租户要求 | 使用基于发行者的默认限制 |
令牌存储 | \[已勾选\] |
1.2. 创建一个匿名触发器。由于您的应用已经通过应用注册受到保护,因此不需要额外的Function App级别保护;否则,您需要一个Function密钥来触发它。
1.3. 配置好Function App后,尝试直接访问端点 - 您应该收到401未授权错误,确认没有适当的托管身份授权无法访问触发器。
1.4. 进行这些更改后,等待10分钟以使设置生效。
- 创建一个Linux Node.js 20 Web应用,获取访问令牌,并使用Web应用调用Function App触发器(Bash示例)
2.1. 在Web应用设置中启用系统分配的托管身份。
2.2. 打开Web应用的Kudu SSH控制台。
2.3. 运行以下命令,进行必要的修改:
- subscriptionsID → 替换为您的订阅ID。
- resourceGroupsID → 替换为您的资源组ID。
- application_id_uri → 替换为您Function App的应用注册中的应用程序ID URI。
- https://az-9640-faapp.azurewebsites.net/api/test_trigger → 替换为相应的Function App触发器URL。
# 请将目标资源设置为您自己的
subscriptionsID="01d39075-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
resourceGroupsID="XXXX"
# 变量设置(无需更改)
identityEndpoint="$IDENTITY_ENDPOINT"
identityHeader="$IDENTITY_HEADER"
application_id_uri="api://9c0012ad-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
# 安装必要的工具
apt install -y jq
# 获取访问令牌
tokenUri="${identityEndpoint}?resource=${application_id_uri}&api-version=2019-08-01"
accessToken=$(curl -s -H "Metadata: true" -H "X-IDENTITY-HEADER: $identityHeader" "$tokenUri" | jq -r '.access_token')
echo "访问令牌: $accessToken"
# 运行触发器
response=$(curl -s -o response.json -w "%{http_code}" -X GET "https://az-9640-myfa.azurewebsites.net/api/my_test_trigger" -H "Authorization: Bearer $accessToken")
echo "HTTP状态码: $response"
echo "响应体:"
cat response.json
2.4. 如果一切设置正确,您应该会看到一个成功的调用结果。
3. 使用Web应用调用Function App触发器(Node.js示例)
我还提供了我的示例,您可以相应地进行修改,并将其保存到/home/site/wwwroot/callFunctionApp.js并运行它
cd /home/site/wwwroot/
vi callFunctionApp.js
npm init -y
npm install azure/identity axios
node callFunctionApp.js
// callFunctionApp.js
const { DefaultAzureCredential } = require("@azure/identity");
const axios = require("axios");
async function callFunctionApp() {
try {
const applicationIdUri = "api://9c0012ad-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; // 在此处更改
const credential = new DefaultAzureCredential();
console.log("正在请求令牌...");
const tokenResponse = await credential.getToken(applicationIdUri);
if (!tokenResponse || !tokenResponse.token) {
throw new Error("获取访问令牌失败");
}
const accessToken = tokenResponse.token;
console.log("令牌已获取:", accessToken);
const apiUrl = "https://az-9640-myfa.azurewebsites.net/api/my_test_trigger"; // 在此处更改
console.log("正在调用API...");
const response = await axios.get(apiUrl, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
console.log("HTTP状态码:", response.status);
console.log("响应体:", response.data);
} catch (error) {
console.error("调用函数失败", error.response ? error.response.data : error.message);
}
}
callFunctionApp();