如何在 Synapse pipeline 中安全地动态传递 API 认证请求头?
可以保留 REST linked service 的 Anonymous 认证方式,在循环内的 Copy activity 中,通过 REST source 的 Additional headers 动态引用 token 和 subscription key。同时,为涉及密钥的活动开启 Secure Input、Secure Output,避免敏感值进入活动监控日志。
Anonymous 表示连接器不会自动处理认证,API 请求仍可携带你配置的认证请求头。Microsoft REST 连接器文档支持这种配置。
1. 确认活动名称和依赖关系
以下示例假设三个 Web activity 的名称和用途如下:
| 活动名称 | 用途 | 后续使用的输出 |
|---|---|---|
GetClientSecret | 从 Key Vault 获取 client secret | .output.value |
GetBearerToken | 请求 token endpoint | .output.access_token |
GetSubscriptionKey | 从 Key Vault 获取 subscription key | .output.value |
.output.value 适用于直接调用 Key Vault 获取 secret 的返回结构。如果 subscription key 来自其他接口,应根据实际响应结构调整表达式。
在 GetClientSecret 成功后执行 GetBearerToken;等 GetBearerToken 和 GetSubscriptionKey 都成功后,再启动 ForEach。这样循环内的 Copy activity 就可以读取这些活动的输出。
2. 在 Copy activity 中添加动态请求头
打开 ForEach 内的 Copy activity,在 Source → Additional headers 中添加两项,并分别通过 Add dynamic content 输入表达式。
Authorization 的值:
@concat('Bearer ', activity('GetBearerToken').output.access_token)
subscription key 对应请求头的值:
@activity('GetSubscriptionKey').output.value
注意 Bearer 后有一个空格。这里假设 token endpoint 返回的 access_token 不含 Bearer 前缀。
subscription key 的请求头名称必须与目标 API 的要求一致。原问题没有提供该名称;如果接口要求 Ocp-Apim-Subscription-Key,就使用这个名称,否则替换为接口实际要求的名称。
这两个表达式读取上游活动的输出,不需要在每次循环中重新获取 token,也不必先把凭据复制到 pipeline 变量。
3. 用 ForEach 当前项生成 endpoint 地址
可以将 REST linked service 的 URL 设置为原脚本中的 $baseUrl,再通过 REST dataset 的 relativeUrl 指定剩余路径。
例如,在 pipeline 中定义:
- Array 参数
resourcePaths:对应原来的 endpoint 名称数组。 - String 参数
contextPath:对应原来的$contextPath。
ForEach 的 Items 使用:
@pipeline().parameters.resourcePaths
在 REST dataset 中增加 String 参数 relativePath,将 dataset 的 relativeUrl 设置为:
@dataset().parameters.relativePath
然后在循环内的 Copy activity 中,给源 dataset 参数 relativePath 传入:
@concat(pipeline().parameters.contextPath, '/', item())
上述拼接假设 contextPath 非空,且 contextPath、endpoint 名称两端都没有多余的 /。如果没有 contextPath,直接传入 @item() 即可。
将 REST source 的请求方法设为 GET,sink 使用 storage account 对应的 dataset。不同 endpoint 应使用能够区分的数据输出路径或文件名,避免写入同一个目标文件。REST dataset 的 relativeUrl 与 linked service URL 的组合方式见连接器配置说明。
4. 保护 secret、token 和请求头
在相关活动的 General 设置中配置:
| 活动 | Secure Input | Secure Output |
|---|---|---|
GetClientSecret | 输入中含敏感信息时开启 | 开启 |
GetBearerToken | 开启,输入包含 client secret | 开启,输出包含 access token |
GetSubscriptionKey | 输入中含敏感信息时开启 | 开启 |
| 循环内的 Copy activity | 开启,输入包含认证请求头 | 输出本身敏感时开启 |
例如,获取 token 的活动应具有以下策略配置;这是活动 JSON 的局部片段:
{
"policy": {
"secureInput": true,
"secureOutput": true
}
}
Secure Output 会隐藏活动输出的监控内容,但后续活动仍可通过表达式使用该输出。消费 secret 的下游活动还需要自行开启 Secure Input,因为保护设置不会自动沿依赖关系传播。Microsoft Key Vault 使用指南说明了这两个设置的配合方式。
读取 Key Vault 时,可以使用 Synapse workspace 的 managed identity,并授予它所需的 secret 读取权限。不要把真实密钥写入表达式、普通参数默认值或调试信息中。
5. 配置后需要检查什么
- token 请求格式:沿用原脚本的
application/x-www-form-urlencoded。如果通过表达式拼接请求体,参数值需要做表单编码,尤其是可能包含特殊字符的 client secret。 - token 有效期:循环可以复用同一个 token,但运行时间必须在其有效期内。长时间任务需要根据实际过期信息设计重新获取 token 的步骤。
- 权限和请求头:出现
401或403时,结合接口错误响应检查 token 是否过期、目标 audience、scope 或应用权限,以及 subscription key 是否有效。不能仅凭状态码认定原因。 - 循环并发:如果多个 endpoint 并行调用,应结合 API 限流要求设置并发,并避免在循环内修改共享的 pipeline 变量。
备注:内容仅供参考。
