Azure Graph et Powershell, belle complémentarité

Lorsque l’on pense automatisation ou exploitation Azure, on pense forcément à Powershell (modules AZ) ou aux commandes CLI. Ce qui est effectivement une bonne idée.

Plus rarement, à Azure Graph et au langage Kusto (utilisé également pour les requêtes au travers des espace de travail log analytics Azure : https://www.microsoft.com/en-us/trust-center/privacy/data-access/?WT.mc_id=AZ-MVP-5003759).
Mais il existe une très belle complémentarité entre les 2. Car même si Powershell est performant, son utilisation sur de très gros environnement est parfois source d’une longue attente pour obtenir les résultats.

Attention, les 2 outils ont des utilisations communes (la lecture), mais une opération de suppression ou de création ne pourra se faire depuis Azure Graph. Graph est là uniquement pour des opérations de récupération d’informations. En général, les pré / post (l’état avant / après) pour de l’automatisation.

Un cas d’usage est par exemple la récupération de tags sur des milliers de ressources. C’est à dire une liste de tous les tags sur une ou plusieurs subscription Azure. Si cette opération est possible avec Powershell (Ou la CLI), elle peut parfois se révéler assez longue. Rien d’insurmontable lorsqu’il s’agit d’automatisation et donc de temps masqué (le script tourne en arrière plan sans bloquer l’activité), mais tout de même, pourquoi ne pas gagner en efficacité en couplant la puissance de Powershell et de Graph ?

Sans pour cela rentrer dans des opérations complexes pour joindre les deux langages puisque Powershell peut utiliser nativement Graph au travers du module Az.ResourceGraph : https://docs.microsoft.com/en-us/powershell/module/az.resourcegraph/?WT.mc_id=AZ-MVP-5003759

Voilà qui facilite l’intégration. Il est souvent préférable d’éviter les gymnastiques techniques (passage par des step intermédiaires = + de complexité) pour VRAIMENT gagner en efficacité. Même s’il est toujours assez amusant de faire fonctionner des services ou commandes qui ne sont pas fait pour nativement s’interfacer, un peu de simplicité est toujours la bienvenue !!

La langage Kusto dont il est question plus haut (que l’on trouve également sous la dénomination KQL) demande de passer un peu de temps sur le sujet mais donne tout de même rapidement de bons résultats. La documentation éditeur est fournie sur le sujet, riche d’exemples et de cas concrets. Il y a même dans le portail un Azure grand nombre de requêtes « sur étagère » depuis le menu Graph.

Avant d’aller plus loin dans le sujet et pour rassurer les personnes pour qui le code n’est pas une pratique courante, on peut utiliser efficacement Graph en connaissant seulement … 3 à 4 commandes. Un peu de sélection, un peu de filtrage et de l’affichage. Dans la démo qui va suivre, c’est à dire l’intégration Graph / Powershell, seules 2 commandes Graph sont utilisées. Un bon exemple de simplicité … efficace !

Pour illustrer la fonctionnalité, direction le portail Azure et le service Graph. Dans les requêtes prédéfinies, il est possible de compter le nombre de ressources Azure. Ici, une requête on ne peut plus simple avec une seule commande summarize.

Une requête existante disponible dans le portail.

Le résultat est instantané, avec sur mon abonnement 107 ressources. Mais sur des environnement avec plusieurs milliers de ressources (ou plusieurs dizaines de milliers), le temps ne dépasse jamais les 3 ou 4 secondes.

Ici déjà, une différence majeure avec Powershell. La portée de la requête. Elle peut être lancée au niveau de l’annuaire, des groupes d’administration ou des abonnements. Avec des cases à cocher pour faciliter les sélections multiples.

La porté des requêtes.

Celles et ceux qui ont déjà « jonglé » entre les contextes avec Powershell comprennent déjà ce que peut apporter Graph.

Pour revenir à cette courte requête, la résultat parait incomplet puisque le détail n’affiche qu’une seule donnée, 107.

Summarize et count()

Ce qui est normal, summarize est un opérateur d’agrégation. Ici, avec la fonction count(), il ne fait que compter les résultats.

Pour une requête détaillée, mais non filtrée, c’est à dire la plus large des requêtes Graph, on utilise simplement Resources.

Resources, la commande la plus large qui soit !

Entre ces deux extrêmes, il existe (heureusement) de multiples possibilités. Une autre requête dans le menu est l’affichage de toutes les machines virtuelles classées par nom.

Une requête un peu plus fine.

Voilà qui commence à être plus intéressant. Après le Summarize de la première requête, quelques commandes complémentaires. Project (ou affiche), Where et Ordrer. Ce qui présente le plus d’intérêt pour cette démo est le Where qui va filtrer la recherche et afficher les ressources de type Microsoft.Compute/virtualMachines.

Il y a beaucoup à faire avec les requêtes existantes présentes sur le portail. Comme elle ne modifient pas les ressources, aucun risque de tester et de comparer les retours. C’est un bon point de départ, modifier une requête existante n’aura aucun impact négatif sur les ressources, une requête non conforme remontera uniquement une erreur.

Puisqu’il était question dans l’introduction de n’utiliser que 3 ou 4 commandes pour traiter le cas des tags de machines virtuelles, voilà une requête Graph qui va récupérer toutes les VM d’un abonnement de production pour lesquelles le tag Env : Prod n’est pas positionné. Du concret donc. Du Where sur le type de ressources et la valeur du tag, et une recherche d’une valeur isnull().

Resources
| where type =~ 'Microsoft.Compute/virtualMachines'
| where isnull(tags.Env) 

Ici, ce sont toutes les ressources de type virtualMachines pour lesquelles il n’existe pas de tag Env.

Cette requête est prête à être utilisée (ou presque). Que se passe t il maintenant du côté de Powershell. La consultation de l’aide des commandes donne un exemple d’ajout de tags pour une ressource Azure (https://docs.microsoft.com/en-us/powershell/module/az.resources/new-aztag?view=azps-7.2.0#example-6–creates-or-updates-the-entire-set-of-tags-on-a-resource/?WT.mc_id=AZ-MVP-5003759).

$Tags = @{"Dept"="Finance"; "Status"="Normal"}
New-AzTag -ResourceId /subscriptions/{subId}/resourcegroups/{rg}/providers/Microsoft.Sql/servers/Server1 -Tag $Tags

Deux paramètres seulement pour ajouter des tags. Le couple nom / valeur (stocké dans la variable $Tags dans l’exemple ci dessus) et la valeur -ResourceId qui est une valeur unique pour chaque ressources existantes du côté d’Azure.

C’est ici que la complémentarité va être expliquée. Sur mon abonnement qui ne compte que 107 ressources et assez peu de VM, l’utilisation de Powershell sans Graph aurait été suffisante, la différence de mperformance sur de petits environnements est moins significative…. même si prendre l’habitude d’utiliser le couple PS / Graph est une bonne pratique.

Chez un client de taille moyenne ou plus, il faut absolument utiliser le couple Graph / Powershell pour améliorer l’efficacité. L’intérêt dans cet exemple est d’utiliser Graph pour ce qu’il fait à merveille (la lecture des ressources et le détail des ressources à une vitesse inégalable) et de basculer le résultat dans la commande Powershell.

De retour sur la requête Graph, l’affichage des détails du résultat donne les informations suivantes.

Les informations détaillées pour une VM qui n’est pas dans l’état de tags désiré.

id … c’est tout à fait le champ qu’il faut utiliser dans la commande Powershell (que l’on trouve côté PS sous la forme -ResourceId ). Le module Powershell Az.ResourceGraph présenté une peu plus haut est un module qui « encapsule » une requête Graph dans une commande Powershell. De la plus simple des façons.
Ainsi, la version Graph

Resources
| where type =~ 'Microsoft.Compute/virtualMachines'
| where isnull(tags.Env)

devient

Search-AzGraph "Resources
| where type =~ 'Microsoft.Compute/virtualMachines'
| where isnull(tags.Env)"

dans le module Powershell.

Reste donc à affiner la requête pour récupérer l’id …

l’id des ressources sans tag Env.

… et à passer les commandes de création des tags

Graph + Powershell en action.

Sur de grands environnements, la différence sur le temps de traitement est énorme ! Et il n’a fallut que deux paramètres Graph pour constituer la requête. Le Where et le Project.

Attention, le langage utilisé est très complet (et parfois complexe), mais il autorise des opérations beaucoup plus avancées que Powershell. Effectivement, certaines ressources sont délicates à gérer avec Powershell. Par exemple, le service de Backup, Recovery Services Vault pour lequel un contexte doit être créé (en + du contexte de la sub). Puis les commandes sont lancées dans chaque contexte. Graph sera là aussi très utile, puisqu’il sera possible de réaliser des jointures qui rendent beaucoup plus facile l’exploitation de ce type de ressources.

Il n’y a pas ou peu de limite à l’utilisation du couple Graph / Powershell, à essayer au + tôt !