PI Services

Le blog des collaborateurs de PI Services

Utilisation de WinSCP .Net Assembly et COM library

Dans cet article nous allons apprendre l'utilisation et l'importance de WinSCP .Net Assembly et COM library.

Introduction

Nous sommes habitué à utiliser le client WinSCP pour se connecter sur un serveur SFTP,SCP ou FTP. Il existe même un module très basique appelé WinSCP.com pour envoyer ou réceptionner des données via un fichier *.bat. Cependant, beaucoup d'entre nous ignore l'existance de WinSCP .Net Assembly et COM library qui offre la possibilité de manipuler des fichiers à distance depuis un environnement supportant .NET, par exemple C#,VB. Net, PowerShell,SSIS et même depuis les sites MS AZURE.

WinSCP .Net assembly et COM library offrent beaucoup de possibilité en termes de ligne de commandes pour automatiser l'envoi et la réception de fichier depuis un serveur FTP,SCP ou sFTP. 

Prérequis

Télécharger le fichier zip indiqué ci-dessous et décompresser le.

Exemple de programmation en PoSH

  • L'initialisation d'une connexion sur un serveur
try
{
    # appel WinSCP .NET assembly
    Add-Type -Path "WinSCPnet.dll"
 
    # paramètre de connexion
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::Sftp
        HostName = "example.com"
        UserName = "user"
        Password = "mypassword"
        SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
    }
 
    $session = New-Object WinSCP.Session
 
    try
    {
        # initialiser la connexion
        $session.Open($sessionOptions)
 
        Write-Host "You are now connected!!!"
    }
    finally
    {
        # Déconnecter et nettoyer
        $session.Dispose()
    }
 
    exit 0
}
catch [Exception]
{
    # Exception
    Write-Host ("Error: {0}" -f $_.Exception.Message)
    exit 1
}

Pour se connecter sur un serveur sFTP avec une clé privée et sans login et mot de passe, remplacer la ligne :

Password = "mypassword"
        SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"

par 

SshPrivateKeyPath = "chemin vers la clé privée"
        GiveUpSecurityAndAcceptAnySshHostKey = "true"
  • Télécharger un fichier 

Pour télécharger un fichier avec son nom, utiliser la ligne de commande ci-dessous:

$session.GetFiles($session.EscapeFileMask(<chemin complet du fichier>), <destination locale>).Check()
  • Pour uploader un fichier 
 # Upload files
        $transferOptions = New-Object WinSCP.TransferOptions
        $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary
 
        $transferResult = $session.PutFiles("d:\toupload\*", "/home/user/", $False, $transferOptions)

 

Pour avoir plus d'informations sur les classes existantes : https://winscp.net/eng/docs/library

 

SCOM - A read operation on a large objects failed while sending data to the client

Pour cet article, nous allons nous intéresser à un cas peu commun.

Une erreur passée inaperçue pendant plusieurs mois car visée par aucune règle ou moniteur se reproduisait très régulièrement, aléatoirement sur l’un ou l’autre des Management Servers :

clip_image002

Evénement 26319, An exception was thrown while processing GetObjectsFromReader for session ID uuid:2f0f5bab-011d-4002-98d1-4c500cc449a2;id=103303.
Exception message : A transport-level error has occurred when receiving results from the server. (provider TCP Provider, error 0 – The specified network name is no longer available).

La partie “provider TCP Provider, error 0 – The specified network name is no longer available” fait immanquablement penser à une erreur SQL, et le fait que la source de l’événement soit OpsMgr SDK Service est un indice supplémentaire en ce sens.

Une verification dans le journal d’événements Applications du serveur SQL de la base OperationsManager montre qu’effectivement, un événement 7886 est présent pour chaque événement 26319 sur les Management Servers :

clip_image004

A read operation on a large objects failed while sending data to the client. A common cause for this is if the application is running in READ UNCOMMITTED isolation level. This connection will be terminated.

« Une cause courante pour cette erreur est si le niveau d’isolation est READ UNCOMMITED »… Vérifions donc cela dans la base OperationsManager, à l’aide de la commande DBCC USEROPTIONS :

clip_image006

Manifestement, ce n’est pas le cas, elle est bien en committed…

Je me tourne donc vers mon moteur de recherche préféré, qui une fois n’est pas coutume ne m’aide qu’assez peu. Un lien retient cependant mon attention : https://scomblog.wordpress.com/2012/02/29/469/.

