Supplies are limited. Contact info@espc.tech right away to save your spot before the conference sells out.
Get your discountScore big with last-minute savings on the final tickets to FabCon Vienna. Secure your discount
My end goal is to find all RLS setting used in a Power BI Dataset and to see which AD groups have been connected to these roles. To do this, I have followed the GetScanResult API, and have implemented this in a PySpark Notebook inside of Azure Synapse.
According to this page, there should be a dictionary with the key "Roles", but in my response of the API there is no such field. This is what I am looking for:
Goal output:
......
"roles": [
{
"name": "Teams",
"modelPermission": "Read",
"members": [
{
"memberName": "john@contoso.com",
"memberId": "ee96296b-fb71-4f65-a8af-c0ec5a7daced",
"memberType": "User",
"identityProvider": "AzureAD"
},
{
"memberName": "group@contoso.com",
"memberId": "0a1cdbc3-f82c-4001-8b96-be04ae9d25a3",
"memberType": "Group",
"identityProvider": "AzureAD"
}
],
"tablePermissions": [
{
"name": "DW_Revenues DW_RevenuesTest",
"filterExpression": "[InTeams] = \"True\""
}
]
}
],
......
However, this is the entire response I get (when I select one of the datasets that the API call):
[
{
"id":"--------------",
"name":"--------------",
"tables":[
],
"configuredBy":"--------------",
"configuredById":"--------------",
"isEffectiveIdentityRequired":true,
"isEffectiveIdentityRolesRequired":true,
"refreshSchedule":{
"days":[
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
],
"times":[
"01:00",
"08:00",
"09:00",
"10:00",
"11:00",
"13:00",
"14:00",
"15:00",
"16:00",
"17:00"
],
"enabled":true,
"localTimeZoneId":"Romance Standard Time",
"notifyOption":"NoNotification"
},
"targetStorageMode":"PremiumFiles",
"createdDate":"2022-12-08T12:22:43.013",
"contentProviderType":"PbixInImportMode"
}
]
As can be seen, the "Tables" dictionary only contains an empty list (which is different from the example output of GetScanResult), but also the "Roles" field is missing.
Things I have tried:
1. Checked the tenant settings to ensure metadata scanning has been enabled (info), I was hoping the settings were turned off and causing this issue, but they were turned on
2. Specified parameters in the getInfo Post API call:
def initiate_scan(aad_token, workspaces):
url = 'https://api.powerbi.com/v1.0/myorg/admin/workspaces/getInfo'
headers = {
'Authorization': f'Bearer {aad_token}',
'Content-Type': 'application/json'
}
body = {
"workspaces": workspaces,
"datasetExpressions": True,
"datasetSchema": True,
"datasourceDetails": True,
"getArtifactUsers": True,
"lineage": True
}
response = requests.post(url, headers=headers, json=body)
if response.status_code == 202:
scan_id = response.json().get('id')
print(f'Scan initiated successfully. Scan ID: {scan_id}, workspaceIDs = {body["workspaces"]} ')
return scan_id
else:
print(f'Failed to initiate scan: {response.status_code}, {response.text}')
return None
3. Tried a different API Call looking something like this: 'https://api.powerbi.com/v1.0/myorg/admin/datasets/{dataset_id}, this results in:
Failed to get dataset info: 404, {"error":{"code":"ItemNotFound","message":"Dataset abcde-12345-12345-abcde is not found."}}.
Additional Information
1. I am using an AAD token which I obtain in the following way:
def get_AAD_token(tenant_id, client_id, client_secret, resource):
token_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/token"
data = {
'grant_type': 'client_credentials',
'client_id': client_id,
'client_secret': client_secret,
'resource': resource
}
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
response = requests.post(token_url, data=data, headers=headers)
if response.status_code == 200:
json_response = response.json()
aad_token = json_response['access_token']
print('Bearer token was obtained successfully')
return aad_token
else:
print(f'Failed to obtain bearer token: {response.status_code}, {response.text}')
return None
2. I am a noob when it comes to Permissions and rights granted via Azure Synapse and this universe in general
3. I think it has something to do with rights, since in the example output there is info about tables and roles
4. I have checked this page
4.1 I have checked this page
5. I have read to wait a bit between starting the scan and reading the scan, I check for the status to be "Succeeded" before getting the results.
6. I Have ensured roles have been set for the dataset I am checking
7. In short, this is my code:
def initiate_scan(aad_token, workspaces):
url = 'https://api.powerbi.com/v1.0/myorg/admin/workspaces/getInfo'
headers = {
'Authorization': f'Bearer {aad_token}',
'Content-Type': 'application/json'
}
body = {
"workspaces": workspaces,
"datasetExpressions": True,
"datasetSchema": True,
"datasourceDetails": True,
"getArtifactUsers": True,
"lineage": True
}
response = requests.post(url, headers=headers, json=body)
if response.status_code == 202:
scan_id = response.json().get('id')
print(f'Scan initiated successfully. Scan ID: {scan_id}, workspaceIDs = {body["workspaces"]} ')
return scan_id
else:
print(f'Failed to initiate scan: {response.status_code}, {response.text}')
return None
def check_scan_status(aad_token, scan_id):
url = f'https://api.powerbi.com/v1.0/myorg/admin/workspaces/scanStatus/{scan_id}'
headers = {
'Authorization': f'Bearer {aad_token}',
'Content-Type': 'application/json'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
status_info = response.json()
status = status_info.get('status')
print(f'Scan status: {status}')
return status, status_info
else:
print(f'Failed to check scan status: {response.status_code}, {response.text}')
return None, None
def get_scan_result(aad_token, scan_id):
print(f"collecting results for scan {scan_id}")
url = f'https://api.powerbi.com/v1.0/myorg/admin/workspaces/scanResult/{scan_id}'
headers = {
'Authorization': f'Bearer {aad_token}',
'Content-Type': 'application/json'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
scan_result = response.json()
print('Scan result retrieved successfully')
return scan_result
elif response.status_code == 404:
print(f'Scan result not found. The scan may have expired or the ID is invalid: {response.text}')
return None
else:
print(f'Failed to get scan result: {response.status_code}, {response.text}')
return None
Any help is greatly appreciated
Hi @sybrenmool ,
Regarding your use of this Power BI admin API you will also encounter the specific 404 error status code "404, {"error":{"code": "ItemNotFound", "message": "Dataset abcde-12345-12345-abcde is not found."}}." At your convenience, can you verify that the account you generated and used the AAD token for has access to the dataset ID "abcde-12345-12345-abcde"? You can also consider using service principal authentication to execute this API, provided that you also meet the prerequisites of the API for service principals in the documentation.
Admin - Datasets GetDatasetsAsAdmin - REST API (Power BI Power BI REST APIs) | Microsoft Learn
Best Regards,
Liu Yang
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.
User | Count |
---|---|
10 | |
5 | |
4 | |
4 | |
3 |
User | Count |
---|---|
14 | |
9 | |
5 | |
5 | |
4 |