Power BI Embeded – Live connection SSAS RLS – ReadOverrideEffectiveIdentity

Cas de figure :

  1. Vous développez une application embarquant des éléments power BI, sur une capacité PowerBI Embeded / Premium
  2. Vous avez enregistré cette application sur un Azure Active Directory
  3. Vous utilisez un principal de service pour vous authentifier sur le service PowerBI depuis cette application
  4. Certains de vos rapports utilisent une connexion live sur un cube SSAS au travers d’une passerelle « Power BI Gateway »
  5. Votre cube implémente du RLS (Row level Security) et vous souhaitez depuis l’application transmettre l’EffectiveIdentity ou le CustomData (pas exemple pour le RLS)

Alors, vous devez donner à votre principal de service un droit spécifique sur la datasource représentant votre cube sur la gateway au sein du service PowerBI.

Ce droit s’intitule ReadOverrideEffectiveIdentity et sous-entend que votre application va prendre la main pour transférer elle-même l’effectiveIdentity ou le CustomData en bypassant le travail de la passerelle.

Ce droit ne peut-être octroyer que par un administrateur de votre locataire PowerBI et il peut l’être à un principal de service, un utilisateur ou un groupe de sécurité. L’action doit être réalisée via un appel aux API Power BI via l’action AddDataSourceUser.

Tout cela est détaillé et décrit dans la documentation fournie par Microsoft et l’API à utiliser est également documentée. Ayant éprouvé malgré tout quelques difficultés à réaliser cette étape voici un petit script Powershell et le détail sur chacun des paramètres requis :

#Import-Module -name microsoftpowerbimgmt
Connect-PowerBIServiceAccount
$headers = Get-PowerBIAccessToken

$gatewayId = ""
$dataSourceId = ""
$principalId = ""

#Get Existing rights
$URL = "https://api.powerbi.com/v1.0/myorg/gateways/$gatewayId/datasources/$dataSourceId/users"
$model = Invoke-RestMethod -Headers $headers -Uri $URL -Method GET
"Existing Rights : "
$model.value

#Set new rights for principal
$User1 = @{
  identifier= "$principalId"
  datasourceAccessRight= "ReadOverrideEffectiveIdentity"
  principalType="App"
} | ConvertTo-Json

try{
Invoke-RestMethod -Headers $headers -Uri $URL -ContentType 'application/json' -Method POST -Body $User1
}
catch {
    # Dig into the exception to get the Response details.
    # Note that value__ is not a typo.
    "catch"
    Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__ 
    Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
    ([System.IO.StreamReader]$_.Exception.Response.GetResponseStream()).ReadToEnd()    
}

Reste à obtenir les valeurs pour les 3 paramètres.

Les deux premiers $gatewayId et $datasourceId s’obtiennent directement en parcourant votre service powerbi. Rendez vous sur la gestion de vos passerelles, dépliez celle qui contient la datasource pointant vers le cube et cliquez sur celle-ci.

L’url contient désormais l’identifiant de la passerelle (la valeur à donner à $gatewayId) et celui de la source de données (la valeur à donner à $datasourceId)

Concernant le troisième paramètre, il s’agit de l’identifiant du service principal et c’est là qu’il ne faut pas se perdre faute de recevoir une exception peu bavarde du type « DMTS_PrincipalsAreInvalidError ».

Fin du suspense pour obtenir l’Id en question, rendez-vous sur le portail Azure et suivez ce chemin :

Azure Active Directory -> App Registration -> Votre application

Ensuite, cliquez à la pointe de la flèche :

Application sur la portail Azure

Cliquez ensuite sur Properties, l’id à utiliser est l’objectId présenté sur cette page de propriétés.

L’exécution du script powershell vous permettra alors d’octroyer les droits requis. Un compte administrateur doit être utilisé pour se connecter lorsque le script vous dirige vers la connexion à PowerBI.

PowerBI Report Server : Planifier le rafraîchissement des données via Script

L’API Rest de PowerBI Report Server

Suite au déploiement automatisé d’un rapport power BI vers le PowerBI Report Server (cf. PowerBI Report Server : Déployer et configurer un rapport via Script), une autre opération consiste à planifier le rafraîchissement du rapport.

A nouveau, nous pouvons faire appel à l’API Rest de PowerBI Report Server. Les planifications étant accessibles sur la route CacheRefreshPlans.

La planification

Pour créer une nouvelle planification, il s’agit d’utiliser sur cette route la méthode POST en lui fournissant un objet Json dont la structure est celle d’une planification.

Il faut y trouver :

  • Un propriétaire
  • Une description
  • L’élément à rafraîchir (représenté par son chemin virtuel)
  • Le type d’événement qui doit être DataModelRefresh
  • Une planification
  • Le cas échéants des valeurs pour les paramètres

Ce qui peut donner le script PowerShell suivant :

