PI Services

Le blog des collaborateurs de PI Services

SCOM : Debug des échecs d’exécution de process et de requêtes wmi.

 

Les alertes “Workflow Runtime: Failed to run a process or script” ou “Workflow Runtime: Failed to run a WMI query” révèle un problème d’exécution d’une règle ou d’un moniteur.

1er cas: ce problème est ponctuel. Le champ repeat count de l’alerte est peu élevé et la dernière occurrence (champ Last Modified) n’est pas très récent:

Dans la plupart de ces cas, le workflow exécuté a l’origine de cette erreur n’a pas pu aboutir pour des problèmes ponctuels de performance ou de disponibilité de la machine cible. Vous pouvez essayez de faire le parallèle entre l’heure de l’alerte et les éventements présent dans les eventlog Application et Systeme de la machine cible.

2nd cas: Ce problème est récurrent. Le champ repeat count de l’alerte est élevé et la dernière occurrence (champ Last Modified) est récente: Cela signifie que le workflow concerné échoue systématiquement pour cette la machine cible.

Action:

Il est important de lire le champ Description de l'alerte pour voir plus de détail sur la commande ou la requête exécutée, le workflow impacté et la machine cible.

Exemples:

*************************************************************

Command executed: "C:\Windows\system32\cscript.exe" /nologo "IsHostingMSCS.vbs" {1C0CCF64-D32D-B64C-A66A-792E7F0934D6} {6E52A2D1-E55F-7E00-A150-D4CFAB747EFE} (…) (…)

Working Directory: C:\Program Files\System Center Operations Manager\Agent\Health Service State\Monitoring Host Temporary Files 2960\58276\

One or more workflows were affected by this.

Workflow name: System.Mom.BackwardCompatibility.Computer.IsHostingMSCS.Discovery

Instance name: Machine1.home.com

*************************************************************

***************************************************************

Object enumeration failed

Query: 'SELECT ServiceName, StartName, DisplayName FROM SqlService WHERE ServiceName="SQLAgent$REC_FR_CI_AS"'

HRESULT: 0x800706be

Details: The remote procedure call failed.

One or more workflows were affected by this.

Workflow name: Microsoft.SQLServer.2008.AgentDiscovery

Instance name: MSSQLSERVER

Instance ID: {6AD519E3-D3C0-7B1B-EE4A-92367A4CDCEC}

***************************************************************

 

Connectez vous sur la machine concernée par l’alerte

Pour les alertes concernant une erreur d’exécution d’un script, tentez d’exécutez dans une fenêtre de commande le script et les argument associés tel que la commande apparait dans le champ Description de l’alerte (Command Executed:…)

Les scripts de supervision des règles/moniteurs retourne dans la plupart des cas leurs données au format XML, ce qui signifie que le script a abouti a une transmission des données récoltées. Dans la cas contraire, le retour affiché par l’exécution de ce script peut être une erreur vbscript ou powershell lié au contenu du script lui-même.

 

Pour les alertes concernant une erreur d’exécution d’une requête wmi, vérifiez sur la machine que la requête wmi précisée dans le champ description de l'alerte (Query:…) peut être effectuée.

=> Utilisez wbemtest.exe présent nativement sur tout les OS Windows pour exécutez la requête wmi.

image

image

image

image

De plus le code situé apres “HRESULT” dans la description de l’alerte indique le type d’erreur wmi. ces types sont disponible sur le lien http://msdn.microsoft.com/en-us/library/aa394559%28v=vs.85%29.aspx

Quelques astuces Powershell

Introduction

Lorsque l'on développe des scripts Powershell, il y a un certain nombres de commandes génériques que l'on réutilise très souvent. Nous verrons aussi quelques astuces qui peuvent être utiles dans de nombreux scripts.

Astuces

Retrouver le dossier d'exécution du script :

Souvent, il arrive que l'on crée une bibliothèque de scripts. Un script peut en appeler un autre parce qu'il contient des fonctions. On peut aussi vouloir faire appel à un fichier de configuration. Beaucoup de scripts contiennent alors le chemin d'exécution via une variable qu'il convient de changer manuellement dès que le répertoire est modifié. Cela n'est cependant pas très portatif. Il est nettement plus intéressant de retrouver ce chemin dynamiquement.