La plupart des informations abordées dans cet article n’ont rien à voir avec le cas qui nous intéresse aujourd’hui, mais le dernier point est des plus intéressant (malgré sa syntaxe assez douloureuse) : il nous apprend que cette erreur peut se produire lorsque une lecture d’une alerte dans la base de données survient au même moment que la mise à jour de cette même alerte (cas d’une alerte dont le RepeatCount s’incrémente), ce qui provoque un conflit.
Le cas de figure le plus évident serait donc celui d’une console SCOM ouverte sur une alerte qui s’incrémente très régulièrement lorsqu’un rafraîchissement de la console survient au moment de la mise à jour de l’alerte en base. En plus, cet environnement a effectivement quelques alertes dont le RepeatCount est élevé (plusieurs dizaines de milliers).

Sauf qu’après une petite enquête auprès des utilisateurs, aucun ne semble avoir de problème récurrent avec la console (popup d’erreur, déconnexions…) qui devraient pourtant se produire lorsque l’incident survient.

Pour en avoir le cœur net, une trace SQL est prise avec l’aide du support Microsoft. Elle révèle que les requêtes qui provoquent le problème sont toutes semblables à ceci :

clip_image008

Cette requête récupère les détails d’une alerte (source, description etc) ; elle est donc parfaitement légitime et il est normal d’en rencontrer un grand nombre. Elle cadre d’ailleurs avec l’explication préalablement analysée.
Un détail attire cependant mon attention : ici, la requête est effectuée pour TOUTES les alertes présentes dans l’environnement, puisque la variable @Id0, supposée contenir l’ID de l’alerte à récupérer, contient ici le caractère %, autrement dit le « joker » du langage SQL !
Il s’agit donc d’une requête particulièrement lourde, et qui n’a pas réellement de raison d’être effectuée par une utilisation normale de la console.

Peut-être est-il alors possible de retrouver par quel compte utilisateur cette requête est déclenchée ? Cela nous aiderait à comprendre comment elle survient…

Revenons donc à notre événement sur le Management Server SCOM. Ce n’est pas très lisible, mais il nous indique quelle session a rencontré le problème via l’information id=. Il s’agit donc ici de la session 103303.

clip_image010

En descendant un peu dans le journal d’événement, il doit normalement exister un événement 26328 qui correspond à la création de cette session et qui contient le compte l’ayant créé :

clip_image012

Voilà qui est intéressant ! Dans cet environnement, tous les utilisateurs se connectent avec leur compte nominal personnel. Le compte « SCOM2012_admin » n’est utilisé que pour l’exécution de scripts qui font appel à SCOM.

Il n’y a ici pas de moyen technique permettant de savoir quel est ce script ni à partir d’où il est exécuté, mais une bonne connaissance de l’environnement m’a permis d’avoir des soupçons sur un script en particulier qui s’exécutait très régulièrement et effectuait des traitements sur les alertes.

Une analyse du script a révélé qu’il exécutait le cmdlet Get-SCOMAlert | Where {blabla}, c’est-à-dire qu’il récupérait l’intégralité des alertes avec toutes leurs propriétés puis les filtrait à l’aide de la clause Where ; ce qui correspond parfaitement à ce qu’indiquait la trace SQL : nous tenons manifestement notre coupable !

Et la correction est en plus assez simple : il suffit de réaliser le filtrage dans la requête, ce qui a pour conséquence de l’alléger considérablement, en modifiant le cmdlet de la sorte : Get-SCOMAlert –Criteria {blablabla}.

Suite à cette modification, l’événement ne s’est plus reproduit et, pour ne rien gâcher, le serveur qui exécutait le script a vu son occupation CPU et RAM diminuer fortement :)

SCOM 2016 – Active Directory et contrôleurs de domaine

Pour commencer, une bonne nouvelle : le Management Pack Active Directory, connu des amateurs pour sa complexité et son manque de fiabilité, vient d’être en grande partie réécrit !

La nouvelle version ne nécessite plus OOMADS, la supervision de la réplication AD est entièrement nouvelle et simplifiée…

Attention ce nouveau MP ne met pas à jour l’ancien qui pourra donc être désinstallé avant de déployer le nouveau, ou conservé en parallèle. Par ailleurs, il n’est compatible qu’avec les contrôleurs de domaine sous Windows 2012 (R2) et 2016, quel que soit le niveau fonctionnel de votre AD.

Venons-en maintenant au problème qui nous intéresse : SCOM 2016 est sorti il y a quelques semaines, et avec lui son (petit) lot de nouveautés sur lesquels nous reviendrons probablement dans de prochains articles.

