Donnez un petit boost à vos ADR avec les Règles de Filtre d’Etat et PowerShell

Introduction

MEMCM offre déjà beaucoup de fonctionnalités pour aider les administrateurs systèmes à automatiser de nombreux processus leur permettant de gagner beaucoup de temps pour boire plus de café☕ travailler sur des tâches moins mondaines et plus intéressantes.

Parmi elles, il y a les Règles de Déploiement Automatiques (Automatic Deployment Rules – ADR) qui permettent l’automatisation du patch management pour les appareils Windows. Il existe aussi les Règles de Filtre d’État qui permettent d’exécuter des actions (Lancer un programme, exécuter un script…) quand des messages d’état spécifiques sont traités par le serveur de site.

Si on mélange ces deux fonctionnalités et qu’on y ajoute un peu de scripting PowerShell, nous pouvons en faire alors bien plus. Donc, allons-y, et donnons un petit boost à vos ADR avec les Règles de Filtre d’État et PowerShell !

Messages d’État et Règles de Filtre d’État, que sont-ils ?

Messages d’état

Avant de jeter un œil aux Règles de Filtre d’État, il est bon de savoir ce que les messages d’état sont dans Configuration Manager. Les messages d’état sont des messages informatifs générés par les divers composants de MEMCM pour indiquer aux administrateurs leur santé et leurs actions. Ils sont similaires aux événements Windows dans le sens qu’ils ont eux aussi différents attributs comme une classification de sévérité, un ID ou une description.

Par exemple, quand une application est créée, un message d’état est généré. Si un Point de Distribution échoue dans le traitement d’un contenu, un message d’état est généré. Ou si un regroupement a été supprimé par quelqu’un, un message d’état est aussi généré. Il y a quelques centaines de messages d’état différents qui peuvent être générés dans un environnement MEMCM quand quelque chose se passe. Pour vous aider à trouver celui que vous désirez, une liste des différents messages d’état est disponible sur GitHub.

Règles de Filtre d’État

Les Règles de Filtre d’État vous permettent de déclencher une action à chaque fois qu’un message d’état remplit des critères que vous avez défini avec des filtres. Simple, mais très efficace.

Elles sont créées depuis Administration > Vue d’ensemble > Configuration du site > Sites. Effectuez un clic droit sur le site désiré et sélectionnez Règles de Filtre d’État pour ouvrir la liste des règles préexistantes et pour pouvoir créer, modifier ou supprimer vos propres règles.

Status-Filter-Rules

Depuis cette liste, vous devez donner un nom à votre règle et vous pouvez sélectionner différents critères de filtre qui, s’ils sont remplis, déclencheront les actions de la règle que vous aurez sélectionnées dans la fenêtre suivante de l’assistant. Mais nous verrons ça un peu plus tard.

Il existe également de nombreuses cmdlets PowerShell qui permettent de travailler avec les Règles de Filtre d’État. Vous pouvez trouver plus d’informations sur le sujet sur le site Microsoft Docs.

La dernière information importante sur les Règles de Filtre d’État est qu’elles permettent d’utiliser des variables que vous pouvez passer comme paramètres quand vous appelez un programme. Pour une liste complète de toutes les variables existantes, vous pouvez consulter cette page.

Obtenir plus des ADR avec PowerShell

Maintenant que nous avons les connaissances basiques sur les Messages d’État et les Règles de Filtre d’État, nous pouvons commencer à les utiliser pour obtenir plus des Règles de Déploiement Automatique. Pour y parvenir, nous allons faire ce qui suit avec PowerShell :

  • Renommer les Groupes de Mise à jour (Software Update Group – SUG) pour retirer l’heure d’exécution (La date suffit) ;
  • Changer la durée maximale d’installation pour chaque mise à jour si elles sont destinées à des serveurs ;
  • Générer un rapport HTML qui contient des informations basiques sur chaque mise à jour contenue dans le SUG.

Ce ne sont que des exemples de ce qui peut être réalisé une fois que le script PowerShell entre en action et vous pourrez trouver de nombreuses autres idées correspondant à vos besoins. Le script complet qui va être détaillé dans cet article peut être trouvé sur notre repo GitHub. Voici plus de détails sur les différentes sections qui le compose.

Veuillez noter que le script montré dans cet exemple ne fonctionne que pour des ADR créant un nouveau SUG à chacune de leurs exécutions.

Prérequis

Le script va commencer avec quelques prérequis. Cette partie pourrait être commune à de nombreux scripts utilisant les Règles de Filtre d’État. Elle permet au script d’entrer en action en récupérant quelques variables nécessaires et en chargeant les modules PowerShell requis.

Tout d’abord, nous avons deux paramètres qui vont être utilisés pour se connecter au bon site MEMCM. Le troisième paramètre est le texte du message d’état intercepté par la Règle de Filtre d’État. Ensuite, le module PowerShell pour ConfigurationManager est importé et un PSDrive liés au site MEMCM est créé s’il ne l’a pas déjà été automatiquement durant l’importation du module (Cela arrive parfois). Après tout ça, le script est prêt à réaliser quelques actions.

