PI Services

Le blog des collaborateurs de PI Services

Powershell : Introduction à la gestion d'événements

Introduction

Le thème abordé est la gestion d'événements sous Powershell. Il s'agit d'une notion peu connue dans ce langage de scripting mais permettant d'interagir automatiquement avec le système si un événement est détecté. Ceux-ci peuvent être : 

  • Le démarrage d'un process
  • Un changement sur un dossier
  • La fin d'un timer
  • Un changement d'état dans un job Powershell
  • ...

Dans un premier, nous verrons comment connaître les objets pouvant être observés et comment gérer les événements via la Cmdlet Register-ObjectEvent, ensuite nous traiterons le cas particulier des événements WMI, puis celui des événements liés à la console Powershell. Enfin, un exemple d'utilisation sera montré (détection des changements dans un dossier).

Avant de débuter, il faut savoir que les événéments gérés, ne le sont que dans la session Powershell en cours (c'est à dire que la remontée d'événements s'arrête dès qu'on quitte la session Powershell). Il existe toutefois une méthode pour créer une gestion d'événements permanente, mais elle ne fonctionne que pour les événements en WMI. Pour faciliter sa mise en place, je vous invite à vous tourner vers l'excellent module PowerEvents : http://powerevents.codeplex.com/.

Les événements des objets Powershell

Pour connaître si un objet Powershell peut être géré via des événements, il suffit d'utiliser la commande Get-Member.

En exécutant la commande suivante :

 

Il est aussi possible de les obtenir via la méthode GetEvents :

 

On obtient le résultat :

image

On remarque que 2 de ces membres sont de type Event (Elapsed et disposed). Ces derniers vont donc pouvoir être utilisé via la cmdlet Register-ObjectEvent.

Exemple pour l’événement Elapsed (fin d’un timer) :

Lorsque l'on lance cette commande, elle crée un job Powershell (similaire à ceux lancés par la commande Start-Job). Dans cet exemple nous voulons monitorer la fin d'un timer pour récupérer les données transmises par un job Powershell à chaque seconde. On crée un objet de type Timer qui a un interval de 1 seconde (en millisecondes). Ce dernier tourne en boucle grâce à l'attribut autoreset. L'événements à surveiller est "Elapsed". On le retrouve dans la commande Register-ObjectEvent avec le paramètre EventName. Le paramètre Action définit le processus exécuté lorsque l'événment est détecté. Il s'agit d'un scriptblock (entre accolades, ici notre variable “ActionTimer”).

Il est possible de passer des données pour qu'elles soient traiter dans l'action. Cela se fait via le paramètre MessageData (N'importe quel type d'objet peut être consommé). Ces données sont ensuite accessible via la variable $event.MessageData. Nous récupérons donc la propriété Id de l'objet Job Powershell afin de recevoir les données via la commande Receive-Job. Pour que l'événement soit remonté , il est obligatoire de fournir l'objet Timer en tant qu'InputObject. Enfin, SourceIdentifier est simplement le nom du job.

Si l'on souhaite arrêter d'observer les événements d'un objet Powershell, il faut utiliser la commande Unregister-ObjectEvent conjointement à Get-EventSubscriber qui récupère l'ensemble des événements observés.

 

Cette commande arrête la remontée de tous les événements. On peut bien entendu filtrer les événements à ne plus gérer via la cmdlet Where-Object par exemple.

Les événements en WMI

En WMI, il existe de nombreuses classes WMI permettant la gestion d'événements. Pour toutes les récupérer et retrouver celle qui vous intéresse, utilisez cette commande :
 

On remarque entre autre des classes pour récupérer :

  • les changements dans les clés de registre
  • les démarrages et arrêts de processus
  • l'arrêt ou la fermeture de session d'un utilisateur
  • l'ajout d'un lecteur (disque dur, clé usb)
  • ...

Pour surveiller un événements en WMI on utilise cette fois la commande Register-WMIEvent.

Exemple de détection de lancement d'un nouveau processus :

La requête effectue une recherche toutes les 2 secondes sur la classe __InstanceCreationEvent. Elle est basé sur le langage WQL dont on peut retrouvé la syntaxe sur le lien suivant :
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394606(v=vs.85).aspx

