PI Services

Le blog des collaborateurs de PI Services

Supervision – Script de corrélation a la seconde

 

Une demande m’a été faite récemment pour la détection de l’occurrence de deux events distinct a la même seconde, ce cas particulier traduisant un problème de sécurité spécifique.

Indépendamment de l’objectif final, il s’agit d’un cas intéressant auquel le script ci-dessous a répondu. Il contient des éléments propre a l’api scom mais peux bien sur être adapté pour être utilisé indépendamment.

 

 

  ##############################################################
### SCRIPT TO DETECT SPECIFIC TWO EVENTS OCCURING AT SAME TIME #####
##############################################################

# PARAMETERS:
### $EventLog: Event Log to look in
### $EventSource: Event Source to search for 

### $FirstEventId: First event to correlate

### $SecondEventId: second event to correlate

### $LastMinutes: Last Time Window to search in
### $DayOfWeekToExclude: Day Of Week To Exclude (Example: "('Saturday','Sunday')" )




param(
$Arguments,
$EventLog,
$EventSource,
$FirstEventId,
$SecondEventId,
$LastMinutes,
$DayOfWeekToExclude
)

$ScriptName = "CorrelateTwoSpecEvent.ps1"

#FUNCTIONS


#Check for the existence of an event source with script name in operation manager eventlog to log some events 
        
Function NewEventSource
 
        
{
 
        
if(!(Test-Path "HKLM:\SYSTEM\CurrentControlSet\services\eventlog\Operations Manager\$ScriptName"))
 
        
{
 
        
New-EventLog -LogName "Operations Manager" -Source $ScriptName
 
        
}

        
} 

#END FUNCTIONS


#Log of script execution 
NewEventSource
 
write-eventlog -logname "Operations Manager" -Source $ScriptName -EventID 1000 -Message "Execution du script $ScriptName" -EntryType Information
 


# Create local variables from override value

.([Scriptblock]::Create($Arguments))

# Determine the moment in the week
if ((Get-date).DayOfWeek -in $DayOfWeekToExclude)
{
# If the day is in $DayOfWeekToExclude -> NO ACTION - END OF SCRIPT
Write-Host "$((Get-date).DayOfWeek) : NO ACTION - END OF SCRIPT"
Exit 0

}

# Create the Scom property bag
$ScomAPI = New-Object -comObject "MOM.ScriptAPI"
$PropertyBag = $ScomAPI.CreatePropertyBag()



$Message =     "SEARCH CRITERIAS: Log: $EventLog - Source: $EventSource - EventId: $FirstEventId or $SecondEventId `n"
$Message


try
{
New-Variable -Name "$($FirstEventId)_Events" -Force -Value $(Get-WinEvent -ErrorAction SilentlyContinue -FilterHashtable @{logname=$EventLog;ProviderName=$EventSource;id=$FirstEventId;StartTime=$(get-date).AddMinutes(-$LastMinutes)})
New-Variable -Name "$($SecondEventId)_Events" -Force -Value $(Get-WinEvent -ErrorAction SilentlyContinue -FilterHashtable @{logname=$EventLog;ProviderName=$EventSource;id=$SecondEventId;StartTime=$(get-date).AddMinutes(-$LastMinutes)})
}
catch
{
$Message = "Error during retrieve of events in the $ScriptName script"
$Message

NewEventSource
Write-EventLog -LogName "operations manager" -Source $ScriptName -EventId 1001 -EntryType Warning -Message "$Message"
Exit 1

}

#If no one of the two events id have occurence no need to continue
if (!$(Get-Variable "$($FirstEventId)_Events").Value -and !$(Get-Variable "$($SecondEventId)_Events").Value)
   
{
   
$Message =  "No one of the two events id have occurences in last $LastMinutes minutes - END OF SCRIPT"
   
$Message

   
Write-EventLog -LogName "operations manager" -Source $ScriptName -EventId 1002 -EntryType Information -Message "$Message"

   
Exit 0

   
}


#If Only one of the two events id have occurences no need to continue
if (!$(Get-Variable "$($FirstEventId)_Events").Value -or !$(Get-Variable "$($SecondEventId)_Events").Value)
   
{
   
$Message = "Only one of the two events id have occurences - END OF SCRIPT"
   
$Message

   
Write-EventLog -LogName "operations manager" -Source $ScriptName -EventId 1003 -EntryType Information -Message $Message

   
Exit 0
   
}



$Message = "$($(Get-Variable "$($FirstEventId)_Events").Value.count) occurence of event $FirstEventId and $($(Get-Variable "$($SecondEventId)_Events").Value.count) occurence of event $SecondEventId in the last $LastMinutes minutes"
$Message +=
"`nSTART OF COMPARAISON...`n"
#$Message



#Compare DateTimes at second level
try
{
$CompareResult = Compare-Object -ReferenceObject $(Get-Variable -Name "$($FirstEventId)_Events").Value.timecreated.second -DifferenceObject $(Get-Variable -Name "$($SecondEventId)_Events").Value.timecreated.second -ExcludeDifferent -IncludeEqual -Verbose
}
catch
{
$Message += "Error during comparaison of Date Creation"
$Message

NewEventSource
Write-EventLog -LogName "operations manager" -Source $ScriptName -EventId 1004 -EntryType Warning -Message $Message
Exit 1
}

#If $CompareResult is null, Events have not occureat the same time
If (!($CompareResult))
   
{
   
$Message += "Events $FirstEventId and $SecondEventId have not occured at the same second - No correlation"
   
$Message

   
NewEventSource   
   
Write-EventLog -LogName "operations manager" -Source $ScriptName -EventId 1004 -EntryType Information -Message $Message
   
   
exit 0

   
}

Else
   
{
   
NewEventSource
   
#
   
$Message += "EVENT $FirstEventId and $SecondEventId have occured at same second $($CompareResult.count) times `n"
   
$Message +=
"`nEVENTS OF LAST $LastMinutes MINUTES:`n"
       
   
$Message += $(Get-Variable "$($FirstEventId)_Events").value | foreach {$_} | Out-String
 
   
$Message += $(Get-Variable "$($SecondEventId)_Events").value | foreach {$_} | Out-String

   
$Message
   
Write-EventLog -LogName "operations manager" -Source $ScriptName -EventId 1005 -EntryType Information -Message $Message
   
$PropertyBag.AddValue("State","CRITICAL")
   
$PropertyBag.AddValue("Message",$Message)
   
   
$PropertyBag
   
}


 
 

[Powershell] CredSSP : Credential Security Service Provider.

CredSSP qu'est ce que c'est ?

CredSSP : Credential Security Service Provider.

A quoi cela sert-il ?

A déléguer des identifiants pour une session distante, plus précisément, CredSSP vous permet de fournir une authentification de bout en bout au travers de plusieurs sessions distantes.

Exemple :

Depuis un Serveur A un script Powershell ouvre une session distante sur un Serveur B, ce dernier traite ses instructions puis ouvre une session distante pour requêter un Serveur C et y déposer ses résultats sur un partage.