La commande ci-dessous permet de retourner le dossier où se situe le script qui est en train de s'exécuter.

001
002
$RootFolder = Split-Path -Path $MyInvocation.MyCommand.Path 

On peut ensuite retrouver nos fichiers additionnels via des chemins relatifs calculés depuis celui que l'on vient de récupérer.

"$MyInvocation.MyCommand.Path" retourne le chemin du fichier.
A partir de ce dernier la commande "Split-Path" nous retourne uniquement le dossier dans lequel est contenu le script.

Connaître le contexte d'exécution (32 ou 64 bits) :

Il peut arriver que l'on souhaite lancer un exécutable spécifiquement depuis une instance Powershell x86 ou x64 car celui-ci n'existe pas dans un autre contexte.

Pour cela, il existe une astuce permettant de savoir quelle édition de Powershell (x86 ou x64) est lancée :

001
002
[System.IntPtr]::Size 

Cette commande nous donne la taille d'un pointeur sous la forme d'un entier. Lorsque l'invite de commande Powershell est en x64, cette valeur vaut 8. Dans le cas contraire il s'agit de 4. On peut facilement imaginer une structure conditionnel permettant de relancer un script automatiquement en Powershell x86 qui intègre un exécutable ne tournant que sur cette version.

001
002
003
004
005
006
if( [System.IntPtr]::Size -ne 4) { 
    #Chemin du script
    $Path = $myInvocation.InvocationName 
    #Invocation de Powershell x86 avec le même script à exécuter comme paramètre
    $Return = &"$env:windir\syswow64\windowspowershell\v1.0\powershell.exe" $Path 
}

Le script est-il exécuté en mode administrateur :

Dans le même esprit, il est possible de savoir si un script a été lancé en mode administrateur. En effet, certaines opérations peuvent exiger ce mode de fonctionnement :