Une de ces nouveautés concerne le déploiement d’un agent sur un contrôleur de domaine : sans intervention de votre part, l’agent passera presque immédiatement en grisé et une alerte System Center Management Health Service Unloaded System Rule(s) est générée.

clip_image001

Une vérification sur le contrôleur de domaine concerné montre effectivement un très grand nombre d’événements 1102 dans le journal OperationsManager :

clip_image003

Mais il faut remonter plus loin, juste après le déploiement de l’agent, pour trouver l’événement qui nous intéresse :

clip_image005

Cet événement 7017 indique The health service blocked access to the windows credential NT AUTHORITY\SYSTEM because it is not authorized on management group <MG>. You can run the HSLockdown tool to change which credentials are authorized.

Ce message d’erreur rappelle une vieille KB Microsoft : https://support.microsoft.com/en-us/kb/946428

Et effectivement, il suffit d’exécuter l’outil HSLockdown (il se trouve dans le dossier d’installation de l’agent SCOM) pour, dans un premier temps, vérifier que le compte LocalSystem est bien bloqué :

clip_image007

Puis, dans un second temps, l’autoriser :

clip_image008

Ne reste plus qu’à redémarrer l’agent (HealthService), et tout rentre dans l’ordre.

Quant à savoir pourquoi ce comportement a changé depuis SCOM 2012, avec lequel LocalSystem n’était pas bloqué sur les DC… mystère !

Skype for Business / Lync Server : Erreur 404 avec les meetings URL

Contexte

Lorsqu'un utilisateur clique sur le lien d'un meeting Skype le client remonte que la conférence est introuvable.

Le problème :

Les URL (https://join.Domaine.ext/SubDomain/meet/john.doe/4J8MVYPH) dans les invitations des meetings Skype retournent une erreur 404

Cause :

Le module "URL rewrite" d'IIS n'est pas correctement configuré, un ou plusieurs sous-domaines sont manquants.

Résolution

Réactiver tous les FE Skype via la commande (la commande doit être exécutée sur chaque FE en tant qu'administrateur et n'a pas d'impact) :

Enable-CsComputer

Windows Serveur : Extraction des configurations DHCP

Attention ne s'applique qu'à partir de  Windows Server 2012 et Windows 8.

Comment connaitre rapidement les configurations DHCP du domaine? Eh bien, avec Powershell.

 

Lister les serveurs DHCP du domaine:

Pour lister les serveurs DHCP du domaine vous pouvez utiliser la commande:

Get-DhcpServerInDC

Cette commande vous retournera par défaut :

  1. l'adresse IP du ou des serveurs
  2. Le nom Dns du ou des serveurs

Lister les scopes DHCP:

Pour lister les scopes DHCP et leurs configurations vous pouvez utiliser la commande suivante:

Get-DhcpServerv4Scope

Par défaut cette commande vous retournera les éléments suivants:

  1. L'étendue
  2. Le masque sous réseau
  3. Le Nom du scope
  4. L'état (Actif ou Inactif)
  5. L'adresse IP de début
  6. L'adresse IP de fin
  7. La durée des baux

Bien sur il est possible de récupérer d'autres informations si vous le souhaitez.

Obtenir des informations sur les scopes:

Pour obtenir des informations sur l'utilisation des scopes vous pouvez utiliser la commande suivante:

 

Get-DhcpServerv4ScopeStatistics

 

Cette commande retourne :

  1. L'étendue
  2. Le nombre d'adresses libres
  3. Le nombre d'adresses utilisées
  4. Le pourcentage d'utilisation
  5. Le nombre d'adresses réservées
  6. Le nombre d'adresses en attente de distribution (normalement 0)
  7. Le nom de l'étendue globale

Peut on scripter tout ça?

Il vous est possible d'exécuter toutes ces commandes à distance via "invoke-command" ou "Enter-PSSession" sauf la commande "Get-DhcpServerInDC".

Donc il est possible de scripter toutes ces commandes et avoir une belle extraction sans se connecter au serveur à condition de déjà posséder la résultante de  "Get-DhcpServerInDC".

Sinon vous pouvez aussi exécuter un script depuis le serveur, mais bon ça, c'est quand même moins "Secure".

Plus d'informations sur : 

https://technet.microsoft.com/library/jj590751(v=wps.620).aspx

 

 

.NET Framework : Installation du .NET 3.5 sous Windows Server 2012 R2

Bonjour à tous !

L'article d'aujourd'hui rentre dans la catégorie "trucs et astuces", mais de celles qui vous feront gagner beaucoup de temps.

En effet, l'installation de la fonctionnalité .NET Framework version 3.5 sous Windows Server 2012 R2 n'a jamais été une sinécure.

La faute en revient à la fonctionnalité Features on Demand introduite avec Windows Server 2012. Afin de rentre le dossier d'installation de Windows Server 2012 moins volumineux, Microsoft a décidé que les fichiers nécessaires pour installer les rôles et fonctionnalités de Windows Server ne seraient plus présents en totalité sur le disque dur local de l'OS. En conséquence, l'installation de certaines fonctionnalités requiert une source externe (ISO ou ressources sur le réseau) et la fonctionnalité .NET Framework 3.5 en fait partie.

La méthode classique

Concrètement, cela se traduit par un chemin à renseigner vers les sources externes Windows Server lors de l'installation de la fonctionnalité .NET 3.5 au sein du Gestionnaire de Serveur.

Ces sources peuvent être une ISO que vous aurez préalablement monté ou des fichiers stockés sur une ressource réseau.

Si vous ne précisez rien dans le chemin des sources, le Gestionnaire de Serveur utilisera Windows Update comme moyen pour télécharger les sources manquantes.

Et c'est là "tout le sel de l'opération", à savoir que si le serveur est managé par un WSUS, le téléchargement des sources externes via Windows Update n'est pas possible et si vous n'avez pas l'ISO Windows Server sous la main, il vous faudra la transférer et vous n'avez peut être pas le temps, ni la bande passante pour envoyer 4,6 Go !

Heureusement, il existe une alternative.

La méthode Windows Update

La méthode suivante vise à permettre le téléchargement des sources manquantes directement via Windows Update, même si le serveur est dans le périmètre de gestion d'un serveur WSUS.

Nous allons donner ici la méthode "unitaire" pour passer la modification, mais celle-ci est très facilement adaptable en GPO.

1) Pour se faire, ouvrez la console GPEdit.msc sur la machine concernée.

2) Allez dans Computer Configuration -> Administrative Templates -> System

