前言
报表的访问权限管理不仅仅只是添加或删除用户对报表的访问权限,还需要维护可访问用户的名单,以便在报表被意外删除或需要进行迁移时,能够快速且完整的恢复用户的访问权限。
虽然采用手工维护的方式也可以达到同样效果,但工作区中报表数量较多的话,维护起来肯定是非常不方便的,因此本篇文章将介绍使用PowerBI REST API的方案来自动化获取与更新工作区中各报表的可访问用户名单。
方案介绍
总体方案如下:
1、调用REST API获取指定工作区中的所有报表
2、调用REST API获取每个报表的可访问用户列表并汇总
3、使用PowerQuery完成上述操作
4、新建PowerBI数据流,运行PowerQuery的相应代码,并设置计划刷新,定时刷新数据流
5、若需要备份历史数据,则可以将数据流替换为数据集,并使用PowerAutomate从数据集中查询数据并进行备份
相信任意一个具有发送http请求的编程语言都可以完成上述操作,但困难的地方则是要保证脚本的持续运行。由于服务器环境不易获取,因此在该方案中采用PowerBI数据流或数据集来代替服务器环境,既保证了脚本的持续运行,也大大提高了方案的易用性,同时数据流或数据集都可以与报表放在同一个工作区中,也比较方便管理。
REST API接口介绍
获取指定工作区中的所有报表
API接口:
Url:https://api.powerbi.com/v1.0/myorg/groups/{groupId}/datasets
Method:GET
Request Headers: {Authorization:访问令牌}
Sample Response:
{
"value": [
{
"id": "cfafbeb1-8037-4d0c-896e-a46fb27ff229", // 报表对应的数据集ID
"name": "SalesMarketing",
"addRowsAPIEnabled": false,
"configuredBy": "john@contoso.com",
"isRefreshable": true,
"isEffectiveIdentityRequired": false,
"isEffectiveIdentityRolesRequired": false,
"isOnPremGatewayRequired": false
},
{
"id": "azwfbeb1-8037-4d0c-896e-a46fb27aw229",
"name": "ProductOps",
"addRowsAPIEnabled": false,
"configuredBy": "john@contoso.com",
"isRefreshable": true,
"isEffectiveIdentityRequired": false,
"isEffectiveIdentityRolesRequired": false,
"isOnPremGatewayRequired": false
},
...
]
}
参数说明:
groupId指的是工作区ID,打开工作区后,可以在浏览器上方地址栏处获得,具体如下图所示:
获取指定指定报表的可访问用户列表
API接口:
Url:https://api.powerbi.com/v1.0/myorg/groups/{groupId}/datasets/{datasetId}/users
Method:GET
Request Headers: {Authorization:访问令牌}
Sample Response:
{
"value": [
{
"identifier": "john@contoso.com",
"principalType": "User",
"datasetUserAccessRight": "Read"
},
{
"identifier": "154aef10-47b8-48c4-ab97-f0bf9d5f8fcf",
"principalType": "Group",
"datasetUserAccessRight": "ReadReshare"
},
{
"identifier": "3d9b93c6-7b6d-4801-a491-1738910904fd",
"principalType": "App",
"datasetUserAccessRight": "ReadWriteReshareExplore"
}
]
}
参数说明:
groupId指的是工作区ID,datasetId指的是报表对应的数据集的ID,打开工作区后,可以在浏览器上方地址栏处获得,具体如下图所示:
访问令牌的获取
在调用REST API时需要访问令牌,关于获取访问令牌的具体步骤与原理,请参考我的另一篇文章:Azure应用注册与访问令牌获取,并从该文章末尾处复制给出的现成代码,然后填写相关参数即可。注意:需要给Azure应用授予PowerBI Services的Dataset.ReadWrite.All权限。
如果只是临时获取报表的可访问用户列表,不需要自动化维护,即不需要自动更新的,那么访问令牌也可以从浏览器调试控制台中获取。
具体方案如下:
1、按F12打开控制台,然后在Network选项卡下的Fetch/XHR类别下找到任意一个请求
2、然后在Request Headers类别下找到Authorization属性,该属性值即为访问令牌
需要注意的是,从浏览器调试控制台中获取的访问令牌具有时效性,过一段时间后访问令牌将失效。因此若想达到自动化更新运维的效果,则需要走正经渠道来申请访问令牌。
使用PowerQuery获取报表的可访问用户列表
核心代码如下:
let
WorkspaceID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", // 工作区ID
Token = "Bearer eyJ0eXAiOiJKV1XXXXXXXXXXXXXXXXXXXXXXXX", // 访问令牌
GetDatasetIds = Table.FromRecords(Json.Document(Web.Contents("https://api.powerbi.com",[Headers=[Authorization=Token],RelativePath="v1.0/myorg/groups/"&WorkspaceID&"/datasets"]))[value])[[id],[name]],
fx=(WorkspaceID,DatasetID)=>let
Url = Text.Format("v1.0/myorg/groups/#{0}/datasets/#{1}/users",{WorkspaceID,DatasetID}),
Result = Table.FromRecords(Json.Document(Text.FromBinary(Web.Contents("https://api.powerbi.com",[Headers=[Authorization=Token],RelativePath=Url])))[value])
in Result,
Result = Table.ExpandTableColumn(Table.AddColumn(GetDatasetIds,"User",each fx(WorkspaceID,[id])), "User", {"datasetUserAccessRight", "identifier", "principalType"}),
#"Renamed Columns" = Table.RenameColumns(Result,{{"id", "datasetId"}, {"name", "reportName"}})
in
#"Renamed Columns"
在核心代码的基础上增加获取访问令牌部分,即可得到完整的代码,申请访问令牌时以主用户模式为例,完整代码如下:
let
// ------------------------------------------------config setting-----------------------------------------------------
// Client Id (Application Id) of the AAD app
CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
// Master user email address.
USER_ACCOUNT = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
// Master user email password.
USER_PASSWORD = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
// ------------------------------------------------config setting end-------------------------------------------------
Token =
let
SCOPE_BASE = "https://analysis.windows.net/powerbi/api/.default" ,
AUTHORITY_URL = "https://login.microsoftonline.com/organizations/oauth2/v2.0/token" ,
RESPONSE =
Web.Contents(
AUTHORITY_URL,
[
Headers = [#"Content-Type"="application/x-www-form-urlencoded"],
Content =
Text.ToBinary(
Text.Format(
"client_id=#{0}&scope=#{1}&username=#{2}&password=#{3}&grant_type=password",
{CLIENT_ID,SCOPE_BASE,USER_ACCOUNT,USER_PASSWORD}
)
)
]
)
in
"Bearer " & Json.Document(RESPONSE)[access_token],
// -------------------------------------------Call REST API by above Token--------------------------------------------
// CallAPI = xxxxx
WorkspaceID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxx",
GetDatasetIds = Table.FromRecords(Json.Document(Web.Contents("https://api.powerbi.com",[Headers=[Authorization=Token],RelativePath="v1.0/myorg/groups/"&WorkspaceID&"/datasets"]))[value])[[id],[name]],
Result =
Table.ExpandTableColumn(
Table.AddColumn(
GetDatasetIds,"User",each let
Url = Text.Format("v1.0/myorg/groups/#{0}/datasets/#{1}/users",{WorkspaceID,[id]}),
Result = Table.FromRecords(Json.Document(Text.FromBinary(Web.Contents("https://api.powerbi.com",[Headers=[Authorization=Token],RelativePath=Url])))[value])
in Result
),
"User",
{"datasetUserAccessRight", "identifier", "principalType"}
),
#"Renamed Columns" = Table.RenameColumns(Result,{{"id", "datasetId"}, {"name", "reportName"}})
in
#"Renamed Columns"
以下是运行上面代码后的示例结果:
新建数据流自动更新可访问用户列表
1、打开工作区,并选择新建数据流选项
2、选择定义新表选项
3、在跳转页面中选择空白查询选项,并将之前编写好的PowerQuery代码粘贴进来,然后点击下一步
4、配置连接凭据,默认匿名连接即可,然后点击右下角的保存并关闭,完成数据流的创建
5、回到工作区界面,找到刚创建的数据流,点击名称隔壁的三个点,然后选择设置
6、配置计划刷新。可以将刷新时间定在凌晨,这样可以保证白天报表出问题后可以使用最新数据进行恢复
7、至此,所有内容都已配置完成,工作区中的所有报表的可访问用户列表将在数据流中进行存储与更新。
总结
通过本文给出的方案,可以自动化获取与更新工作区中各报表的可访问用户名单,在发生意外的情况下也可以快速且完整的恢复用户的访问权限。
天有不测风云,谁也不知道意外与明天哪个会更先到来,因此做好各种灾备机制是很有必要的。