001
002
([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")

Bien évidemment il n'existe pas de commande pour relancer le script dans ce mode. On peut cependant inviter l'utilisateur à le faire.

Tester son script pour une autre version de Powershell :

Il peut arriver que l'on développe son script Powershell sur son poste client qui est en version 3 alors que le serveur qui le lance est lui en version 2. Afin d'être certain que ce script est compatible, il est possible d'indiquer la version de Powershell à utiliser. En voici un exemple ci-dessous :

test version

En version 3 il n'est plus nécessaire de faire d'Import-Module pour utiliser les cmdlets Active Directory, ce qui n'est pas le cas en Powershell 2. Nous voyons donc clairement la différence entre les 2 exécutions.

Appeler une librairie .NET :

Il existe de nombreuses méthodes pour charger une librairie .NET (sous forme de dll ou directement de code C# par exemple). Ici, nous en verrons une qui utilise la commande Powershell Add-Type :

Pour utiliser les Windows forms pour les interfaces graphiques.

001
002
Add-Type -AssemblyName "System.Windows.Forms"

Pour administrer IIS, on charge une dll depuis son emplacement sur le disque

001
002
Add-Type -Path "c:\windows\system32\inetsrv\microsoft.web.administration.dll"

Intégrer directement du code C# (il est aussi possible de le faire avec du code VBScript)

001
002
003
004
005
006
007
008
009
010
011
012
Main; Add-Type -TypeDefinition @"
public class Test
{
    public string Name {get;set;}
    public int Size {get;set;}
    public Test(string Name, int Size){
        this.Name = Name;
        this.Size = Size;
    }
}
"@

Toutefois lorsque la commande Add-Type sera exécutée il n'est pas possible de recharger une librairie qui aurait été modifiée (Cela est dû à .NET). En effet une librairie ne peut être déchargée. Il faut alors changer de session Powershell (c'est à dire lancer une nouvelle instance de Powershell).

Lync 2013 – Meeting personnalisés

Lors de la création d’un meeting Lync (via Outlook), le contenu de la demande peut paraitre très simpliste. Surtout quand l’intégration à la téléphonie n’est pas réalisée:

image Dans lync 2013, de nouvelles options sont disponibles pour rendre la demande de meeting plus personnalisé et adapté via des “meeting configuration” particulière. Voici les 4 nouveaux paramètres:

    • Logo URL
    • Help URL
    • Legal Text URL
    • Custom Footer Text

      Pour configurer ses élément il suffit d’éditer la configuration des meeting par default ou encore de certaines politiques appliquer a un partie des utilisateurs:

      image
    Il est aussi possible d’utiliser le Lync Management Shell via la commande:

      set-CsmeetingConfiguration avec les paramètres –LogoURL –Legalurl –helpURL –CustomFooterText.
      Une fois la configuration réaliser, les champs sont appliquer et les demandes de meeting prennent en compte les paramètres fixés:
    image Vous pouvez stocker les images directement sur le server FrontEnd Lync Server.

Interaction Powershell - Exchange Web Services

Introduction

Avec Exchange 2010, pour certains besoins bien spécifiques, il se peut que les cmdlets Powershell soit limitées. Cependant, il existe aussi les Exchanges Web Services. Bien entendu, quand on parle des Exchange Web Services, on pense au C# et à un développement complexe. Cependant, on n'oublie souvent que Powershell permet d'exécuter du C#.
Il sera donc question d'accéder aux EWS via Powershell. Il s'agit surtout d'une introduction car les possibilités de scripting sont infinies. L'exemple mis en œuvre dans cet article montrera comment accéder à un dossier bien spécifique pour le purger suivant les dates de réception des emails. Cela permettra entre autres de voir le langage AQS permettant la recherche d'objets dans une boîte aux lettres Exchange.

Prérequis

Avant toute chose, pour manipuler l'API Exchange Web Services, il est nécessaire d'installer le package correspondant sur le poste qui exécutera le script. Il est trouvable en suivant ce lien : http://www.microsoft.com/en-us/download/details.aspx?id=28952

Attention si vous utilisez, Exchange 2013, il faut prendre cette version :
http://www.microsoft.com/en-us/download/details.aspx?id=35371

Il sera ensuite nécessaire d'ajouter dans chacun des scripts qui sera réalisé la dll permettant d'interagir avec les Web Services. Pour rappel, cela se réalise via la commande Powershell Add-Type :

001
002
003
Add-Type -path "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"


AQS ou Advanced Query Syntax:

Le langage AQS permet de réaliser des recherches dans les objets d'une boîte aux lettres Exchange. Il est très simple à prendre en main.

Pour comprendre toutes les possibilités de ce langage voici le lien MSDN dédié :
http://msdn.microsoft.com/en-us/library/ee693615.aspx

Grâce à ce langage il va être possible de rechercher des éléments :
- par type (emails, réunions, notes, contacts, ...)
- par date (réception ou envoi)
- par propriété d'un email (champ from, to, cc, subject, body, ...)

L'exemple suivant permet de rechercher des emails ayant été reçu le 3 Septembre 2013 :
"Kind:email AND Received:03/09/2013"

On remarque l'opérateur AND qui permet de prendre en compte 2 propositions. Il en existe d'autres comme le OU (l'une ou l'autre des propositions) et le NOT (l'inverse d'une proposition).

Script commenté

Il s'agit ici d'un script où l'utilisateur se connecte à une boîte aux lettres sur laquelle il possède des droits et dont les messages du dossier nommé Personnel seront supprimées s'ils datent de plus de 30 jours. Aussi, pour chaque dossier, il affiche la taille de celui-ci en Ko. Cette dernière opération est aussi faisable via la commande EMS Get-MailboxFolderStatistics mais avec cette exemple nous n'aurons pas besoin d'installer ces outils mais seulement l'API EWS beaucoup plus légère.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
#Mailbox à traiter
$MailboxName = 'j.dupont@myenterprise.fr'

# A installer avant : www.microsoft.com/en-us/download/details.aspx?id=28952
try{
    Add-Type -path "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"
}catch{

}

#On spécifie la version des web services
$Version = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2
$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($version)

#On utilise les credentials avec lesquels on est connecté
$Service.UseDefaultCredentials = $true

#On récupère la configuration Autodiscover pour se connecter à la BAL
$Service.AutodiscoverUrl($MailboxName,{$true})

#On récupère l'ID du dossier
$RootFolderID = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Root,$MailboxName)

#On se connecte au dossier via la connexion que l'on a initialisé
$RootFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service,$RootFolderID)