Lors de l'ouverture de la session distante entre A et B Windows utilise les identifiants fournis, mais lors de l'ouverture de la session distante depuis B vers C, Windows considère qu'il s'agit d'une usurpation Kerberos (car par défaut WinRm n'autorise pas la délégation des identifiants).

Afin de palier  cela que ce soit pour un "Invoke-Command" ou un "New-PSSession" vous devrez ajouter "-Authentication CredSSP"; cet ajout vous permettra de déléguer les identifiants pour la seconde session distante.

Mise en oeuvre :

Et non, on ne peut pas utiliser l'option CredSSP sans prérequis, voici ceux à mettre en place.

Sur le Serveur A on va activer CredSSP "Client" via la commande suivante :

Enable-WSManCredSSP -Role Client -DelegateComputer ServerB.mondomaine.com -Force

On peut vérifier que cela à bien fonctionné à l'aide de la commande suivante :

Get-WSManCredSSP

Puis sur le Server B on va activer CredSSP "Server" via la commande suivante :

Enable-WSManCredSSP -Role Server -Force

vérifions.

Et voilà nous devrions donc pouvoir exécuter la commande initiale depuis le serveur A, vérifions cela sans oublier d'ajouter "-Authentication CredSSP".

Enter-PSSession -ComputerName lab01-wsus1.LAB.ORG -Credential Lab\Adminmad -Authentication Credssp

Jusque la tout fonctionne, essayons donc maintenant de requêter vers le serveur C.

Invoke-Command -ComputerName Lab01-wsus2.lab.org -ScriptBlock {Get-WindowsFeature | Where-Object {$_.Name -like "UpdateServices"}}

C'est bien fonctionnel, bien entendu comme ce changement est lié à la sécurité, il est préconisé de désactiver cette option après usage.

On peut utiliser les commandes :

Disable-WSManCredSSP –Role Client # Sur le serveur A
Disable-WSManCredSSP –Role Server # Sur le serveur B

Ou directement depuis le serveur A :

Invoke-Command –ComputerName ServerB –ScriptBlock { Disable-WSManCredSSP –Role Server }
Disable-WSManCredSSP –Role Client

 

Annexes :

Vous pouvez aussi le faire sur plusieurs Serveurs : 

Enable-WSManCredSSP -Role "Client" -DelegateComputer "ServerB.mondomaine.com", "ServerC.mondomaine.com", "ServerD.mondomaine.com" -Force

Ou sur toutes les machines du domaine :

Enable-WSManCredSSP -Role "Client" -DelegateComputer "*.mondomaine.com" -Force

 Pour plus d'informations:

https://docs.microsoft.com/en-us/powershell/module/microsoft.wsman.management/enable-wsmancredssp?view=powershell-6 

https://msdn.microsoft.com/en-us/library/windows/desktop/bb931352(v=vs.85).aspx

Stratégies de groupe : Analyse du fichier gpsvc.log - Paramètres CSE (Partie 3/3)

Bonjour,

Après un second article sur l'analyse de ce fichier, voici un troisième complétant celle-ci et traitant plus spécifiquement des paramètres CSE.

Les paramètres CSE

Les paramètres CSE sont également appelés Client Side Extensions.

Ils correspondent à des fichiers DLL installés sur les clients stratégies de groupe et sont capables d'interpréter les paramètres contenus dans les stratégies. Vous pouvez voir la liste complète des extensions présentes sur votre poste en allant dans la clé registre suivante : HKEY_LOCAL_MACHINE/Software/Microsoft/Windows NT/CurrentVersion/Winlogon/GPExtensions

Deux types de traitements existent :

  • Background
  • Foreground

Le traitement de type Background concerne tous les paramètres CSE pouvant être modifiés sans impact pour l'utilisateur sur son poste.

Le traitement de type Foreground concerne tous les paramètres ne pouvant pas être traités en arrière-plan, les plus connus étant les paramètres Folder Redirection, Software Installation et GPP Drive Mapping. Le mode Foreground est activé uniquement au démarrage d'un poste ou lors de l'ouverture d'une session par utilisateur.

Traitement des paramètres CSE

Le traitement de ces paramètres est repérable dans la section suivante :

GPSVC(274.22f8) 11:11:30:216 ProcessGPOs: Both user and machine lists are defined. Merging them together.
GPSVC(274.22f8) 11:11:30:720 NlaQueryNetSignatures returned 1 networks
GPSVC(274.22f8) 11:11:30:720 Estimated bandwidth on one of the connections : 0 kbps
GPSVC(274.22f8) 11:11:30:721 Estimated bandwidth on one of the connections : 718611 kbps
GPSVC(274.22f8) 11:11:30:721 ReadExtStatus: Reading Previous Status for extension {35378EAC-683F-11D2-A89A-00C04FBBCFA2}

[...]

GPSVC(274.22f8) 11:11:30:761 ProcessGPOs: -----------------------
GPSVC(274.22f8) 11:11:30:761 ProcessGPOs: Processing extension Group Policy Environment
GPSVC(274.22f8) 11:11:30:761 CompareGPOLists: The lists are the same.
GPSVC(274.22f8) 11:11:30:761 CompareGPOLists: The lists are the same.
GPSVC(274.22f8) 11:11:30:762 CheckGPOs: No GPO changes but couldn't read extension Group Policy Environment's status or policy time.

On peut remarquer que :

  • L'état précédent de l'extension est évalué en premier
  • La valeur hexadécimale retournée pour indiquer quelle extension est analysée correspond à la liste des extensions présente dans le registre dans la clé GPExtensions
  • Dans le cas d'un rafraîchissement périodique des GPO (Background Processing), une comparaison est effectuée afin de détecter les changements qui auraient été effectués depuis le dernier rafraîchissement. On remarque bien que les paramètres ne sont pas réapliqués de nouveau.

Nous allons voir ici un dernier exemple, lorsqu'un Foreground Processing est effectué (ouverture d'une session utilisateur) :

GPSVC(274.178c) 09:29:22:013 ProcessGPOList: Entering for extension Registre
GPSVC(274.178c) 09:29:22:013 UserPolicyCallback: Setting status UI to Application de la stratégie Registre...

GPSVC(274.178c) 09:29:22:029 ResetPolicies: Entering.
[...]
GPSVC(274.178c) 09:29:22:029 ParseRegistryFile: Entering with <C:\Users\XXX\ntuser.pol>.
GPSVC(274.178c) 09:29:22:029 DeleteRegistryValue: Deleted Software\Policies\Microsoft\Cryptography\AutoEnrollment\
[...]
GPSVC(274.178c) 09:29:22:169 ParseRegistryFile: Entering with <\\contoso.com\sysvol\contoso.com\Policies\{E29B2A23-1589-4A05-A637-B83976319901}\User\registry.pol>.
GPSVC(274.178c) 09:29:22:169 SetRegistryValue: NoWelcomeScreen => 1 [OK]
GPSVC(274.178c) 09:29:22:169 SetRegistryValue: ForceStartMenuLogOff => 1 [OK]
GPSVC(274.178c) 09:29:22:169 SetRegistryValue: AEPolicy => 7 [OK]
 