3) Allez à l’option Specify settings for optional component installation and component repair.

4) Passez le paramètre à Enabled si celui-ci est à Disabled ou Not Configured.

5) Cochez l'option Contact Windows Update directly to download repair content instead if Windows Server Update Services (WSUS). Cliquez sur Apply pour valider la modification.

6) Passez la commande GPUpdate /force dans une invite de commande afin que le poste prenne en compte la modification dans ses paramètres de mise à jour.

7) Relancez l'installation de la fonctionnalité .NET Framework 3.5 depuis le Gestionnaire de Serveur, en laissant l'Alternate File Path vide. L'installation devrait désormais être fonctionnelle.

Fonction de collecte de perf via Scom

Bien que la méthode en passant par une requête SQL soit plus rapide, il peut être utile de pouvoir collecter des données de performance spécifique via le sdk Scom.

La fonction suivants prend en paramètre  les données de connexion ($managementServer,$user,$passwd) et les critère de compteurs de performance qui peuvent être regroupé dans le paramètre $criteria, ainsi que le paramètre $HourOffset qui permet de préciser une fenêtre de collecte.

! Attention: Plus ce paramètre en heure est important, plus le nombre de sample renvoyé est important.

 

    # Fonction de recuperation de compteur de performance dans la base OperationsManager       Function GetPerfValueFromScomv2($managementServer,$user,$passwd,$criteria,$monitoringClassId = $null,$monitoringObjectName = $null,$monitoringObjectDisplayName = $null,$objectName = $null,$counterName = $null,$instanceName = $null,$HourOffset,$startTime = (Get-Date).AddHours(-$HourWindow),$endTime = (Get-Date))     {   #Fonction d'ajout de critere a la requete function Add-Criteria() {     param($criteria,$clause)           if ($criteria -ne $null)         {$criteria += " AND $clause"}     else         {$criteria = $clause}               return($criteria) }     #Import du module Scom import-module OperationsManager   #Connexion au management server     $mgConn = New-Object Microsoft.EnterpriseManagement.ManagementGroupConnectionSettings($managementServer) $mgConn.UserName = $user $mgConn.Password = $passwd $mg = New-Object Microsoft.EnterpriseManagement.ManagementGroup($mgConn)     if ($criteria -eq $null) {     if ($monitoringClassId -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "MonitoringClassId = '{$monitoringClassId}'" }     if ($monitoringObjectDisplayName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "MonitoringObjectDisplayName = '$monitoringObjectDisplayName'" }     if ($monitoringObjectName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "MonitoringObjectName = '$monitoringObjectName'" }     if ($objectName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "ObjectName = '$objectName'" }     if ($counterName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "CounterName = '$counterName'" }     if ($instanceName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "InstanceName = '$instanceName'" } }   #Creation du reader $reader = $mg.GetMonitoringPerformanceDataReader($criteria) while ($reader.Read()) {     #Creation de l'objet de performance     $perfData = $reader.GetMonitoringPerformanceData()     $valueReader = $perfData.GetValueReader($startTime,$endTime)       #Renvoi des valeurs     while ($valueReader.Read())     {         $perfValue = $valueReader.GetMonitoringPerformanceDataValue()         $perfValue     } }   }        