#On limite le nombre de dossier à analyser à 1000 (sinon problème de throttling)
$FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000)

#On définit un ensemble de propriété à récupérer en même temps que nos dossiers
$PropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
#On crée une propriété de type taille de dossier
$SizeObject = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(3592,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Long)
#On l'ajouter à notre vue de dossier afin que la taille soit aussi récupérée.
$PropertySet.Add($SizeObject); 
$FolderView.PropertySet = $PropertySet;

#On spécifie qu'on analyse l'intégralité de la hiérarchie
$FolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep

#On calcule la date d'il y a 30 jours et on la met au format dd/MM/yyyy
$DateOld = ((Get-Date).AddDays(-30)).ToString("dd/MM/yyyy")

#On récupère tous les dossiers
$Response = $RootFolder.FindFolders($FolderView)
#Pour chaque dossier
ForEach ($Folder in $Response.Folders) {
   
    $FolderSize = $null
    #Si la taille est disponible alors on l'export dans la variable $FolderSize
    if($Folder.TryGetProperty($SizeObject,[ref] $FolderSize)){
        $FolderSizeValue = ([Int64]$FolderSize)/1000 
        #On affiche la taille du dossier
        $Message = "Le dossier " + $Folder.DisplayName + " a une taille de $FolderSizeValue Ko"
        Write-Host $Message
    }else{
        $Message = "Taille du dossier " + $Folder.DisplayName +" introuvable."
        Write-host $Message
    }

    #On compare le display name avec la valeur recherchée
    if($Folder.DisplayName -eq "Personnel"){
        #Si le dossier est bien Personnel alors on récupère tous les mails selon les critères de date définies
        $Items = $Folder.FindItems("Kind:email AND Received:<$DateOld",$ItemView) 
        #Pour chaque email trouvée
        ForEach($Item in $Items){
            #On le supprime définitivement (à décommenter pour que ce soit effectif)
            #$Item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)
        }
    }
}

 

On remarque l’opérateur “<” (inférieur à) dans la requête AQS qui permet de spécifier tout ce qui se trouve avant cette date.

On peut accéder aux dossiers publics, modifier, supprimer, créer, tout type d'objet y compris des dossiers. Il est aussi possible de récupérer différentes informations comme la taille d'un dossier. Il est aussi possible d'analyser les pièces jointes pour supprimer celle dont l'extension est d'un certain type. Il est donc possible d'imaginer plein de scripts comme des tâches planifiées effectuant des traitement sur des boîtes aux lettres.

Symantec Endpoint Protection Manager – Reset Password

Problématique

Si il vous arrive d’oublier votre mot de passe utilisé pour l’accès à la console Symantec Endpoint Manager, il peut être bien pratique de rétablir les identifiants par défaut.

De plus, l’accès à la console SEP Manager est sécurisé par un système qui bloque pour une durée de temps variable l’authentification dès que plusieurs authentifications ont échouées.

Procédure

  • Tout d’abords vérifier que les services utilisé par SEP sont bien lancé, si ce n’est pas le cas, les démarrer puis retenter l’authentification,
  • Ouvrir un explorateur de fichier,
          • Se placer dans C:\Program Files\Symantec\Symantec Endpoint Protection Manager\Tools
          • Exécuter en tant qu’administrateur le script Resetpass.bat
          • Les identifiants ont étés remis par défaut soit : admin/admin
          • Le log scm-server-0.log situé dans C:\Program Files\Symantec\Symantec Endpoint Protection Manager\Tomcat\Logs enregistre tout les évènements d’échec d’authentification, pratique pour troobleshooter un problème. 