On remarque les éléments suivants :
  • Le fichier des paramètres registre locaux (ntuser.pol) est analysé
  • Une suppression de tous les paramètres registre présents est effectuée
  • Une lecture du fichier des paramètres registre (registry.pol) pour chaque GPO est faite
  • Le paramètre correspondant est appliqué dans le registre
  • Une réapplication complète des paramètres utilisateurs registre est donc effectuée

Logs supplémentaires pour les paramètres CSE

Afin de pouvoir pousser les investigations encore plus loin, il est possible d'activer des fichiers de logs supplémentaires pour chaque extension CSE. Voici les principaux :

Scripts and Administrative Templates CSE Debug Logging (gptext.dll) HKLM\Software\Microsoft\WindowsNT\CurrentVersion\Winlogon

ValueName: GPTextDebugLevel 
ValueType: REG_DWORD 
Value Data: 0x00010002 
Options: 0x00000001 = DL_Normal 
0x00000002 = DL_Verbose 
0x00010000 = DL_Logfile 
0x00020000 = DL_Debugger

Log File: C:\WINNT\debug\usermode\gptext.log 

Security CSE WINLOGON Debug Logging (scecli.dll) 
KB article: 245422 How to Enable Logging for Security Configuration Client Processing in Windows 2000

HKLM\Software\Microsoft\WindowsNT\CurrentVersion\WinLogon\GPExtensions\{827D319E-6EAC-11D2- A4EA-00C04F79F83A

ValueName: ExtensionDebugLevel 
ValueType: REG_DWORD 
Value Data: 2 
Options: 0 = Log Nothing 
1 = Log only errors 
2 = Log all transactions

Log File: C:\WINNT\security\logs\winlogon.log

Folder Redirection CSE Debug Logging (fdeploy.dll) 
HKLM\Software\Microsoft\WindowsNT\CurrentVersion\Diagnostics

ValueName: fdeployDebugLevel 
ValueType: REG_DWORD 
Value Data: 0x0f

Log File: C:\WINNT\debug\usermode\fdeploy.log

Offline Files CSE Debug Logging (cscui.dll) 
KB article: 225516 How to Enable the Offline Files Notifications Window in Windows 2000 

Software Installation CSE Verbose logging (appmgmts.dll) 
KB article: 246509 Troubleshooting Program Deployment by Using Verbose Logging 
HKLM\Software\Microsoft\WindowsNT\CurrentVersion\Diagnostics

ValueName: AppmgmtDebugLevel 
ValueType: REG_DWORD 
Value Data: 0x9B or 0x4B

Log File: C:\WINNT\debug\usermode\appmgmt.log 

Software Installation CSE Windows Installer Verbose logging 
KB article: 314852 How to enable Windows Installer logging

HKLM\Software\Policies\Microsoft\Windows\Installer

ValueName: Logging 
Value Type: Reg_SZ 
Value Data: voicewarmup

Log File: C:\WINNT\temp\MSI*.log

Installation d'une instance sql server 2017 sur linux (ubuntu)

Introduction

Dans mon blog précédent  , j'ai expliqué comment lancer une instance SQL 2017 installée sur une image docker (linux) depuis Docker installé sous Windows. Dans ce blog, je vais détailler l'installation d'une instance SQL Server 2017 sur Linux. Microsoft SQL Server 2017 supporte les versions d'OS suivants:

  • Red Hat Enterprise Linux (7.3 or 7.4)
  • SUSE Linux Enterprise Server (v12 SP2)
  • Ubuntu (16.04)
  • Docker Engine (1.8+)

Attention: l'installation de sql server sur linux nécessite de 2 Gb de ram minimum et de la version de NFS 4.2 ou supérieur.

Installation de SQL Server 2017

Mise à jour de l'os

Avant de démarrer l'installation de SQL Server 2017, assurez vous que Ubuntu est bien à jour en exécutant les deux commandes suivantes:

sudo apt-get update
sudo apt-get upgrade

Installation de SQL Server 2017

Importer les clés GDP:

wget -qO- https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -

Enregistrer la repository Ubuntu de Microsoft SQL Server:

sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/16.04/mssql-server-2017.list)"

Exécuter les commandes suivantes pour l'installation de SQL Server 2017:

sudo apt-get update
sudo apt-get install -y mssql-server

A la fin de l'installation, exécuter la commande suivante pour configurer SQL Server:

sudo /opt/mssql/bin/mssql-conf setup

Entrer 1

Accepter les conditions d'utilisations et entrer le mot de passe SA.

L'installation et la configuration de SQL Server 2017 est finie:

Vérification du service SQL Server

Lancer la commande suivante:

systemctl status mssql-server

On constate que le service est bien démarré:

Tests

Utiliser SSMS pour se connecter à ce serveur:

 Exécuter la commande sql ci-dessus pour voir la version de SQL server qui a été installée.

 

Démarrer une instance MSSQL 2017 sous linux sur un conteneur Docker installé sous Windows

1. Objectif

L'objectif de ce blog est de démontrer comment lancer une instance MSSQL Server 2017 sous linux sur un conteneur Docker installé sous windows.

2. Installation de Docker

Télécharger la version de docker pour votre système d'exploitation depuis ce lien [https://docs.docker.com/install/#supported-platforms] . J'utilise la version de docker pour un windows 10 comme indiqué ci-dessous:

Avant d'installer Docker sous windows, assurez vous que hyper-v est installé. Docker utilisera hyper V pour monter une VM linux automatiquement pour faire tourner l'image contenant MSSQL server 2017 dans une conteneur Linux sous Windows.

Une fois l'installation terminée , lancer Docker depuis le bureau et l'icon ci-dessous apparaitra: 

Faire un clique droit puis "switch to linux containers" car l'image que nous allons faire tourner est une image linux:

On constatera que Docker a créé automatiquement une VM sous hyper-v, qui se nomme MobyLinux:

3. Téléchargement d'une image