[CmdletBinding()]
param(
    # Name of the site server returned by the Status Filter Rule
    [Parameter(Mandatory = $true)]
    [String] $SiteServer,
    # Site code returned by the Status Filter Rule
    [Parameter(Mandatory = $true)]
    [String] $SiteCode,
    # Description of the Status Message returned by the Status Filter Rule
    [Parameter(Mandatory = $true)]
    [String] $Description
)

# Import the ConfigurationManager.psd1 module
if (-not(Get-Module ConfigurationManager)) {
    try {
        Import-Module ("{0}\..\ConfigurationManager.psd1" -f $ENV:SMS_ADMIN_UI_PATH)
    }
    catch {
        Exit 1
    }
}

# Create the site PSDrive if it has not been created automatically during the module importation
If(-not(Get-PSDrive $SiteCode)) {
    try {
        New-PSDrive -Name $SiteCode -PSProvider "AdminUI.PS.Provider\CMSite" -Root $SiteServer | Out-Null
    }
    catch {
        Exit 1
    }
}

# Set the location to the Configuration Manager PSDrive to be able to use MEMCM Powershell commands
Set-Location "$($SiteCode):"

Actions

Pour la partie suivante, il est important de savoir à quoi ressemble le message d’état intercepté puisque cela sera le contenu de la variable Description. Quand une ADR est exécutée et qu’un nouveau Groupe de Mise à Jour est créé, un message d’état avec l’ID 5800 est généré.

Message-ID-5800

La valeur exacte du champ Description d’un tel message est la suivante :

CI Assignment Manager successfully processed new CI Assignment %1.

Dans ce message, la variable %1 respectera le modèle suivant :

  • ADR Name yyyy-MM-dd HH:mm:ss” si l’ADR est paramétrée pour créer un nouveau SUG à chaque exécution.
  • ADR Name” si elle est paramétrée pour réutiliser le même SUG à chaque fois.

Faites attention en renommant vos Groupes de Mise à Jour. Si l’ADR s’exécute plus d’une fois par jour, la seconde fois qu’elle s’exécutera, le script échouera parce que le second SUG aura le même nom que le premier une fois qu’il aura été renommé. En effet, chaque SUG doit avoir un nom unique.

Avec ces nouvelles connaissances à l’esprit, la partie suivante du script identifie si un Groupe de Mise à Jour existe avec le même nom et la même date de création que ce qui ont été extrait du message d’état. Si un SUG a été trouvé (Ce devrait être le cas ou vous avez de sérieux problèmes !) et que ce n’est pas un SUG contenant des définitions Windows Defender (Identifié par son nom), alors le Groupe de Mise à Jour est renommé pour retirer la composante horaire du nom complet. Ensuite, la durée d’exécution maximum de chaque mise à jour du SUG est changée à 120 minutes si le groupe est destiné à des serveurs.

Note sur la durée d’exécution maximale : Soyez prudent en changeant la durée d’exécution maximal de vos mises à jour si vous utilisez des Fenêtres de Maintenance pour le déploiement des mises à jour. Si le temps d’exécution cumulé des mises à jour est supérieur à la durée de la Fenêtre de Maintenance, les mises à jour ne s’appliqueront pas. Vous obtiendrez même un message d’état pour vous l’indiquer. 😉

# Regex to capture the name of the created SUG and the creation date
[regex]$Regex = "CI Assignment Manager successfully processed new CI Assignment\s+(?<Name>.*)\s(?<Date>\d{4}-\d{2}-\d{2})"

# Use the Regex on the Description variable to extract the SUG's name and creation date. Store the values in variables
$Description | Select-String -Pattern $Regex -AllMatches | ForEach-Object {
    [string]$DeploymentName = $_.Matches.Groups[$Regex.GroupNumberFromName("Name")].Value
    [string]$DeploymentDate = $_.Matches.Groups[$Regex.GroupNumberFromName("Date")].Value
}

# Check the SUG name. If it contains the word "Definition", it is a SUG containing the Windows Defender definitionsso the script stops
# Can be changeg to whatever fits best your environment
If ($DeploymentName -notlike "*Definition*") {
    # Look for a SUG with the same name and creation date. If it exists, the script continues. Otherwise, it stops.
    If ($SUG = Get-CMSoftwareUpdateGroup -Name "$($DeploymentName)*" | Where-Object {(Get-Date $_.DateCreated -Format 'yyyy-MM-dd') -eq (Get-Date $DeploymentDate -Format 'yyyy-MM-dd')}) {
        # Create a new name without the SUG's creation time, keeping only the name and creation date. Then, rename the SUG
        $NewSUGName = "$DeploymentName $DeploymentDate"
        Set-CMSoftwareUpdateGroup -InputObject $SUG -NewName $NewSUGName

        # If the SUG name matches a specific name, set the maximum execution time of each updates in the SUG to 120 minutes
        If($DeploymentName -match '^ADR_WinServ') {
            ForEach ($Update in (Get-CMSoftwareUpdate -UpdateGroupID $SUG.CI_ID -Fast)) {
                Set-CMSoftwareUpdate -InputObject $Update -MaximumExecutionMins 120
            }
        }
    }
}