Manipuler les enregistrements DNS en Powershell 2

Problème rencontré

Lors d'un changement complet du plan d'adressage des serveurs d’un datacenter, il était nécessaire de changer les enregistrements DNS. Au delà des enregistrements NS des serveurs DNS, il fallait aussi mettre à jour l'intégralité des enregistrements statiques A et PTR. Il était nécessaire de proposer une solution qui soit simple à mettre en œuvre (peu d’intervention utilisateur), puisque près de 600 enregistrements était à modifier. Il n'était pas faisable de faire cela manuellement.

Solution proposée

Comme indiqué dans l'intitulé, il a été choisi que cette opération serait réalisée par un script Powershell. Actuellement, il y a encore peu de parcs informatique utilisant Powershell 3 avec le module DNS pour Windows 8/2012. Le module DNS fournit par Powershell 3 peut donc seulement être utilisé dans des cas très limités. La solution proposée utilisait les classes WMI. Il s'agissait ensuite de loguer un maximum d'informations pour avoir un maximum de contrôle sur les modifications apportées.

Les classes WMI

Voici un listing des classes WMI pour les enregistrements DNS les plus courants :
- Enregistrements PTR : MicrosoftDNS_PTRType
- Enregistrements A : MicrosoftDNS_AType
- Enregistrements CNAME : MicrosoftDNS_CNAMEType
- Enregistrements MX : MicrosoftDNS_MXType
- Enregistrements NS : MicrosoftDNS_NSType

Récupération d'enregistrements DNS

Voici un exemple de récupération d'un enregistrement A.

On déclare la zone dans laquelle on veut effectuer la recherche.

001
002
$DNSZone = "myenterprise.lan"

 

On définit le serveur DNS sur lequel on effectue la recherche.

001
002
$DNSServer = "SRVDNS01" 

 

On cherche l'enregistrement via l'attribut OwnerName qui est le nom DNS complet.

001
002
$OwnerName = "SRV01.$DNSZone" 

 

On utilise une requête WMI sur le serveur DNS avec un filtre sur la zone et l'enregistrement à chercher.

001
002
003
004
$Record = Get-WMIObject -Computer $DNSServer `
-Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_AType" `
-Filter "ContainerName='$DNSZone' AND OwnerName='$OwnerName'" 

Si l'on souhaite obtenir toutes les propriétés de cet enregistrement et notamment voir les autres attributs sur lesquels on peut effectuer une recherche il suffit d'appeler la variable : $Record

Mis à jour d'enregistrements DNS :

En reprenant l'enregistrement précédent, on peut rapidement modifier son addresse IP (ou TTL) via la méthode Modify().

001
002
$NewRecord = $Record.Modify($Record.TTL, "10.0.1.1") 

 

Détecter si un enregistrement est dynamique :

Aussi, il peut être intéressant de ne mettre à jour que les enregistrements statiques. On peut détecter les enregistrements dynamiques via leur timestamp qui n'est pas nulle :

001
002
003
004
if($Record.Timestamp -ne 0){ 
    $NewRecord = $Record.Modify($Record.TTL, "$newRecordAddress") 
} 

Il suffit donc juste d'utiliser une structure conditionnelle si sinon sur l'attribut timestamp de notre enregistrement DNS.

Exemple avec un enregistrement PTR :

Pour réaliser cette opération on réutilise les variables $DNSServer, $DNSZone et $OwnerName déclarées plus haut et définir la zone où chercher l'enregistrement PTR.

001
002
$DNSZonePTR = "10.in-addr.arpa" 

 

La syntaxe pour rechercher un enregistrement PTR est similaire. Seuls la classe WMI et le champ de recherche (PTRDomainName au lieu de Ownername).

001
002
003
004
$PTRRecord = Get-WMIObject -Computer $DNSServer `
-Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_PTRType" `
-Filter "ContainerName='$ZonePTR' AND PTRDomainName='$OwnerName.'" 

 