Il existe une multitude d'image sur le portail https://hub.docker.com/ . Nous allons prendre l'image microsoft/mssql-server-linux [https://hub.docker.com/r/microsoft/mssql-server-linux/]

Pour télécharger l'image depuis powershell , tapper la commande suivante:

docker pull microsoft/mssql-server-linux

Pour afficher une image, tapper la commande suivante: 

docker image ls

On voit bien notre image microsoft/mssql-server-linux est présente dans la repository.

4. Démarrage de l'instance MSSQL Server 2017

Pour démarrer une instance MSSQL Server 2017 depuis l'image, tapper la commande suivante:

docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=yourStrong(!)Password' -p 1433:1433 -d microsoft/mssql-server-linux:2017-latest

Changer le mot de passe SA_PASSWORD et le port d'écoute au besoin. Une fois la commande passée, vérifier que l'image s'est bien créé et est démarrée avec la commande suivante:

docker ps

On voit bien que notre image a bien été créée et l'état est bien "up".

5. Tests

 

Lancer SQL Server Management Studio, puis entrer les informations suivants:

On arrive bien a se connecter à l'instance sql :

Tapper la commande suivante pour vérifier les informations du serveur sql:

select @@version
Microsoft SQL Server 2017 (RTM-CU3-GDR) (KB4052987) - 14.0.3015.40 (X64)   Dec 22 2017 16:13:22   Copyright (C) 2017 Microsoft Corporation  Developer Edition (64-bit) on Linux (Ubuntu 16.04.3 LTS)

Nous voyons bien qu'en étant sur localhost (windows), nous avons réussi à lancer une instance MSSQL Server 2017 installée sur un serveur Linux dans un conteneur Docker.

Stratégies de groupe : Analyse du fichier gpsvc.log (Partie 2/3)

Bonjour,

Après un premier article sur l'activation de ce fichier, voici un second sur l'analyse de celui-ci.

Vous pouvez le trouver dans le dossier C:\Windows\debug\usermode\gpsvc.log

Threads

Sur les machines avec des architectures multi-coeurs, il peut y avoir plusieurs threads qui s'exécutent au même moment (un thread pour les paramètres utilisateurs et un thread pour les paramètres machine.). Il peut être utile de savoir les différencier dans le fichier de log.

Pour se faire, il suffit d'analyser les valeurs rapportées pour GPSVC :

GPSVC(78d.666) 12:41:45:477 Caller requesting for user notification/lock is from session 0

On remarque que celles-ci sont composées de deux parties :

  • 78d : Correspond au PID (Process ID) (en héxadécimal)
  • 666 : Correspond au TID (Thread ID)

Début du traitement des stratégies

Le traitement des stratégies débute toujours avec les paramètres machine.

Il peut être repéré par l'enregistrement suivant :

GPSVC(2dc.18c) 11:40:08:707 bMachine = 1
GPSVC(2dc.18c) 11:40:08:707 Setting GPsession state = 1

Connectivité réseau

Immédiatement après le début du traitement des stratégies machines, une vérification de la connectivité réseau est faite :

GPSVC(2dc.18c) 11:40:08:707 bMachine = 1
GPSVC(2dc.18c) 11:40:08:707 Setting GPsession state = 1
GPSVC(2dc.520) 11:40:08:707 Waiting for connectivity before applying policies

Souvent, le client Stratégies de groupe démarre avant que la connectivité réseau soit effective, ce qui génère le message suivant :

GPSVC(2dc.18c) 11:40:08:806 There is no connectivity. Waiting for connectivity again …

Mais quelques secondes plus tard, la connectivité est établie :

GPSVC(2dc.18c) 11:42:09:106 There is connectivity
GPSVC(2dc.18c) 11:42:09:106 Wait For Connectivity : Succeded

GPSVC(2dc.18c) 11:42:09:106 We have network connectivity… proceeding to apply policy.

En cas de non connectivité (30 secondes de timeout par défaut), on trouvera toujours l'erreur suivante :

GPSVC(2dc.520) 11:45:10:033 Application complete with bConnectivityFailure = 1.

Note : Cela peut être une erreur de connectivité mais pas uniquement réseau, cela peut concerner du LDAP par exemple

Estimation de la bande passante

Avant de traiter les stratégies de groupe, une estimation de la bande passante est faite.

Celle-ci est calculée en se connectant d'abord à un contrôleur de domaine afin d'obtenir une liste de ceux-ci, puis en évaluant la vitesse de la connexion entre le poste et un contrôleur de domaine. Le calcul de la bande passante est effectuée par le NLA (Network Location Awarnesss).

Le début de l'estimation se présente comme ceci :

GPSVC(2cc.c28) 15:56:04:821 GetDomainControllerConnectionInfo: Enabling bandwidth estimate.
GPSVC(2cc.c28) 15:56:05:134 Started bandwidth estimation successfully

La fin de l'estimation se présente comme ceci :

GPSVC(2cc.c28) 15:56:05:510 IsSlowLink: Bandwidth Threshold (WINLOGON) = 500.
GPSVC(2cc.c28) 15:56:05:510 IsSlowLink: Bandwidth Threshold (SYSTEM) = 500.
GPSVC(2cc.c28) 15:56:05:510 IsSlowLink: WWAN Policy (SYSTEM) = 0.
GPSVC(2cc.c28) 15:56:05:510 IsSlowLink: Current Bandwidth >= Bandwidth Threshold.
 
On remarque que le seuil est de 500 kbps par défaut.

Ordre de traitement des stratégies

Les stratégies vont être traitées de manière hiérarchique dans l'ordre suivant :
1) Ordinateur Local
2) Sites AD
3) Domaines AD
4) OU Parentes
5) OU Enfants
 
Avec toutefois quelques exceptions :
  • Le lien d'un GPO peut être appliqué (enforced) ou/et désactivé
  • Une stratégie peut avoir des paramètres ordinateurs/utilisateurs désactivés
  • Le blocage de l'héritage au niveau de l'OU est activé
  • Le mode bouclage est activé
 
La règle à retenir est la suivante : C'est le dernier paramètre lu qui gagne
 
Exemple : Vous avez deux GPOs qui définissent une page de démarrage pour Internet Explorer.
Une est à la racine du domaine, l'autre dans une OU enfant.
Dans le fichier de log, le paramètre de la GPO étant à la racine du domaine sera traité en premier et le paramètre de la GPO étant dans une OU enfant sera traité en deuxième.
Le dernier paramètre lu étant celui qui est appliqué, ce sera donc le paramètre de la GPO étant située dans l'OU enfant qui sera appliqué.
 
Voici comment cela se présente dans le fichier de log :

Lecture des stratégies :

