部署函数通过应用认证调用外部 Azure 和 Fabric 资源作为应用身份。 声明函数所需的受众,并通过 ctx.Tokens 使用平台提供的资源范围令牌。
开发者的CLI登录和创作时的端点发现与部署的运行时访问是分开的。 即使开发者可以访问资源,也要核实已部署应用身份的权限。
先决条件
- 一个带有Functions初始化的Fabric应用。 关于设置说明,请参见“在 Fabric 应用中使用函数”。
- 在
rayfin/rayfin.yml中将services.functions.auth.type设置为application。 有关配置细节,请参见 应用认证。 - 应用身份授予对函数代码调用的每个外部资源的访问权限。
声明外部连接
在 RayfinContext 注解中声明受众,然后从 ctx.Tokens 读取作用域令牌:
import {
UserDataFunctions,
AudienceType,
type RayfinContext,
} from '@microsoft/fabric-user-data-functions';
const udf = new UserDataFunctions();
udf.func(
'accessStorage',
async (
ctx: RayfinContext<AppSchema, AudienceType.Storage>,
): Promise<string> => {
const token: string = ctx.Tokens.Storage;
// Use the token with the resource SDK or REST API.
return 'ok';
},
[],
);
注释就是声明。 在 中 RayfinContext<Schema, Audiences> 列出受众即可识别连接绑定。 将 udf.func() 的第三个参数保持为 []。
ctx.Tokens 被缩小到你指定的受众。 未申报受众会导致编译错误:
async (
ctx: RayfinContext<AppSchema, AudienceType.Sql | AudienceType.Storage>,
) => {
const sqlToken: string = ctx.Tokens.Sql;
const storageToken: string = ctx.Tokens.Storage;
};
令牌值属于 string 类型。 声明某个受众会注册其绑定关系,但并不保证令牌可用或能够访问资源。 如果主机没有提供声明的令牌,读取其 ctx.Tokens 属性会报错。
指定模式参数
RayfinContext 首先获取你的应用架构定义。 使用你传递到 RayfinClient<AppSchema> 的同一个模式,这样数据客户端在添加受众时保持类型:
async (ctx: RayfinContext<AppSchema, AudienceType.Sql>) => {
const data = ctx.getDataClient();
const token = ctx.Tokens.Sql;
};
如果函数需要受众但不访问 Rayfin 数据库,则明确传递默认模式:
async (ctx: RayfinContext<Record<string, any>, AudienceType.Fabric>) => {
const token = ctx.Tokens.Fabric;
};
支持的受众
AudienceType 是支持受众的真相来源:
| 外部资源 | AudienceType |
|---|---|
| Fabric 湖仓、仓库、Fabric 中的 SQL 数据库、镜像数据库或 Azure SQL 数据库 | Sql |
| Fabric OneLake files、Azure Blob 存储、Azure Table storage,或 Azure 队列存储 | Storage |
| Microsoft Fabric REST API | Fabric |
| Azure AI Foundry | AzureAI |
| Azure DevOps | ADO |
Power BI 语义模型无法通过 ctx.Tokens 使用。 请改用 fabric-semanticmodel 连接器。 有关连接器的说明,请参见 连接到 Fabric 数据。
理解部署元数据
类型参数在函数运行前会被擦除。 在 npx rayfin up期间,TypeScript 编译器解析已声明的受众,并将 union 写入部署元数据。 函数工作者利用这些元数据绑定连接。
当 Functions 项目具有 tsconfig.json 时,类型别名可正常工作:
type SqlAccess = AudienceType.Sql;
async (ctx: RayfinContext<AppSchema, SqlAccess>) => {
const token = ctx.Tokens.Sql;
};
优先使用字面值 AudienceType.X。 如果 Functions 项目没有 tsconfig.json,CLI 无法使用编译器,而是读取注释语法。 在该模式下,别名会解析为其自身名称,而不是它所代表的受众群体。 将 CLI 发出的有关此回退的警告视为必须修复的错误。
上下文参数必须有显式 RayfinContext<...> 注释。 类型生成通过该注释识别上下文参数。 没有它,该参数被视为请求体参数。
授予资源权限
对于当前的 Fabric 应用,应用身份是 Fabric 应用项目的所有者。 外部连接使用该身份及其权限,而非调用该功能的应用用户的身份或权限。
向应用身份授予 Functions 代码调用的每个资源和 API 所需的权限。 声明受众并部署 Functions 会注册令牌绑定,但不会授予对目标资源的权限。
资源代币留在服务器上。 绝不要把它们作为函数结果返回,也不要发送到前端。
应用登录和调用函数的授权与应用身份对外部资源的访问是分开的。
Rayfin 数据库标识
Rayfin 数据库使用独立的认证路径。
ctx.getDataClient() 使用调用的 Rayfin 令牌,因此数据库访问可以保留调用者的身份和数据库权限。 Functions 的应用程序身份验证不会将对 Rayfin DB 的访问切换为使用应用程序标识。
在 Azure SDK 中使用令牌
许多 Azure SDK 客户端需要的是 TokenCredential,而不是原始令牌字符串。 定义一个适配器,从上下文返回令牌:
import type { TokenCredential, AccessToken } from '@azure/identity';
class ContextTokenCredential implements TokenCredential {
constructor(private readonly token: string) {}
async getToken(): Promise<AccessToken> {
return {
token: this.token,
expiresOnTimestamp: Date.now() + 3600_000,
};
}
}
将 new ContextTokenCredential(ctx.Tokens.Storage) 或相应声明的令牌传递给需要凭据的 SDK 客户端。 在 rayfin/functions/package.json 中安装资源 SDK 包,而不是在项目根目录中安装。
在本地开发
npx rayfin dev并npx rayfin dev functions apply启动本地的 Azure Functions Core Tools 主机。 在本地 Functions 主机中,外部资源令牌使用的是应用生成器用来登录的账户的身份和权限。
已部署的函数则改为使用应用身份。 因此,成功的本地调用并不证明已部署的应用身份有权访问该资源。 在赋予应用身份所需权限后测试已部署的功能。