Attention, il n'est pas possible de modifier l'IP d'un enregistrement PTR, il faut d'abord supprimer l'enregistrement puis le recréer.

Avant, on récupère la TTL pour la réutiliser afin qu'elle soit identique lors du nouvel enregistrement :

001
002
$TTL = $PTRRecord.TTL 

 

On supprime l'enregistrement DNS en supprimant l'objet WMI

001
002
$PTRRecord | Remove-WmiObject 

 

On déclare la nouvelle valeur de notre enregistrement. Si IP vaut 10.B.C.D dans la zone "10.in-addr.arpa" alors celui-ci vaudra D.C.B.10.in-addr.arpa

001
002
$PTROwnerName = "1.1.0.10.in-addr.arpa"

 

On déclare le type de notre enregistrement, ici PTR :

001
002
003
$PTRTypeClass = [WMIClass]"\\$DNSServer\root\MicrosoftDNS:MicrosoftDNS_PTRType" 

$PTRNewRecord = $PTRTypeClass.CreateInstanceFromPropertyData("$DNSServer.myenterprise.lan",$ZonePTR,$PTROwnerName,$null,$TTL,"$OwnerName.") 

 

Le 4ème attribut est dénommé record class : par défaut il s'agit de IN. La valeur à insérer est 1 ou $null.

Exemple sous Powershell v3 avec module DNS :