#Création de l'objet Json de planification
$payload = convertTo-Json (@{
"Owner" = "Domain\User";
"Description" = "Planification créée automatiquement"
"CatalogItemPath" = "/MonRapportPublie";
"EventType"="DataModelRefresh";
"Schedule" = @{"ScheduleID" = "";
"Definition" = @{
"StartDateTime" = "2018-11-14T16:00:00.00+02:00"
}
};
"ParameterValues" = @()
})


#Création de la planification sur le serveur
Invoke-WebRequest -Uri $powerBIReportsCacheRefreshPlansUri -Method POST -Body $payload -ContentType "application/json" -UseDefaultCredentials

Nous disposons désormais d’un rapport dont le rafraîchissement est planifié, la publication ayant été pilotée uniquement en PowerShell.

PowerBI Report Server : Déployer et configurer un rapport via Script

L’API Rest de PowerBI Report Server

Dans le cadre d’un industrialisation du serveur de rapport, il est utile de pouvoir déployer, configurer et planifier le rafraîchissement de rapports PowerBI de manière automatisée.

PowerBI Report Server est une version enrichie de SQL Server Reporting Services 2017.

Il est par conséquent possible d’utiliser la récente API REST de Reporting Services pour réaliser certaines opérations via Script. Elle se trouve par défaut à cet emplacement : http://<urlserver>/reports/api/v2.0

La documentation exhaustive de l’API s’obtient à partir du fichier swagger. Elle a été mise en forme à cette adresse : https://app.swaggerhub.com/apis/microsoft-rs/pbirs/2.0

Les exemples sont ici fournis en PowerShell, mais un proxy .Net peut être obtenu à partir du fichier Swagger pour manipuler l’API au travers d’un modèle objet.

Le déploiement

L’API présente notamment une route PowerBIReports qui permet d’obtenir la liste des rapports PowerBI publiés si on la requête en GET.

Pour déployer via Script, la logique est d’appeler cette Url en POST avec la bonne structure.

Voici un extrait de code PowerShell permettant le déploiement d’un rapport depuis un dossier vers le serveur de rapport :

#Déclaration des variables
$ReportPortalUri = 'http://localhost/reports'
$uploadItemPath = 'D:\Repository\MonRapport.pbix'
$destName = 'MonRapportPublie'


#Liste des rapports existants
$powerBIReportsUri = $ReportPortalUri + "/api/v2.0/PowerBIReports"
$res = Invoke-WebRequest -Uri $powerBIReportsUri -Method Get -UseDefaultCredentials


#Upload du rapport (en POST - échouera s'il existe déja)
$bytes = [System.IO.File]::ReadAllBytes($uploadItemPath)
$payload = @{
"@odata.type" = "#Model.PowerBIReport";
"Content" = [System.Convert]::ToBase64String($bytes);
"ContentType"="";
"Name" = $destName;
"Path" = '/';
} | ConvertTo-Json
Invoke-WebRequest -Uri $powerBIReportsUri -Method Post -Body $payload -ContentType "application/json" -UseDefaultCredentials | Out-Null

La méthode POST créé le rapport s’il n’existe pas et retourne une erreur s’il existe déjà. Dans ce deuxième cas, la méthode PATCH devra être préférée puisqu’elle permet la mise à jour.

Le rapport apparait désormais sur le portail.

La configuration

A la suite de la publication, une opération fréquente consiste à modifier la configuration du rapport, une chaine de connexion par exemple. Il est également possible d’automatiser cette opération.

Les chaines de connexion d’un rapport sont exposées dans les DataSources de ce rapport. Cette collection est accessible dans l’API suivant cette route : PowerBIReports($id)/DataSources

Le script suivant permet d’obtenir la liste des sources de données d’un rapport, dont on a récupéré précédemment l’identifiant, et de modifier les credentials associés

#Déclaration des variables
$id = ""
$ReportPortalUri = 'http://localhost/reports'
$powerBIReportsDataSourceUri = $ReportPortalUri + "/api/v2.0/PowerBIReports($id)/DataSources"


#Récupération des sources de données
$res = Invoke-WebRequest -Uri $powerBIReportsDataSourceUri -Method Get -UseDefaultCredentials
$content =convertFrom-json ($res.Content)
$datasources = $content.value


#Affectation des credentials dans les objets DataSource
Foreach($dataSource in $datasources)
{
$dataModelDatasource = $dataSource.DataModelDataSource
$dataModelDatasource.Username = "Domain\user"
$dataModelDatasource.Secret = "Mdp"
}
#la serialisation Json par défaut ne traite les tableaux que sur 2 niveaux, il faut donc la forcer à au moins 3
$payload = convertTo-Json -depth 3($datasources)


#Modification des datasources sur le serveur de rapport
Invoke-WebRequest -Uri $powerBIReportsDataSourceUri -Method PATCH -Body $payload -ContentType "application/json" -UseDefaultCredentials

Les informations d’authentification sont désormais modifiées.

A suivre : La création de la planification du rafraîchissement des rapports ainsi déployés