GPSVC(2dc.22b0) 17:16:01:922 SearchDSObject: Searching <OU=OU_Enfant,OU=OU_Parent,DC=contoso,DC=local>
GPSVC(2dc.22b0) 17:16:01:922 SearchDSObject: Found GPO(s): <[LDAP://cn={D110C8FA-777B-4F95-BB65-A333A8B0091D},cn=policies,cn=system,DC=contoso,DC=local;0]...>
GPSVC(2dc.22b0) 17:16:01:922 ProcessGPO: ==============================
 
Il existe trois valeurs numériques à la fin de la requête LDAP pour chaque lien :
  • 0 : Paramètre par défaut
  • 1 : Le lien est désactivé
  • 2 : Le lien est appliqué (enforced)
 Une fois que toutes les GPO sont lues, celles-ci sont traitées.

Traitement des stratégies :

GPSVC(2dc.22b0) 17:16:02:109 ProcessGPO: Searching <cn={EC37F666-21C0-459E-88DF-3AD63AE600A1},cn=policies,cn=system,DC=contoso,DC=local>
GPSVC(2dc.22b0) 17:16:02:109 ProcessGPO: User has access to this GPO.
GPSVC(2dc.22b0) 17:16:02:109 FilterCheck: Found WMI Filter id of: <[contoso.local;{118D5E2E-9A8A-41C8-AB0C-D87AAE094BF1};0]>
GPSVC(2dc.22b0) 17:16:02:171 ProcessGPO: GPO passes the filter check.
GPSVC(2dc.22b0) 17:16:02:171 ProcessGPO: Found functionality version of: 2
GPSVC(2dc.22b0) 17:16:02:171 ProcessGPO: Found file system path of: <\\contoso.local\sysvol\gds.local\Policies\{EC37F666-21C0-459E-88DF-3AD63AE600A1}>
GPSVC(2dc.22b0) 17:16:02:203 ProcessGPO: Found common name of: <{EC37F666-21C0-459E-88DF-3AD63AE600A1}>
GPSVC(2dc.22b0) 17:16:02:203 ProcessGPO: Found display name of: <CONTOSO-COMPUTER_WSUS>
GPSVC(2dc.22b0) 17:16:02:203 ProcessGPO: Found user version of: GPC is 1, GPT is 1
GPSVC(2dc.22b0) 17:16:02:203 ProcessGPO: Found flags of: 1
GPSVC(2dc.22b0) 17:16:02:203 ProcessGPO: No client-side extensions for this object.
GPSVC(2dc.22b0) 17:16:02:203 ProcessGPO: GPO CONTOSO-COMPUTER_WSUS is disabled. It will be skipped.
 
Plusieurs remarques peuvent être faites :
  • La présence d'un filtre WMI est détecté en 1er et s'il est présent, il est évalué.
  • Le GUID de la GPO renvoie à son chemin physique dans le dossier SYSVOL.
  • La présence de paramètres CSE est évaluée
  • L'état de la GPO (désactivée ou non) est évaluée afin de décider de son traitement
  • La présence de paramètres CSE est évaluée
Une fois ces GPO traitées, une passe particulière est réalisée pour les paramètres CSE (Client Side Extentions).
Ce sera l'objet de notre prochain billet.
 

Azure AD Connect – Relancer les synchronisations après la suppression d’un domaine Active Directory enfant

Contexte

La synchronisation entre l’Active Directory et Office 365 est un sujet extrêmement sensible dans un environnement de production. Une mauvaise configuration peut entrainer la suppression de nombreux objets dans le cloud (comptes, groupes…).

Le domaine enfant de mon domaine Active Directory a été décoché dans la configuration de mon connecteur dans la console Synchronization Service Manager.

2018-01-10_1613512

Figure 1 – Propriétés du connecteur

Lorsque l’on coche à nouveau le domaine enfant et que l’on relance une synchronisation, le domaine enfant n’est pas resynchronisé.

Solution

Lors de la suppression du domaine enfant, les étapes de synchronisation associées sont supprimées.

On remarque en allant dans Configure Run Profiles… sur le connecteur qu’il n’y a qu’une seule étape qui correspond au domaine parent.

2018-01-12_1111362

Figure 2 – Profil du connecteur pour le Full Import avec une seule étape (domaine parent)

Il est donc nécessaire de recréer les étapes pour le domaine enfant. Pour cela il est recommandé de lancer l’outil de configuration d’Azure AD Connect.

Une fois l’outil de configuration terminée, les étapes pour le domaine enfant sont de nouveaux en place.

2018-01-12_1142582

Figure 3 – Profil du connecteur pour le Full Import avec deux étapes (domaine parent et domaine enfant)

Il est ensuite nécessaire de relancer dans l’ordre :

  • Full Import – Connecteur Active Directory
  • Full Synchronisation – Connecteur Active Directory
  • Export – Connecteur Active Directory
  • Delta Import – Connecteur Office 365 (domaine.onmicrosoft.com)
  • Delta Synchronisation – Connecteur Office 365 (domaine.onmicrosoft.com)
  • Export – Connecteur Office 365 (domaine.onmicrosoft.com)

SCOM – Créer un moniteur d’échantillons consécutifs de performance à 3 états – 2/2

Au cours de l’un ou l’autre des développements de Management Pack que j’ai été amené à réaliser, il est arrivé à plusieurs reprises que l’on me demande de mettre en place un moniteur de performances fonctionnant sur plusieurs mesures consécutives et ayant trois états (healthy/warning/critical), ou autrement dit deux seuils de déclenchement distincts.

Prises séparément, ces deux contraintes ne posent aucune difficulté particulière puisqu’il est possible de créer nativement via la console SCOM des moniteurs de performance de type « consecutive samples » (mesure d’échantillons consécutifs à deux états/un seul seuil) et « double thresholds » (trois états/deux seuils mais déclenchement sur une seule mesure).

Réunir ces deux besoins nécessite par contre d’en passer par un peu d’authoring, ce dont je profiterai pour présenter deux façons de procéder :

- Fusionner deux types de moniteurs natifs

- Utiliser la Suppression, une propriété méconnue de l’expression filter natif (cet article)

Nous avons vu dans la première partie de cet article que nous pouvions utiliser la fusion de deux types de moniteurs natifs pour arriver à nos fins. Cette solution est tout à fait adaptée et peut en plus être réutilisée très largement et s’appliquer à bien d’autres problématiques, mais il existe une autre solution, peut être encore plus élégante à notre problème : le paramètre « Suppression » de l’ExpressionFilter de SCOM.

Dans l’article précédent, j’avais présenté le fonctionnement du type de moniteur Double Threshold et notamment son utilisation de trois Expression Filter successifs.

clip_image002

En allant voir la définition de ce filtre, on constate qu’en plus de travailler sur une Expression, il est capable de travailler sur une Suppression, bien que ce second élément ne soit pas exploité dans la configuration native du type de moniteur Double Threshold :

clip_image004

Ce paramètre de Suppression fonctionne à l’aide de trois paramètres :

- MatchCount : le nombre de fois que l’élément Expression doit matcher avant que le property bag de sortie ne soit effectivement généré

- Sample Count : le nombre de fois que l’Expression Filter doit être évalué avant qu’il soit possible de générer le property bag de sortie.

- Within Seconds : la plage de temps au cours de laquelle l’élément Expression doit matcher avant qu’il soit possible de générer le property bag de sortie.

Il est donc possible d’utiliser Match Count seul ou en combinaison soit avec Sample Count, soit Within Seconds (mais pas les deux) afin d’obtenir une condition de type « l’expression matche 5 fois sur les 10 dernières occurrences » ou « l’expression matche 5 fois sur les 10 dernières minutes ».

Et il est extrêmement simple à utiliser !

Reprenons une fois de plus l’exemple du type de moniteur Double Threshold, et ajoutons une Suppression à la suite de son Expression dans sa condition CDUnderThresold1 :

clip_image005

Voilà, le tour est joué, il ne reste plus qu’à ajouter NumSamples à la configuration de notre type de moniteur personnalisé.

Et comme ici aussi un bon exemple vaut tous les longs discours, voici un fragment complet :

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <TypeDefinitions>
    <MonitorTypes>
      <UnitMonitorType ID="Test.ThreeStateConsecutiveThreshold.Suppression.MonitorType" Accessibility="Public">
        <MonitorTypeStates>
          <MonitorTypeState ID="UnderThreshold1"/>
          <MonitorTypeState ID="OverThreshold1UnderThreshold2"/>
          <MonitorTypeState ID="OverThreshold2"/>
        </MonitorTypeStates>
        <Configuration>
          <xsd:element name="ComputerName" type="xsd:string" minOccurs="0" maxOccurs="1"/>
          <xsd:element name="CounterName" type="xsd:string"/>
          <xsd:element name="ObjectName" type="xsd:string"/>
          <xsd:element name="InstanceName" type="xsd:string" minOccurs="0" maxOccurs="1"/>
          <xsd:element name="AllInstances" type="xsd:boolean" minOccurs="0" maxOccurs="1"/>
          <xsd:element name="Frequency" type="xsd:unsignedInt"/>
          <xsd:element name="ScaleBy" type="xsd:double" minOccurs="0" maxOccurs="1"/>
          <xsd:element name="Threshold1" type="xsd:double"/>
          <xsd:element name="Threshold2" type="xsd:double"/>
          <xsd:element name="NumSamples" type="xsd:int"/>
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="Frequency" ParameterType="int" Selector="$Config/Frequency$"/>
          <OverrideableParameter ID="Threshold1" ParameterType="double" Selector="$Config/Threshold1$"/>
          <OverrideableParameter ID="Threshold2" ParameterType="double" Selector="$Config/Threshold2$"/>
          <OverrideableParameter ID="NumSamples" ParameterType="double" Selector="$Config/NumSamples$"/>
        </OverrideableParameters>
        <MonitorImplementation>
          <MemberModules>
            <DataSource TypeID="Perf!System.Performance.DataProvider" ID="DS1">
              <ComputerName>$Config/ComputerName$</ComputerName>
              <CounterName>$Config/CounterName$</CounterName>
              <ObjectName>$Config/ObjectName$</ObjectName>
              <InstanceName>$Config/InstanceName$</InstanceName>
              <AllInstances>$Config/AllInstances$</AllInstances>
              <Frequency>$Config/Frequency$</Frequency>
              <ScaleBy>$Config/ScaleBy$</ScaleBy>
            </DataSource>
            <ConditionDetection TypeID="System!System.ExpressionFilter" ID="CDUnderThreshold1">
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">Value</XPathQuery>
                  </ValueExpression>
                  <Operator>Less</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/Threshold1$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <SuppressionSettings>
                <MatchCount>$Config/NumSamples$</MatchCount>
              </SuppressionSettings>
            </ConditionDetection>
            <ConditionDetection TypeID="System!System.ExpressionFilter" ID="CDOverThreshold1UnderThreshold2">
              <Expression>
                <And>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="Double">Value</XPathQuery>
                      </ValueExpression>
                      <Operator>GreaterEqual</Operator>
                      <ValueExpression>
                        <Value Type="Double">$Config/Threshold1$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="Double">Value</XPathQuery>
                      </ValueExpression>
                      <Operator>LessEqual</Operator>
                      <ValueExpression>
                        <Value Type="Double">$Config/Threshold2$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                </And>
              </Expression>
              <SuppressionSettings>
                <MatchCount>$Config/NumSamples$</MatchCount>
              </SuppressionSettings>
            </ConditionDetection>
            <ConditionDetection TypeID="System!System.ExpressionFilter" ID="CDOverThreshold2">
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">Value</XPathQuery>
                  </ValueExpression>
                  <Operator>Greater</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/Threshold2$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <SuppressionSettings>
                <MatchCount>$Config/NumSamples$</MatchCount>
              </SuppressionSettings>              
            </ConditionDetection>
          </MemberModules>
          <RegularDetections>
            <RegularDetection MonitorTypeStateID="UnderThreshold1">
              <Node ID="CDUnderThreshold1">
                <Node ID="DS1"/>
              </Node>
            </RegularDetection>
            <RegularDetection MonitorTypeStateID="OverThreshold1UnderThreshold2">
              <Node ID="CDOverThreshold1UnderThreshold2">
                <Node ID="DS1"/>
              </Node>
            </RegularDetection>
            <RegularDetection MonitorTypeStateID="OverThreshold2">
              <Node ID="CDOverThreshold2">
                <Node ID="DS1"/>
              </Node>
            </RegularDetection>
          </RegularDetections>
        </MonitorImplementation>
      </UnitMonitorType>
    </MonitorTypes>
  </TypeDefinitions>
  
  
  <Monitoring>
    <Monitors>
      <UnitMonitor ID="Test.ThreeStateConsecutiveThreshold.Suppression.Perf.Monitor" Accessibility="Public" Enabled="true" Target="MWSL!Microsoft.Windows.Server.6.2.LogicalDisk" ParentMonitorID="Health!System.Health.PerformanceState" Remotable="true" Priority="Normal" TypeID="Test.ThreeStateConsecutiveThreshold.Suppression.MonitorType" ConfirmDelivery="false">
        <Category>PerformanceHealth</Category>
        <AlertSettings AlertMessage="Test.ThreeStateConsecutiveThreshold.Suppression.Perf.Monitor.Alert.Message">
          <AlertOnState>Warning</AlertOnState> 
          <AutoResolve>true</AutoResolve>
          <AlertPriority>Normal</AlertPriority>
          <AlertSeverity>MatchMonitorHealth</AlertSeverity>  <!-- Common options for AlertSeverity are MatchMonitorHealth, Information, Warning, Error -->
          <AlertParameters>
            <AlertParameter1>$Data/Context/ObjectName$</AlertParameter1>
            <AlertParameter2>$Data/Context/CounterName$</AlertParameter2>
            <AlertParameter3>$Data/Context/InstanceName$</AlertParameter3>
            <AlertParameter4>$Data/Context/Value$</AlertParameter4>
            <AlertParameter5>$Data/Context/TimeSampled$</AlertParameter5>
          </AlertParameters>
        </AlertSettings>
        <OperationalStates>
          <OperationalState ID="Healthy" MonitorTypeStateID="OverThreshold2" HealthState="Success" />
          <OperationalState ID="Warning" MonitorTypeStateID="OverThreshold1UnderThreshold2" HealthState="Warning" />
          <OperationalState ID="Critical" MonitorTypeStateID="UnderThreshold1" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName>
          <CounterName>% Free Space</CounterName>
          <ObjectName>LogicalDisk</ObjectName>
          <InstanceName>$Target/Property[Type="Windows!Microsoft.Windows.LogicalDevice"]/DeviceID$</InstanceName>
          <AllInstances>false</AllInstances>
          <Frequency>60</Frequency>  <!-- 60 seconds is a good recommended interval for a native module perfmon monitor -->
          <Threshold1>65</Threshold1>
          <Threshold2>80</Threshold2>
          <NumSamples>3</NumSamples>

    
      </Configuration>
      </UnitMonitor>
      
    </Monitors>
  </Monitoring>
  <Presentation>
    <StringResources>
      <StringResource ID="Test.ThreeStateConsecutiveThreshold.Suppression.Perf.Monitor.Alert.Message" />
    </StringResources>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.Suppression.Perf.Monitor">
          <Name>Test 3State Consecutive Free Disk Space Perf Monitor (Using Suppression)</Name>
          <Description />
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.Suppression.Perf.Monitor" SubElementID="Healthy">
          <Name>Healthy</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.Suppression.Perf.Monitor" SubElementID="Warning">
          <Name>Warning</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.Suppression.Perf.Monitor" SubElementID="Critical">
          <Name>Critical</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.Suppression.Perf.Monitor.Alert.Message">
          <Name>Test 3 state consecutive counter has breached a threshold</Name>
          <Description>The monitor breached a threshold

Object: {0}
Counter {1}
Instance {2}
Has a value {3} 
At time {4}
          </Description>
        </DisplayString>
 
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPackFragment>

 

SCOM – Créer un moniteur d’échantillons consécutifs de performance à 3 états – 1/2

Au cours de l’un ou l’autre des développements de Management Pack que j’ai été amené à réaliser, il est arrivé à plusieurs reprises que l’on me demande de mettre en place un moniteur de performances fonctionnant sur plusieurs mesures consécutives et ayant trois états (healthy/warning/critical), ou autrement dit deux seuils de déclenchement distincts.

Prises séparément, ces deux contraintes ne posent aucune difficulté particulière puisqu’il est possible de créer nativement via la console SCOM des moniteurs de performance de type « consecutive samples » (mesure d’échantillons consécutifs à deux états/un seul seuil) et « double thresholds » (trois états/deux seuils mais déclenchement sur une seule mesure).

Réunir ces deux besoins nécessite par contre d’en passer par un peu d’authoring, ce dont je profiterai pour présenter deux façons de procéder :

- Fusionner deux types de moniteurs natifs (cet article)

- Utiliser la Suppression, une propriété méconnue de l’expression filter natif

Comme vu dans l’introduction, il existe nativement dans SCOM deux types de moniteurs qui, s’ils pouvaient être assemblés, formeraient une solution évidente à notre problème.

Et il se trouve que SCOM permet ce genre de fantaisie assez facilement, bien que cela nécessite de mettre les mains dans le code…

Commençons par aller regarder la « définition » de ces deux types de moniteurs, à l’aide de l’indispensable systemcenter.wiki : ConsecutiveSamplesThreshold et DoubleThreshold

On remarque immédiatement qu’ils sont basés sur une construction très similaire : ils comportent tous les deux en point d’entrée une source de données (Data Source) qui leur permet de récupérer la valeur du compteur de performance qui nous intéressent :
clip_image001

Cette Data Source est suivie par un ensemble de conditions de détection (Condition Detection) qui leur permettent de déterminer quand l’un ou l’autre état du moniteur est atteint.

Pour comprendre leur fonctionnement, il faut imaginer que la valeur relevée par la DataSource passe successivement par chaque Condition Detection, qui, si les conditions qui les définissent sont réunies, vont renvoyer un property bag.

Dans le cas du Consecutive Sample, on trouve trois Condition Detections :

- La première, de type System.Performance.ConsecutiveSamplesCondition, permet de compter le nombre de fois où la valeur du compteur est passée au delà du seuil configuré. Elle n’agit pas directement sur l’état du moniteur.
clip_image002

- La seconde et la troisième, de type ExpressionFilter permettent quant à elles de déterminer deux états pour le moniteur, en fonction de la valeur renvoyée par la première (nombre d’échantillons au-delà du seuil suffisant ou non pour changer l’état).
clip_image004

Dans le cas du Double Threshold, on retrouve également trois Condition Detection, mais ici chacune des trois servent à déterminer l’état du moniteur directement en fonction de la valeur renvoyée par la Data Source (sous le premier seuil, entre les deux seuils ou au-dessus du second):

clip_image006

En se basant sur ces constations, on réalise que rien n’empêche d’écrire nous-même un Monitor Type qui contiendrait à la fois une Condition Detection de type ConsecutiveSamplesCondition pour compter le nombre d’échantillons au-dessus du seuil de détection, suivie de trois ExpressionFilter pour déterminer 3 états différents qui vérifieraient à la fois la valeur du compteur et le nombre de fois qu’il est passé au  delà du seuil!
Le filtre pour l’état « entre deux seuils » ressemblerait donc à cela :

clip_image007

On voit bien que pour que le moniteur prenne l’état « Warning », j’ai simplement créé une expression qui nécessite la réunion de 3 conditions : un nombre de mesures (NumSamples) au-delà du seuil défini et une valeur de ces mesures inférieure à un premier seuil et supérieure à un second.

Et comme un bon exemple complet vaut mieux que tous les longs discours, voici ici le fragment intégral, implémenté pour le compteur « Logical Disk / Free Space % :

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <TypeDefinitions>
    <MonitorTypes>
  <UnitMonitorType ID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.MonitorType" Accessibility="Internal">
    <MonitorTypeStates>
      <MonitorTypeState ID="Healthy" NoDetection="false" />
      <MonitorTypeState ID="Warning" NoDetection="false" />
      <MonitorTypeState ID="Critical" NoDetection="false" />
    </MonitorTypeStates>
    <Configuration>
      <xsd:element name="Frequency" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="WarningThreshold" type="xsd:double" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="CriticalThreshold" type="xsd:double" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="NumSamples" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="Direction" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="ComputerName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="CounterName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="ObjectName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="InstanceName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="AllInstances" type="xsd:boolean" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
    </Configuration>
    <OverrideableParameters>
      <OverrideableParameter ID="Frequency" Selector="$Config/Frequency$" ParameterType="int" />
      <OverrideableParameter ID="WarningThreshold" Selector="$Config/WarningThreshold$" ParameterType="double" />
      <OverrideableParameter ID="CriticalThreshold" Selector="$Config/CriticalThreshold$" ParameterType="double" />
      <OverrideableParameter ID="NumSamples" Selector="$Config/NumSamples$" ParameterType="int" />

    </OverrideableParameters>
    <MonitorImplementation>
      <MemberModules>
        <DataSource ID="DS" TypeID="Perf!System.Performance.DataProvider">
          <ComputerName>$Config/ComputerName$</ComputerName>
          <CounterName>$Config/CounterName$</CounterName>
          <ObjectName>$Config/ObjectName$</ObjectName>
          <InstanceName>$Config/InstanceName$</InstanceName>
          <AllInstances>$Config/AllInstances$</AllInstances>
          <Frequency>$Config/Frequency$</Frequency>
        </DataSource>
        <ConditionDetection ID="ConsecutiveSamples" TypeID="Perf!System.Performance.ConsecutiveSamplesCondition">
          <Threshold>$Config/WarningThreshold$</Threshold>
          <Direction>$Config/Direction$</Direction>
        </ConditionDetection>
        <ConditionDetection ID="HealthyCondition" TypeID="System!System.ExpressionFilter">
          <Expression>
            <And>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>GreaterEqual</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/WarningThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>GreaterEqual</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/CriticalThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </And>
          </Expression>
        </ConditionDetection>
        <ConditionDetection ID="WarningCondition" TypeID="System!System.ExpressionFilter">
          <Expression>
            <And>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Integer">Value</XPathQuery>
                  </ValueExpression>
                  <Operator>GreaterEqual</Operator>
                  <ValueExpression>
                    <Value Type="Integer">$Config/NumSamples$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>LessEqual</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/WarningThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>Greater</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/CriticalThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </And>
          </Expression>
        </ConditionDetection>
        <ConditionDetection ID="CriticalCondition" TypeID="System!System.ExpressionFilter">
          <Expression>
            <And>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Integer">Value</XPathQuery>
                  </ValueExpression>
                  <Operator>GreaterEqual</Operator>
                  <ValueExpression>
                    <Value Type="Integer">$Config/NumSamples$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>LessEqual</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/CriticalThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </And>
          </Expression>
        </ConditionDetection>
      </MemberModules>
      <RegularDetections>
        <RegularDetection MonitorTypeStateID="Healthy">
          <Node ID="HealthyCondition">
            <Node ID="ConsecutiveSamples">
              <Node ID="DS" />
            </Node>
          </Node>
        </RegularDetection>
        <RegularDetection MonitorTypeStateID="Warning">
          <Node ID="WarningCondition">
            <Node ID="ConsecutiveSamples">
              <Node ID="DS" />
            </Node>
          </Node>
        </RegularDetection>
        <RegularDetection MonitorTypeStateID="Critical">
          <Node ID="CriticalCondition">
            <Node ID="ConsecutiveSamples">
              <Node ID="DS" />
            </Node>
          </Node>
        </RegularDetection>
      </RegularDetections>
    </MonitorImplementation>
  </UnitMonitorType>
  </MonitorTypes>
  </TypeDefinitions>
  <Monitoring>
    <Monitors>
      <UnitMonitor ID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor" Accessibility="Public" Enabled="true" Target="MWSL!Microsoft.Windows.Server.6.2.LogicalDisk" ParentMonitorID="Health!System.Health.PerformanceState" Remotable="true" Priority="Normal" TypeID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.MonitorType" ConfirmDelivery="false">
        <Category>PerformanceHealth</Category>
        <AlertSettings AlertMessage="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor.Alert.Message">
          <AlertOnState>Warning</AlertOnState>
          <AutoResolve>true</AutoResolve>
          <AlertPriority>Normal</AlertPriority>
          <AlertSeverity>MatchMonitorHealth</AlertSeverity>
          <AlertParameters>
            <AlertParameter1>$Data/Context/ObjectName$</AlertParameter1>
            <AlertParameter2>$Data/Context/CounterName$</AlertParameter2>
            <AlertParameter3>$Data/Context/InstanceName$</AlertParameter3>
            <AlertParameter4>$Data/Context/SampleValue$</AlertParameter4>
            <AlertParameter5>$Data/Context/TimeSampled$</AlertParameter5>
          </AlertParameters>
        </AlertSettings>
        <OperationalStates>
          <OperationalState ID="Healthy" MonitorTypeStateID="Healthy" HealthState="Success" />
          <OperationalState ID="Warning" MonitorTypeStateID="Warning" HealthState="Warning" />
          <OperationalState ID="Critical" MonitorTypeStateID="Critical" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <Frequency>60</Frequency>
          <WarningThreshold>80</WarningThreshold>
          <CriticalThreshold>65</CriticalThreshold>
          <NumSamples>3</NumSamples>
          <Direction>Less</Direction>
          <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName>
          <CounterName>% Free Space</CounterName>
          <ObjectName>LogicalDisk</ObjectName>
          <InstanceName>$Target/Property[Type="Windows!Microsoft.Windows.LogicalDevice"]/DeviceID$</InstanceName>
          <AllInstances>false</AllInstances>
        </Configuration>
      </UnitMonitor>
    </Monitors>
  </Monitoring>
  <Presentation>
    <StringResources>
      <StringResource ID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor.Alert.Message" />
    </StringResources>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor">
          <Name>Test 3State Consecutive Free Disk Space Perf Monitor (Condition Detection)</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor" SubElementID="Healthy">
          <Name>Healthy</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor" SubElementID="Warning">
          <Name>Warning</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor" SubElementID="Critical">
          <Name>Critical</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor.Alert.Message">
          <Name>Test 3 state consecutive counter has breached a threshold</Name>
          <Description>
            The monitor breached a threshold

            Object: {0}
            Counter {1}
            Instance {2}
            Has a value {3}
            At time {4}
          </Description>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPackFragment>

 

Direct Access : Mode single-NIC avec deux cartes réseau

Bien qu’il ne s’agisse pas forcément de la configuration la plus fréquente (ni la plus recommandée) dans un environnement de production, il peut arriver qu’il soit nécessaire de réaliser un déploiement de serveurs DirectAccess en mode « single network adapter behind an edge device », autrement dit avec une seule carte réseau connectée dans une DMZ au lieu du fonctionnement plus classique avec une carte réseau sur le LAN et une autre sur Internet :

clip_image002

(image provenant du whitepaper F5 : https://f5.com/resources/white-papers/f5-and-windows-server-2012-directaccessremote-access-services)

Et il peut également arriver que même dans cette configuration, une seconde carte réseau soit présente sur les serveurs DirectAccess, connectée à un réseau totalement différent (par exemple un réseau d’administration isolé, permettant la prise en main à distance des machines de la DMZ).

Dans ce dernier cas, bien que la configuration soit parfaitement correcte (ce qui n’est déjà pas toujours une mince affaire avec DirectAccess…), les clients ne peuvent pas se connecter et on constate des événements IPSec Main Mode « No Policy Configured ».
Par contre, en désactivant la seconde carte réseau puis en redémarrant, le fonctionnement est rétabli ; et a contrario en réactivant la seconde carte le fonctionnement est maintenu tant qu’aucun redémarrage n’a eu lieu.

Ce phénomène se produit lorsqu’au niveau du firewall Windows, la seconde carte réseau est détectée comme ayant un profil « public » et la raison est la suivante : lors du paramétrage de DirectAccess, les règles du firewall permettant de créer le tunnel IPhttps sont créées uniquement pour le profil de firewall « domain », ce qui est souhaité puisque c’est normalement bien le cas de la carte permettant l’accès aux ressources du LAN.

Or l’interface réseau virtuelle IPhttps s’attache de préférence aux cartes réseau dont le profil est « private » ou « public » lorsqu’elles sont présentes : dans ce cas les règles de firewall deviennent donc inopérantes.

Il y a donc deux solutions possibles : faire en sorte que la seconde carte réseau soit également détectée avec un profil « domain » (ce qui n’est pas toujours réalisable), ou modifier la GPO Direct Access afin qu’elle s’applique à tous les profils :

$gposession = Open-NetGPO –PolicyStore <Name of the server GPO>

Set-NetIPsecRule –DisplayName <Name of the IPsec policy> –GPOSession $gposession –Profile Any

Save-NetGPO –GPOSession $gposession

On notera que pour une fois, ce contournement est bien détaillé sur Technet (https://technet.microsoft.com/en-us/library/jj134204.aspx )… mais sur une page où il a bien peu de chances d’être trouvé, puisqu’elle concerne un stade de la configuration de Direct Access ou la GPO n’existe pas et où il n’y a donc aucune raison d’envisager d’y apporter des modifications !

Enfin, attention : il est fort probable qu’il faille réappliquer le contournement à chaque fois que la configuration DirectAccess est modifiée en utilisant l’assistant, puisque ce dernier met à jour la GPO.