On retrouve les paramètres sourceIdentifier et Action vues précédemment avec la commande Register-ObjectEvent.

Les événements de la console Powershell

On peux écouter deux événements sur la console Powershell. Lorsqu'elle est fermée (Exiting) et lorsqu'elle est en état Idle (OnIdle). Ainsi, on peut exécuter des actions quand l'un de ces états est atteint. Cette opération s'effectue via la commande Register-EngineEvent :

 

La syntaxe est semblable à celle de la commande Register-ObjectEvent sauf que c'est le paramètre SourceIdentifier qui contient le non de l'événement (on aura donc 2 SourceIdentifier possibles : Powershell.Exiting et Powershell.OnIdle).

NB : Depuis Powershell 3.0, un troisième événement semble exister : WorkflowJobStartEvent. Cependant, il n'est à l'heure actuelle (au 23/05/2014) pas documenté.

Exemple d'utilisation :

Le script commenté ci-dessous déplace les fichiers d'un répertoire à un autre lorsqu'un nouveau fichier apparaît. Un premier événement sur l'objet de type FileSystemWatcher est récupéré : Created. Lors de la remontée de cet événement (à chaque création de fichier) le chemin du fichier est retourné. Un second objet de type Timer est surveillé. A chaque seconde, il récupère les résultats du Job précédent (les chemins de fichiers). Il les ajoute à une liste puis il traîte cette liste en essayant de déplacer les fichiers. Deux résultats sont alors possibles :

  • Si le transfert réussi, alors le chemin initial est supprimé de la liste des fichiers à transférer.
  • Si le déplacement échoue (fichier en cours d'écriture par exemple) alors il retentera de le déplacer au prochain déclenchement de l'événement (après 60 tentatives le transfert n'est plus réalisé).

Les différentes opérations sont logguées dans l'observateur d'événements.

NB : Si le fichier existe déjà à la destination, un horodatage est ajouté en suffixe du nom du fichier.

Desired State Configuration (Partie 4) : Configuration du mode pull (via web service)

Introduction

Cet article fait partie d’une série de 5 billets sur Desired State Configuration :

Desired State Configuration est disponible comme Powershell 4.0 sur Windows 2012 R2/8.1, Windows 2012/8 et Windows 2008 R2/7.

Lors du précédent article nous avons vu le fonctionnement du mode Pull puis son implémentation. Cette dernière se base sur un partage SMB permettant à tous les clients d'aller récupérer leur configuration par ce biais.

Dans cette quatrième partie, nous aborderons l'implémentation du mode Pull via un web service.

Fonctionnement

Le fonctionnement du mode Pull est expliqué dans la Partie 2 de ce guide sur DSC. Dans le mode Pull via web services, seul la façon de publier les fichiers de configurations et l'implémentation changent. Au lieu d'utiliser un partage, les clients DSC interrogerons à intervalle régulier une URL pour récupérer leur configuration :
http://PullServerName:8080/PSDSCPullServer/PSDSCPullServer.svc" où PullServerName représente le nom du serveur Pull.

Contrairement au mode Pull via partage SMB, il n'est possible de déployer le Web Services que sur une version Serveur de Windows. Celui-ci se base sur la fonctionnalité Windows Powershell Desired State Configuration Service. Cependant, via le web service, il est possible de sécuriser la connexion avec l'usage de certificat.

Nous retrouvons les mêmes étapes que pour un serveur Pull via partage. Les clients ont un GUID unique de configuration. Ils récupèrent le fichier .mof portant ce GUID. Une vérification d'intégrité du fichier est effectuée grâce à un fichier portant le même GUID avec l'extension .mof.checksum.

Implémentation du web service

Dans cette section, j'explique comment mettre en place un serveur Pull avec Web Service de façon manuelle afin de comprendre les différentes briques de cette fonctionnalité. Dans le dernier paragraphe, vous trouverez des liens vers des ressources Desired State Configuration permettant de réaliser toute cette configuration beaucoup plus rapidement.

Tout d'abord, on installe le service DSC en graphique ou via la commande :

Install DSC Service

Toute une série de dépendance est ainsi installée dont notamment IIS et le Windows Process Activation Service.

Capture d_écran 2014-04-20 à 11.52.16

Puis dans IIS, on crée un nouveau pool d'application (DSCApplicationPool) qui sera lancé avec le compte Local System (Sur le pool d’application choisir “Advanced Settings” puis “Identity”).

Add PoolConfigure Pool

On crée un nouveau site (Exemple : DSCPullSite) utilisant notre pool d’application nouvellement créé et on le fait pointer vers un dossier de son choix. Ce dernier contiendra les sources du web service.

Add Site

Dans le dossier du site web IIS, on crée un répertoire bin dans lequel on copie le fichier Microsoft.Powershell.DesiredStateConfiguration.Service.dll contenu dans $pshome/modules/psdesiredstateconfiguration/pullserver ($pshome correpond à C:\Windows\System32\WindowsPowerShell\v1.0 si vous avez une installation classique de Windows). 

Il faut ensuite copier les fichiers suivants contenu dans le dossier  $pshome/modules/psdesiredstateconfiguration/pullserver à la racine du site web :

  • Global.asax 
  • PSDSCPullServer.mof 
  • PSDSCPullServer.svc 
  • PSDSCPullServer.xml 
  • PSDSCPullServer.config : il doit être renommé en web.config

L'arborescence doit être identique à celle ci-dessous :

Arborscence

Il faut ensuite autoriser les différentes méthodes d'authentification en réalisant un "unlock" sur les sections adéquate du fichier web.config que nous avons copié (anciennement PSDSCPullServer.config).

Voici un script permettant de réaliser cette opération :

Le résultat peut être vérifié dans le fichier C:\Windows\System32\inetsrv\config\applicationHost.config 

web.config

Enfin, dans ce même fichier web.config il faut ajouter les lignes suivantes dans le noeud appsettings :

Lors de l'installation du service DSC, une hiérarchie de dossier a été créée dans C:\Program Files\WindowsPowerShell\DscService :

  • Configuration : dans ce dossier, il faut placer les fichiers .mof et .mof.checksum (renommé avec un GUID, voir Partie 2).
  • Modules : Contient les éventuels modules dont on pourrait avoir besoin.

Pour terminer la configuration du serveur Pull, il faut copier le fichier $pshome/modules/psdesiredstateconfiguration/pullserver/Devices.mdb vers le dossier C:\Program Files\WindowsPowerShell\DscService

L'url du web service (http://PullServerName/PSDSCPullServer.svc) est maintenant opérationnelle !

Ressource LocalConfigurationManager

La ressource LocalConfigurationManager (déjà rencontrée dans les autres articles sur DSC) doit être configurée pour utiliser le web service.

Cette configuration est similaire à celle de la Partie 2 et 3. On retrouve le ConfigurationID permettant de récupérer les bons fichiers .mof. Les paramètres à changer sont :

  • DownloadManagerName : Il prend la valeur WebDownloadManager. 
    DownloadManagerCustomData : Il contient un hashtable avec l'url du web service et un second paramètre AllowUnsecureConnection utile si vous n'utilisez pas de certificat.
Voici une configuration d'exemple :

Annexe

Depuis la sortie de Powershell V4.0, Microsoft s'est employé à fournir de nombreuses nouvelles ressources pour DSC. Celles-ci sont disponibles en suivant le lien ci-dessous :
http://gallery.technet.microsoft.com/scriptcenter/DSC-Resource-Kit-All-c449312d

Ces ressources sont précédées d'un "x" car elles sont encore considérées comme expérimentales. Parmis toutes ces nouvelles ressources (plus d'une cinquantaine !), il y en a une pour déployer un server Pull facilement (xDscWebService). Cette dernière permet d'effectuer toutes les opérations fastidieuses que l'on a mis en place dans la section précédente (création d'un pool d'application, d'un site web, copie des différents fichiers,...).

Voici un exemple d'utilisation de cette ressource :

On retrouve les paramètres tel que le nom du pool d'application (EndpointName), le chemin vers le site web (PhysicalPath),... Cela nous permet aussi de pouvoir customiser simplement les chemins qui vont contenir nos fichiers .mof et .mof.checksum ainsi que les ports utilisés par DSC et l'intégration d'un certificat.