Quest RUM : Diagnostic de processings "erratiques"

Bonjour à tous !

Nous allons nous pencher aujourd'hui plus profondément dans les entrailles du produit Quest Migration Manager for Active Directory, notamment avec l'étude d'un cas problématique et de sa résolution.

Le cas que nous allons étudier ci-dessous est susceptible d'être peu rencontré, mais il n'en est pas moins "vicieux". J'espère donc que ce billet n'en sera que d'autant plus utile.

Les symptômes

  • Vous avez migré un ensemble d'utilisateurs à l'aide de QMM.
  • Vous avez lancé des processings avec RUM sur un ensemble de postes.
  • Sur certains postes, le processing se passe correctement, sur d'autres non.
  • Aucune erreur particulière n'est rapportée dans la console RUM, le seul signe visible est qu'aucun élément n'est mis à jour lors du processing (Aucun fichier, aucune clé registre, ...).
  • Si vous remigrez les utilisateurs à l'aide d'un autre serveur Quest, et si vous effectuez de nouveau des processings sur les précédents postes avec ce nouveau serveur, vous pourrez constater que certains postes sont correctement processés cette fois-ci, et que d'autres ne le sont plus.

Analyse du problème

La console RUM de Quest ne nous indiquant aucune erreur particulière lors des processings sur les postes en question, c'est donc vers les fichiers de logs que nous allons devoir nous tourner.

Le premier fichier de log nous intéressant va être celui qui remonte les détails du processing d'un poste.

Vous pourrez trouver, pour une instance RUM, tous les fichiers de processing de l'ensemble des postes dans le dossier suivant :

C:\Program Files (x86)\Common Files\Aelita Shared\Migration Tools\Resource Updating\Logs\

Allez dans le dossier correspondant au poste voulu et ouvrez le fichier de log correspondant au processing "en échec".

A première vue, il n'y a rien d'inhabituel dans le fichier de log, à part que l'on remarque bien qu'il n'y a aucun élément mis à jour lors de processing. Cependant, il faut bien regarder le Warning présent à la deuxième ligne.

Nous y trouvons l'avertissement suivant, à savoir que Le fichier INI contient une ligne invalide :

INI file contains invalid line '9;User_XXX;106572;;User;XXX@sourcedomain.local;User;XXX@targetdomain.local;1'. Escape to next domain pair

Avant de pouvoir analyser la ligne en question, il nous faut donc parcourir le fichier INI en question. Ce fichier correspond en fait au fichier de mappage des utilisateurs que RUM utilise lors de ces processings. A chaque processing, un nouveau fichier de mappage est généré selon les utilisateurs migrés par l'instance QMM. Tous les fichiers de mappage générés se trouvent à l'intérieur du dossier suivant :

C:\Program Files (x86)\Common Files\Aelita Shared\Migration Tools\Resource Updating\Configs\

Si l'on prend le fichier INI cité précédemment, voici ce que l'on trouve à l'intérieur de celui-ci :

La 1ère ligne représente une ligne correctement formée, à savoir que tous les champs du fichier de mappage sont séparés par un point-virgule.

La 2ème ligne surlignée correspond à la ligne citée en erreur. Quand on effectue une analyse de celle-ci, on remarque qu'elle contient plus de point-virgule que pour une ligne correctement formée. Je vous remets le message d'erreur avec le surlignage pour bien mettre en évidence les anomalies :

INI file contains invalid line '9;User_XXX;106572;;User;XXX@sourcedomain.local;User;XXX@targetdomain.local;1'. Escape to next domain pair

En l'occurrence, après une vérification dans les propriétés de l'utilisateur dans l'AD Source, il s'avère que le SamAccountName de l'utilisateur en question est bien "User_XXX" mais que l'UPN de celui-ci est "User;XXX" !

Le fichier de mappage va donc inclure d'office ces points virgules supplémentaires ce qui va causer l'erreur citée précédemment, qui n'est donc pour le moment pas explicitement gérée par Quest dans le sens ou, précédemment, la migration de cette utilisateur via QMM n'a donné lieu à aucun avertissement.

La conséquence de cette erreur nous est donnée dans le message d'avertissement, à savoir Escape to next domain pair.

Une domain pair dans le jargon de Quest correspond à une paire domaine source - domaine cible déclarée dans Quest. Si vous avez plusieurs domaines distincts à migrer avec QMM, vous devez déclarer une domain pair pour chacun d'entre eux. Ce qu'indique le message d'erreur, c"est que toute la partie du fichier de mappage qui est après la ligne en erreur est ignorée, jusqu'à la prochaine domain pair rencontrée comme schématisé dans l'image ci-dessous :

C'est ce fait qui explique pourquoi certains postes n"étaient pas procéssés, tandis que d'autres l'étaient correctement. C'est également ce fait qui explique les disparités observées dans les processings effectués à l'aide d'une autre instance de Quest RUM. En effet, comme le fichier de mappage des comptes est re-généré à chaque processing, l'ordre des comptes à l'interieur de celui-ci diffère suivant les instances, c'est donc pourquoi le processing était de nouveau fonctionnel pour certains postes, et pour d'autres non avec une nouvelle instance.

Solution

La résolution du problème se présente sous la forme suivante :

  • Modifiez l'utilisateur en erreur dans l'AD source et dans l'AD cible afin de retirer le caractère point-virgule du nom d'utilisateur
  • Effectuez une nouvelle migration de l'utilisateur (un merge dans le cas présent car l'utilisateur est déjà existant dans l'AD cible) avec QMM car RUM se base sur les utilisateurs migrés avec QMM pour construire son fichier de mappage des utilisateurs (voir la section Addendum pour les exceptions)
  • Effectuez de nouveau un processing des postes en erreurs, celui-ci devrait être désormais fonctionnel, avec notamment le message suivant dans le fichier de log des postes procéssés :

Addendum

Il nous faut ajouter une petite précision, car nous avons précisé au paragraphe précédent que RUM se basait sur la liste des utilisateurs migrés avec QMM pour construire son fichier de mappage des utilisateurs.

Ce n'est plus systématiquement vrai avec la version 8.13 de QMM et RUM, car nous pouvons indiquer à RUM lors des processings de se baser directement sur le SIDHistory de l'utilisateur cible (SID de l'utilisateur source) dans l'AD cible pour effectuer la correspondance des comptes utilisateurs sur les machines migrées.

Vous trouverez l'option lors de l'étape suivante du processing :

Quest RUM : Script de désinstallation des agents

Bonjour à tous !

Lors d'une migration effectuée à l'aide du produit Quest Migration Manager for Active Directory, vous vous retrouvez souvent en fin de migration avec un nombre conséquent d'agents Quest à désinstaller de tous les postes migrés.

Ce que vous pouvez très bien faire à l'aide de Quest RUM (Resource Updating Manager) via l'option Cleanup :

Mais il peut arriver qu'entre temps que certains postes migrés soient devenus indisponibles. Plutôt que de refaire une passe numéro X pour désinstaller les agents, nous allons voir comment automatiser la désinstallation de ceux-ci.

Prérequis

Pour ce faire, il vous faut :

  • Un serveur sur lequel sera placé un partage accessible par toutes les machines ayant un agent Quest
  • Un éditeur de script Powershell
  • Une console d'édition de stratégies de groupe

Le partage de fichiers

Afin que notre script de désinstallation puisse écrire les logs nécessaire, il doit avoir à disposition un partage sur lequel les machines concernées puissent avoir un droit d'écriture de fichiers.

Par défaut, le script va utiliser le nom de partage QuestUninstallLogs$ mais vous pourrez le modifier via les arguments du script. Nous rajoutons un à la fin du nom du partage afin de masquer celui-ci.

Il faut ajouter sur le partage (droit de partage) le droit en modification pour le groupe Everyone.

Il faut ajouter sur le dossier (droit NTFS) le droit en modification et en écriture pour le groupe Authenticated Users

Une fois cela fait, nous pouvons passer à l'édition du script.

Le script

Arguments

Le script s'appelle à l'aide des arguments suivants :

  • -Pole (obligatoire) : Nom du dossier de 1er niveau des logs
  • -Site (obligatoire) : Nom du dossier de 2ème niveau des logs
  • -LogServer (obligatoire) : Nom du serveur devant recevoir les logs
  • -LogShare (facultatif) : Nom du partage devant recevoir les logs

Sortie

Deux types de fichiers de logs vont être générés en sortie dans le chemin indiqué en paramètre du script :

  • XXX_SUMMARY.log : Fichier résumant toutes les désinstallations effectuées par le script
  • COMPUTERS\PC-XXX.log : Fichier détaillant le déroulement de la désinstallation de l'agent Quest pour le poste concerné

Code

#-------------------#
# Script Parameters #
#-------------------#
# Description
# The Uninstall_Quest_Agent script is uninstalling the Quest RUM Agent
# 
# How to use it 
#
# .\Uninstall_Quest_Agent.ps1 -Pole "POLE_IDF" -Site "Site_1" -LogServer "LOG_SERVER_1" -LogShare "QuestUninstallLogs$"
#
# -Pole = Targeted Pole
# -Site = Targeted Site
# -LogServer = Server on which the uninstall logs will be stored
# -LogShare (not mandatory) = Network Share on which the uninstall logs will be stored

########## PARAMETERS ##########

[CmdletBinding(DefaultParametersetName="Common")]
param(
	
	#Attribute field to check
	[Parameter(Mandatory=$true,Position=1)][string] $Pole = $null,
	
	#Attribute field to check
	[Parameter(Mandatory=$true,Position=2)][string] $Site = $null,
	
	#Attributes fields to check
	[Parameter(Mandatory=$false,Position=3)][string] $LogServer = $null,

	#Attributes fields to check
	[Parameter(Mandatory=$false,Position=4)][string] $LogShare = "QuestUninstallLogs$"
	
	)

########## SCRIPT EXECUTION ##########

# Check if script has been executed (log file already exists)

# Define logfile path and name
# Detailed logs
$LogFileDirectoryPath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site + "\COMPUTERS"
$LogFileName = $env:computername + ".log"
$LogFilePath = $LogFileDirectoryPath + "\" + $LogFileName

# Summary logs
$SummaryLogFileDirectoryPath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site
$SummaryLogFileName = $Pole + "_" + $Site + "_" + "SUMMARY.log"
$SummaryLogFilePath = $SummaryLogFileDirectoryPath + "\" + $SummaryLogFileName

# End script if Quest Agent Service is missing
$Service = Get-Service QsRUMAgent -ErrorAction SilentlyContinue

if($Service -eq $null)
{
    Exit
}

########## LOG FILES MANAGMENT ##########

# Checking if directories need to be created

# Check if pole directory exists
$PoleFilePath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole

# If directory don't exist, we create it
if(!(Test-Path $PoleFilePath))
{
    New-Item $PoleFilePath -ItemType Directory
}

# Check if site directory exists
$SiteFilePath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site

# If directory don't exist, we create it
if(!(Test-Path $SiteFilePath))
{
    New-Item $SiteFilePath -ItemType Directory
}

# Check if COMPUTERS directory exists
$ComputersFilePath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site + "\COMPUTERS"

# If directory don't exist, we create it
if(!(Test-Path $ComputersFilePath))
{
    New-Item $ComputersFilePath -ItemType Directory
}

########## UNINSTALLING AGENT ##########

$Date = (Get-Date).ToString()
$ComputerName = "\\" + $env:computername

# Log
$ToWrite = $Date + " - " + "Begining of Quest agent uninstallation"
Add-Content $LogFilePath $ToWrite

# Stopping and Deleting Quest Migration Manager RUM Agent Service
$Service = Get-Service QsRUMAgent -ErrorAction SilentlyContinue

#If service exists
if($Service)
{
    Stop-Service $Service.Name
    # Log
    $ToWrite = $Date + " - " + "Quest Migration Manager RUM Agent Service - Stopped"
    Add-Content $LogFilePath $ToWrite

    sc.exe $ComputerName delete $Service.Name
    # Log
    $ToWrite = $Date + " - " + "Quest Migration Manager RUM Agent Service - Deleted"
    Add-Content $LogFilePath $ToWrite

    # Log Général
    $ToWrite = $Date + " - " + $env:computername + " - " + "Agent Deleted"
    Add-Content $SummaryLogFilePath $ToWrite
}

else
{
    # Log
    $ToWrite = $Date + " - " + "ERROR : Quest Migration Manager RUM Agent Service not found !"
    Add-Content $LogFilePath $ToWrite
}

# Deleting Quest Migration Manager RUM Agent Directory
$QuestAgentDirectory = "$env:SystemRoot\Quest Resource Updating Agent"

#If directory exists
if(Test-Path $QuestAgentDirectory)
{
    Remove-Item $QuestAgentDirectory -Recurse
    # Log
    $ToWrite = $Date + " - " + "Quest Migration Manager RUM Agent Directory - Deleted"
    Add-Content $LogFilePath $ToWrite
}

else
{
    # Log
    $ToWrite = $Date + " - " + "ERROR : Quest Migration Manager RUM Agent Directory not found !"
    Add-Content $LogFilePath $ToWrite
}

# Log
$ToWrite = $Date + " - " + "End of Quest agent uninstallation"
Add-Content $LogFilePath $ToWrite

Utilisation du script

Vous pouvez utiliser ce script directement sur le poste concerné ou par GPO pour une désinstallation groupée.

Par GPO, le script s'utilise dans la section Powershell dans les Paramètres Ordinateurs de la console de configuration des GPO.

Le chemin pour y accéder est Configuration Ordinateur > Stratégies > Paramètres Windows > Arrêt > Scripts Powershell

A minima, le script doit s'appeller à l'aide des paramètres suivants :

Au fur et à mesure que le script est exécuté, vous devriez voir le dossier des logs se remplir, que ce soit pour le log SUMMARY qui résume toutes les désinstallations ou pour les logs individuels par machine.

Erreur de mises à jour WSUS

Contexte :

Le problème décrit ci-dessous a été rencontré dans le cadre de la mise en place d’un serveur WSUS sous Windows Server 2012 R2.

Problème rencontré :

Suite à la mise en place de WSUS, toutes les installations de mises jours depuis les serveurs étaient en échec ainsi que la remontée des rapports.

image

Un code d’erreur apparait : 80244016.

image

Analyse :

Pour obtenir plus de détails sur ce type de problème, l’outil WireShark peut être utilisé depuis un « client » WSUS afin d’analyser les flux réseau entre le client et le serveur WSUS.

Il faut ensuite filtrer les résultats obtenus sur les protocoles http et https.

La traceWireShark permet de mettre en évidence qu’une erreur de type « http/1.1 400 Bad Request » est déclenchée.

image

En observant en détail la requête http, on observe que le client WSUS tente de récupérer un fichier « .cab » sur le serveur WSUS avec le nom complet du serveur WSUS (FQDN).

La requête essai de communiquer avec l’host : hote.mondomaine.com.

image

Explication :

Le problème est dû à une incohérence entre la configuration du site IIS du serveur WSUS et l’URL positionnée sur les clients WSUS.

Les deux valeurs doivent être identiques (soit le nom NetBIOS du serveur WSUS, soit son FQDN).

Pour trouver le paramètre erroné il suffit de vérifier tous les endroits où l’URL est rentrée.

Le premier point à vérifier est la configuration de la stratégie de groupe positionnant l’URL WSUS sur le client.

Pour vérifier il suffit de lancer la commande « Rsop.msc » sur le client WSUS, puis d’aller dans le dossier « Windows Update » dans la section Configuration Ordinateur / Modèle d’administration / Composant Windows :

image

L’URL est positionnée dans le paramètre « Spécifier l’emplacement intranet du service de mise à jour Microsoft »

image

Il ne reste plus qu’à vérifier la configuration de IIS. Une fois la page de management est ouverte il faut se mettre sur le site « WSUS Administration ».

Puis aller dans le paramètre « Bindings »

image

Et d’éditer l’adresse http.

image

Dans notre exemple, la GPO demande au client d’utiliser le FQDN du serveur alors que le site IIS accepte uniquement les requêtes adressées au nom court.

image

Résolution :

Pour résoudre le problème, il suffit de modifier le « host name » du site Web IIS par le FQDN du serveur.

Suite au redémarrage de IIS, les clients WSUS peuvent appliquer les mises à jour avec succès.

image

On peut vérifier en relançant une capture de trames et on s’aperçoit bien que le serveur WSUS répond avec le code 200, ce qui signifie que la requête a été traitée avec succès.

image