Pour terminer, voici comment réaliser les mêmes opérations (Récupération/Mis à jour d'enregistrements DNS) avec le module DNS Powershell v3. Il faut posséder un poste sous Windows 8/2012 pour exécuter ses commandes et avoir installé l'outil de gestion des serveurs DNS (via les outils d'administration).

On commence par déclarer la zone, le serveur DNS et le nom de l'enregistrement :

001
002
003
004
005
$DNSZone = "myenterprise.lan" 
$DNSServer = "DNS01" 
$RecordName = "SERV01" 
$NewRecordAddress = "10.0.1.1" 

 

Le type est renseigné dans le paramètre RRType. Attention, il est important de stocker l'objet dans une variable car nous allons le réutiliser pour le modifier.

001
002
003
$Record = Get-DnsServerResourceRecord -ZoneName "$DNSZone" -Name "$RecordName" `
-RRType "A" -ComputerName "$DNSServer" 

 

Pour valider les modifications nous aurons besoin de l'enregistrement DNS avant et après sa mise à jour. Il faut donc réaliser une deuxième récupération de l'enregistrement DNS dans une autre variable.

001
002
003
$NewRecord = Get-DnsServerResourceRecord -ZoneName "$DNSZone" -Name "$RecordName" `
-RRType "A" -ComputerName "$DNSServer" 

 

Ensuite, il faut modifier la propriété qui nous intéresse, ici l'adresse IP.

001
002
$NewRecord.RecordData.IPv4Address.IPAddressToString = "$NewRecordAddress" 

 

Enfin, on enregistre les modifications en passant les 2 objets (avant et après modification), la zone et le nom du serveur DNS :

001
002
003
Set-DnsServerResourceRecord -NewInputObject $NewRecord -OldInputObject $Record -ZoneName "$DNSZone" `
-ComputerName "$DNSServer" 

SQL Server : BULK INSERT – Msg 4861 - Operating system error code 5

Problématique

Dans certains cas nous somme amené à utiliser l’instruction BULK INSERT pour injecter dans une table des enregistrements qui proviennent d’un fichier texte stocké sur un partage réseau

Supposons maintenant que nous disposons de 3 serveurs :

  • 1 contrôleur de domaine DC01
  • 2 serveurs SQL 2008 R2 SQL01 et SQL02, le serveur SQL01

Dans le premier scénario nous allons exécuter une requête BULK INSERT sur le serveur SQL01 qui injectera dans la table #TEST les lignes d’un fichier texte nommé ListCustomers.txt accessible via le chemin UNC \\SQL01\FILES\Input

Dans ce premier scénario la requête aboutit sans aucun problème  

image

Dans le deuxième scénario nous allons exécuter une requête BULK INSERT sur le serveur SQL01 mais depuis le serveur SQL02 qui injectera dans la table #TEST les lignes d’un fichier texte nommé ListCustomers.txt accessible via le chemin UNC \\SQL01\FILES\Input

Dans ce deuxième scénario la requête aboutit sans aucun problème

image

Dans le troisième scénario nous allons exécuter une requête BULK INSERT sur le serveur SQL01 mais depuis le serveur SQL02 qui injectera dans la table #TEST les lignes d’un fichier texte nommé ListCustomers.txt accessible via le chemin UNC \\SQL02\FILES\Input

Dans ce troisième scénario une erreur est générée, en effet l’instruction BULK INSERT n’arrive pas à ouvrir le fichier source pour y lire les enregistrements !

image 

Le message complet de l’erreur peut être:

 image

Explication

L’erreur enregistrée dans le scénario 3 est dû au fait que lorsqu’un utilisateur se connecte à SQL Server avec l’authentification Windows il n’est autorisé à lire que les fichiers accessibles par le biais de son compte utilisateurs, quelque soit le profil de sécurité du processus SQL Server.

Résolution

Pour remédier à ce problème on pourra procéder de deux manières, soit qu’on utilise une connexion SQL Server au lieu de l’authentification Windows soit configurer Windows pour activer la délégation des comptes de sécurité.

Pour la configuration de Windows il faudra procéder comme suit :

Supposons  que le compte de service utilisé pour le démarrage du service SQL sur le serveur  SQL01 est SvcSQL01 alors il faudra créer un SPN sur ce compte en utilisant la commande suivante :

SETSPN –A MSSQLSvc/SQL01.domain.lan:1433 DOMAIN\SvcSQL01

Pour vérifier que l’SPN a été bien créé on peut exécuter la commande suivante :

SETSPN –L DOMAIN\SvcSQL01

    image

Une fois le nom principal de service créé il faudra approuver le compte SvcSQL01 à la délégation et le compte de la machine  SQL01 à la délégation, ceci se fait via la console Utilisateurs et Ordinateurs Active Directory

Attention : l’onglet “Delegation” n’apparaitra sur le compte SvcSQL01 qu’après avoir créé le nom principal de servie avec la commande SETSPN 

imageimage

On peut vérifier maintenant que la requête ne gènère plus d’erreur comme le montre la figure suivante.

l’exécution de la requête

SELECT session_id, auth_scheme FROM sys.dm_exec_connections nous permet de confirmer l’authentification utilisé pour nitre session est bien KERBEROS 

image

Remarque

Nous avons pu remarquer que si nous créons le nom principal de service avec le nom de l’instance et non le numéro de port d’une instance nommée l’erreur 4861 persiste, il a fallut fixer le port utilisé par l’instance et l’utiliser pour la configuration du nom principal du service lié au compte de service SQL. 

Quest Resource Updating Manager : The RPC server is unavailable

Introduction

La phase de réacélisation d’un serveur est utile lorsque vous avez migré des comptes ou groupes d’un domaine à un autre. Les ACL d’un dossier sont généralement associé à un groupe, lors du déplacement du groupe dans l’autre domaine, l’ACL n’est pas traduite automatiquement. Pour ce faire on utilise un logiciel tel que Quest Migration Manager, plus exactement Quest Resource Updating Manager pour traiter par lot des serveurs contenant des ACL (serveurs de fichiers par exemple).

Lors de la réacélisation d’un parc de serveurs, j’ai été confronté à l’erreur “The RPC Server is unavailable”. Après avoir longtemps cherché, voici les points clés pour résoudre cette erreur.

Résolution

  1. Réinitialiser le serveur cible depuis la console Quest

Exécutez une tache “Cleanup” sur les serveurs cible impactés par cette erreur. Cela aura pour effet de supprimer l’agent installé automatiquement.

  1. Activer NetBIOS over TCP/IP

Pour ce faire, dans les propriétés de la carte réseau, propriétés TCP/IPv4, Avancée…, onglet WINS, choisissez l’option Enable NetBIOS over TCP/IP.

  1. Les règles de pare-feu pour RPC

Le must est de désactiver le pare-feu le temps du traitement. Si ce n’est pas possible, veillez a ce que les règles Remote Administration (RPC) et Remote Service Management (RPC) soient activées dans le profil de votre carte réseau.

  1. Le service RPC

Démarrez le service Remote Procedure Call (RPC).

  1. Le fichier HOST

Dans le fichier HOST de la machine à traiter, ajoutez l’adresse IP et le nom du serveur Quest.

  1. L’agent

L’installation manuelle de l’agent Quest peut aider. En effet j’ai pu remarquer que l’agent déployé automatique via la tâche Discovery ne se lançait pas. Depuis le serveur à traiter, accédez au dossier d’installation de Quest RUM (C:\Program Files (x86)\Common Files\Aelita Shared\Migration Tools\Resource Updating) et installez le package QsResourceUpdatingAgent.msi. Ne pas oublier de changer le compte de service pour le faire correspondre au compte de service Quest, autrement vous aurez l’erreur Access Denied.

Points de vérification :

  1. Sur le serveur cible, exécutez la commande “nbtstat –a <IP_du_serveur_Quest>”. Vous devez obtenir un résultat. Si vous obtenez “Host not found”, vérifiez les points ci dessous.
  2. Dans la console Quest, lancez la tâche Discovery. Vous devez obtenir un statut OK, sans erreur ni avertissements. Une fois que vous avez le statut OK, lancez la tâche de Processing. Patientez et normalement vous devriez voir la progression et un statut OK une fois la tâche terminée.

Active Directory – Gestion des photos d’identités

L’annuaire “Active Directory” permet d’ajouter une photo afin d’identifier un utilisateur

via des clients tel que Outlook ou Lync.

Pour la gestion des photos on peut s’aider d’utilitaire tel que CodeTwo Active Directory Photos.

On peut récupérer cet outils ici :

https://www.codetwo.com/freeware/active-directory-photos/

L’installation est très simple:

clip_image002

clip_image004

clip_image006

clip_image008

clip_image010

L’utilisation est très simple également.

clip_image012

La photo est “stockée” dans l’attribut “thumbnailPhoto”

clip_image013

Il est important que cet attribut soit répliqué.

A vérifier selon la version d’Exchange.

clip_image015

Ajoutez les photos des collaborateurs.

clip_image017

clip_image019

L’attribut “thumbnailPhoto” est renseigné.

clip_image021

Et voilà le résultat sous Outlook.

clip_image022

Template VHD pour HYPER-V

Lors de la mise au point d’une maquette sur un poste portable, il est pratique d’avoir en local des templates au format VHD. Dans ce post nous verrons comment créer des templates au format VHD ainsi que comment les déployer à l’aide d’HYPER-V.

Créer un template au format VHD

Tout d’abords il faut créer une machine virtuelle avec l’OS désiré pour le template, il est également pertinent de passer les derniers patchs ainsi que d’installer la dernière version des services d’intégrations HYPER-V. Il est également possible d’installer des applications qui seront utiles au master.

    • Un fois la VM prête pour être transformée en template, il serait judicieux d’éteindre la VM et d’en copier le VHD (avant l’exécution du sysprep) afin de pouvoir recréer le Template si celui-ci venait à être mis à jour.
    • Après avoir démarré la VM, il faut maintenant exécuter le sysprep sur celle ci en prenant bien soir de cocher la case generalize afin de générer un nouvel SSID lors de l’utilisation du template.

image

  • Une fois la VM éteinte, il faut en copier le VHD vers l’emplacement souhaité, il est par ailleurs préférable d’ ajouter l’attribut Read-Only au VHD généré.

Utiliser un template VHD dans HYPER-V

En utilisant HYPER-V, il est très simple de déployer un OS à l’aide d’un VHD, pour ce faire il suffit de suivre l’assistant de création d’une machine virtuelle et une fois arrivé à la page Connect Virtual Hard Disk il faut utiliser un VHD existant et ne pas laisser HYPER-V en créer un automatiquement :

image