Reporting

Le bloc de code suivant devrait être placé entre les deux blocs If du bloc de code précédent. Il en a été sorti pour cet article dans l’unique but de pouvoir partager le code en différentes sections.

Une fois que toutes les actions sont terminées, il est temps d’effectuer un peu de reporting. Il y a de multiples options disponibles, que ce soit l’envoi d’un courriel ou bien un message sur Teams. Pour cet exemple, j’ai décidé de générer un rapport HTML simple ayant le même look que pourrait avoir un email.

D’abord, on ajoute un peu de CSS pour rendre le rapport HTML plus attrayant. Ensuite, un tableau est créé, contenant quelques informations sur chaque mise à jour faisant partie du Groupe de Mise à Jour. Finalement, les différents morceaux sont assemblés et un fichier HTML est généré.

# Define some CSS style that will be added to the HTML report header
        $HtmlHeader = @"
<style>
    body {
        font-size: 12px;
        font-family: Arial, Helvetica, sans-serif;
    }
    table {
        font-size: 12px;
        border: 0px;
        font-family: Arial, Helvetica, sans-serif;
    }

    td {
        padding: 4px;
        margin: 0px;
        border: 0;
    }

    th {
        background: #395870;
        background: linear-gradient(#49708f, #293f50);
        color: #fff;
        font-size: 11px;
        text-transform: uppercase;
        padding: 10px 15px;
        vertical-align: middle;
    }

    tbody tr:nth-child(even) {
        background: #f0f0f2;
}
</style>
"@

        # Define the text that will be part of the HTML report in a herestring. Be careful with "@
        $PreContent = @"
Hello, <br/><br/>

The $NewSUGName Software Update Group has been created. It contains the following updates:<br/><br/>
"@
        
        # Build an array of PS Objects each containing the KB ID, KB Name and execution time
        $Info = @()
        ForEach ($Update in (Get-CMSoftwareUpdate -UpdateGroupID $SUG.CI_ID -Fast))
            {
            $UpdateProperties = [PSCustomObject]@{
                KB = $Update.ArticleID
                Titre = $Update.LocalizedDisplayName
                # Though it's set in minutes, the execution time is stored in seconds so we need to divide it by 60 to display the value in minutes
                "Max execution time (mins)" = $Update.MaxExecutionTime / 60
            }
            $Info += $UpdateProperties
        }

        # Build an HTML table out of the previous array and add the header and precontent text
        $Info | ConvertTo-Html -As Table -PreContent $PreContent -Head $HtmlHeader | Out-File "C:\Temp\$NewSUGName.html"

Utiliser les Règles de Filtre d’État pour exécuter automatiquement le script

Maintenant que le script est prêt, utilisons une Règle de Filtre d’État pour en automatiser son exécution. Retournez sur Administration > Vue d’Ensemble > Configuration du site > Sites et effectuez un clic droit sur le site désiré où le Règle de Filtre d’État doit être créée.

Dans la nouvelle fenêtre, suivez ces étapes :

  • Cliquez sur le bouton Créer et choisissez un nom pour votre règle ;
  • Cochez la case Message ID and entrer 5800 dans le champ texte situé à côté ;
  • Cliquez sur le bouton Suivant.

Voilà pour le filtre, nous n’avons besoin de rien d’autre. Sur la page Actions, cochez la case Lancer un programme et entrez la commande suivante (Voir plus bas). Ensuite, cliquez sur Suivant pour passer votre règle en revue et terminer l’assistant.

Cette ligne de commande va appeler le script PowerShell avec trois paramètres. Comme vous pouvez le voir, il s’agit de variables de Règles de Filtre d’État.

C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File C:\Scripts\OnADRCompletion.ps1 -SiteServer %sitesvr -SiteCode %sc -Description "%msgdesc"


Votre Règle de Filtre d’État est maintenant prête à travailler. Tout ce que vous avez à faire est d’attendre que vos ADR s’exécutent à nouveau pour voir le résultat. Ou, si vous ne voulez pas attendre, vous pouvez forcer l’exécution d’une ADR.

Vérification finale

Une fois terminée, la Règle de Filtre d’État devrait intercepter le message d’état correspondant à la création d’un Groupe de Mise à Jour et démarrer le script PowerShell.

Pour vérifier qu’il n’y a pas de problème, vous pouvez regarder le log statmgr.log. Il devrait y avoir une ligne de log indiquant que le process PowerShell a été lancé avec les arguments que vous avez défini dans votre Règle de Filtre d’État.

statmgr.log

A propos de l'auteur

Expert poste de travail et MEMCM qui aime automatiser ce qu'il peut avec PowerShell et Configuration Manager.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *