Le blog technique

Toutes les astuces #tech des collaborateurs de PI Services.

#openblogPI

Retrouvez les articles à la une

PowerShell – Récupérer la fréquence d’utilisation des suffixes des userPrincipalName (UPN) dans une forêt Active Directory

<pre class="wp-block-syntaxhighlighter-code">#Informations récupérées : suffixe des userPrincipalName (UPN) et fréquence d'utilisations dans les domaines choisis

#Prérequis : l'utilisateur qui lance le script doit pouvoir lire l'Active Directory en PowerShell

#List de paramètres qui permettent de récupérer soit la fréquence des UPN de l'ensemble des domaines Active Directory (AD) de la forêt ou de spécifier les domaines dans lesquels chercher
#Exemple 1 d'utilisation du script : .\Get-UPNSuffixFrequency.ps1 -SearchInAllDomainsOfTheForest
#Exemple 2 d'utilisation du script : .\Get-UPNSuffixFrequency.ps1 -SpecifyDomains customer.intern, technical.intern
Param
( 	
	#Paramètre de type switch qui s'il est utilisé va récupérer la fréquence des suffixes UPN de l'ensemble des domaines AD de la forêt
	[Parameter(Mandatory=$false)]
    [switch]$SearchInAllDomainsOfTheForest,

	#Paramètre de type tableau qui s'il est utilisé va réucupérer la fréquence des suffixes UPN dans les domaines AD mentionnés
    [Parameter(Mandatory=$false)]
    [array]$SpecifyDomains
)

#Importe le module Active Directory qui contient des commandes utilisées dans le script
Import-Module ActiveDirectory

#Si le paramètre de type switch $SearchInAllDomainsOfTheForest est utilisé, récupère les noms de tous les domaines dans la forêt AD
if ($SearchInAllDomainsOfTheForest)
{
	$Domains = Get-ADForest | Select-Object Domains
	$Domains = $Domains.Domains
}

#Si le paramètre de type tableau $SpecifyDomains est utilisé, ajoute les noms des domaines spécifiés comme base de recherche pour la fréquence des suffixes UPN
if ($SpecifyDomains)
{
	$Domains = $SpecifyDomains
}

#Variable globale qui va contenir l'ensemble des UPN des utilisateurs des domaines requêtés
$AllUsersObjects = @()

#Parcours chaque domaine requêté et récupère l'ensemble des UPN des utilisateurs
foreach ($Domain in $Domains)
{
	#Récupére l'ensemble des utilisateurs du domaine actuellement requêté
    $UsersObjectsFromDomain = Get-ADUser -Filter * -Server $Domain -Properties userPrincipalName | Select-Object userPrincipalName

	#Ajoute les utilisateurs du domaine actuellement requêté a la variable globale qui va contenir l'ensemble des UPN des utilisateurs des domaines requêtés
    $AllUsersObjects += $UsersObjectsFromDomain
}

#Commande qui va récupérer l'ensemble des suffixes UPN utilisables dans l'AD
$ADForestObject = Get-ADForest | Select-Object UPNSuffixes

#Créer un tableau qui contiendra l'ensemble des suffixes UPN et leur fréquence
$Array = @()

#Parcours l'ensemble des suffixes UPN dans l'AD et les compare à la liste de l'ensemble des utilisateurs des domaines requêtés
foreach ($UPNSuffixe in $ADForestObject.UPNSuffixes)
{
	#Initialise la fréquence du suffixe UPN actuellement requêté à 0
	$UPNSuffixeOccurence = 0

	#Créer un objet PowerShell qui contiendra le suffixe UPN actuellement requêté et sa fréquence d'utilisation dans les domaines requêtés
    $Line = New-Object PSObject

	#Ajoute à l'object PowerShell précédemment crée, le suffixe UPN actuellement requêté
	$Line | Add-Member -MemberType NoteProperty -Name "UPNSuffixe" -Value $UPNSuffixe

	#Boucle qui va comparer le suffixe UPN actuellement requêté avec chaque utilisateur des domaines requêtés et comptabilise la fréquence d'utilisation
	foreach ($UserObject in $AllUsersObjects)
	{
		#Vérifie que l'UPN de l'utilisateur actuellement requêté n'est pas vide
		if ($UserObject.userPrincipalName)
		{
			#Sépare le préfixe du suffixe UPN de l'utilisateur actuellement requêté
			$UserUPNSuffixe = (($UserObject.userPrincipalName).Split('@'))[1]

			#Compare la valeur du suffixe UPN de l'utilisateur actuellement requêté avec le suffixe UPN actuellement requêté
			if ($UserUPNSuffixe -eq $UPNSuffixe)
			{
				#Si la valeur du suffixe UPN de l'utilisateur actuellement requêté et le suffixe UPN actuellement requêté sont égaux, incrémente de 1 le nombre d'utilisation du suffixe UPN
				$UPNSuffixeOccurence += 1
			}
		}
	}

	#Une fois que l'ensemble des suffixes UPN des utilisateurs des domaines requêtés ont été comparés au suffixe UPN actuellement requêté, ajoute la fréquence du suffixe UPN à l'objet PowerShell précédemment crée
	$Line | Add-Member -MemberType NoteProperty -Name "UPNSuffixeOccurence" -Value $UPNSuffixeOccurence

	#Ajoute à la variable globale qui contient l'ensemble des suffixes UPN et leur fréquence, l'objet PowerShell précédemment crée lors de l'itération courante
    $Array += $Line

	#Supprime les valeurs des variables propres au suffixe UPN actuellement requêté
    Clear-Variable UPNSuffixe, Line
}

#Affiche sous forme de liste tableau l'ensemble des suffixes UPN et leurs fréquences d'utilisation
$Array

<# Exemple d'affichage
UPNSuffixe             UPNSuffixeOccurence
----------             -------------------
customer.intern                         47
technical.intern                        42
#></pre>

 

PowerShell – Vérifier si une mise à jour Windows (KB) est installée sur les contrôleurs de domaine d’une forêt Active Directory

<pre class="wp-block-syntaxhighlighter-code">#Informations récupérées : Nom du contrôleur de domaine (DC), domaine Active Directory (AD) d'appartenance, OS, présence ou non des KB recherchées, date d'installation des KB

#Prérequis : l'utilisateur qui lance le script doit pouvoir requêter en remote PowerShell Administrator l'ensemble des DC de la forêt

#Paramètre obligatoire qui doit contenir la liste des KB à récupérer
#Par exemple pour appeler le script avec une liste de KB : .\Get-DomainControllerKB.ps1 -DCHotFixIDs KB5022511, KB4589208
Param
( 	
	[Parameter(Mandatory=$true)]
    [array]$DCHotFixIDs
)

#Importe le module Active Directory qui contient des commandes utilisées dans le script
Import-Module ActiveDirectory

#Permet de récupérer les noms de tous les domaines dans la forêt AD
$Domains = Get-ADForest | Select-Object Domains
$Domains = $Domains.Domains

#Créer un tableau qui contiendra l'ensemble des statuts des KB des DC de chaque domaine de la forêt
$Array = @()

#Parcours chaque domaine AD de la forêt et récupére la liste des DC
foreach ($Domain in $Domains)
{
	#Récupére l'ensemble des DC du domaine AD actuellement requêté
	$DCs = Get-ADDomainController -Server $Domain -Filter * | Select-Object Name, HostName, OperatingSystem

	#Parcours chaque DC du domaine AD actuellement requêté
    foreach ($DC in $DCs)
    {
		#Vérifie pour chaque KB si elle est présente sur le DC actuellement requêté
		foreach ($DCHotFixID in $DCHotFixIDs)
		{
			#Créer un objet PowerShell qui contiendra les informations sur la KB actuellement requêtée du DC actuellement requêté
			$Line = New-Object PSObject

			#Ajoute à l'objet PowerShell précédemment crée, le nom du DC actuellement requêté
			$Line | Add-Member -MemberType NoteProperty -Name "DomainController" -Value $DC.HostName

			#Ajoute à l'objet PowerShell précédemment crée, le domaine AD d'appartenence du DC actuellement requêté
			$Line | Add-Member -MemberType NoteProperty -Name "Domain" -Value $Domain

			#Ajoute à l'objet PowerShell précédemment crée, le système d'exploitation du DC actuellement requêté
			$Line | Add-Member -MemberType NoteProperty -Name "OperatingSystem" -Value $DC.OperatingSystem

			#Ajoute à l'objet PowerShell précédemment crée, le numéro de la KB actuellement requêté du DC actuellement requêté
			$Line | Add-Member -MemberType NoteProperty -Name "HotFixIDSearched" -Value $DCHotFixID

			#Commande qui va vérifier si la KB actuellement requêtée est présente sur le DC actuellement requêté
			$HotFixObject = Get-HotFix -ComputerName $DC.HostName -ID $DCHotFixID -ErrorAction SilentlyContinue | Select-Object Description, HotFixID, InstalledBy, InstalledOn

			#Si la KB actuellement requêtée est PRESENTE sur le DC actuellement requêté, ajoute les informations relatives à son installation dans l'objet PowerShell précédemment créé
			if ($HotFixObject)
			{
				#Ajoute à l'objet PowerShell précédemment crée, le statut présent ou absent de la KB actuellement requêtée du DC actuellement requêté
				$Line | Add-Member -MemberType NoteProperty -Name "KBIsInstalled" -Value "Success"

				#Ajoute à l'objet PowerShell précédemment crée, le nom de l'utilisateur qui a réalisé l'installation de la KB actuellement requêtée du DC actuellement requêté
				$Line | Add-Member -MemberType NoteProperty -Name "HotFixInstalledBy" -Value $HotFixObject.InstalledBy

				#Ajoute à l'objet PowerShell précédemment crée, la date d'installation, arrondi au jour prêt, de la KB actuellement requêtée du DC actuellement requêté
				$Line | Add-Member -MemberType NoteProperty -Name "HotFixInstalledOn" -Value $HotFixObject.InstalledOn

				#Ajoute à l'objet PowerShell précédemment crée, le type de KB actuellement requêté du DC actuellement requêté
				$Line | Add-Member -MemberType NoteProperty -Name "HotFixDescription" -Value $HotFixObject.Description

				#Supprime les valeurs des variables propres à la KB actuellement requêté du DC actuellement requêté
				Clear-Variable HotFixObject
			}

			#Si la KB actuellement requêtée est ABSENTE sur le DC actuellement requêté, ajoute des valeurs Fail ou NULL pour ses informations dans l'objet PowerShell précédemment créé
			else
			{
				$Line | Add-Member -MemberType NoteProperty -Name "KBIsInstalled" -Value "Fail"
				$Line | Add-Member -MemberType NoteProperty -Name "HotFixInstalledBy" -Value "NULL"
				$Line | Add-Member -MemberType NoteProperty -Name "HotFixInstalledOn" -Value "NULL"
				$Line | Add-Member -MemberType NoteProperty -Name "HotFixDescription" -Value "NULL"
			}

			#Ajoute à la variable globale qui contient l'ensemble des statuts des KB des DC de chaque domaine, l'objet PowerShell précédemment crée lors de l'itération courante
			$Array += $Line

			#Supprime les valeurs des variables propres à la KB actuellement requêtée du DC actuellement requêté
			Clear-Variable DCHotFixID, Line
		}

		#Supprime les valeurs des variables propres au DC actuellement requêté
        Clear-Variable DC
    }

	#Supprime les valeurs des variables propres au domaine actuellement requêté
    Clear-Variable Domain, DCs
}

#Affiche sous forme de liste l'ensemble des KB requêtées des DC de chaque domaine avec leurs status
$Array

<#Exemple d'affichage
DomainController  : DC01.customer.intern
Domain            : customer.intern
OperatingSystem   : Windows Server 2022 Standard
HotFixIDSearched  : KB5022511
KBIsInstalled     : Fail
HotFixInstalledBy : NULL
HotFixInstalledOn : NULL
HotFixDescription : NULL

DomainController  : DC01.customer.intern
Domain            : staff.nsi.dir
OperatingSystem   : Windows Server 2022 Standard
HotFixIDSearched  : KB4589208
KBIsInstalled     : Fail
HotFixInstalledBy : NULL
HotFixInstalledOn : NULL
HotFixDescription : NULL

DomainController  : DC02.technical.intern
Domain            : technical.intern
OperatingSystem   : Windows Server 2019 Standard
HotFixIDSearched  : KB5022511
KBIsInstalled     : Success
HotFixInstalledBy : NT AUTHORITY\SYSTEM
HotFixInstalledOn : 15/02/2023 00:00:00
HotFixDescription : Update

DomainController  : DC02.technical.intern
Domain            : technical.intern
OperatingSystem   : Windows Server 2019 Standard
HotFixIDSearched  : KB4589208
KBIsInstalled     : Success
HotFixInstalledBy : NT AUTHORITY\SYSTEM
HotFixInstalledOn : 28/01/2021 00:00:00
HotFixDescription : Update
#></pre>

 

PowerShell – Récupérer la configuration système des contrôleurs de domaine d’une forêt Active Directory

<pre class="wp-block-syntaxhighlighter-code">#Informations récupérées : Nom du contrôleur de domaine, domaine AD, adresse IP, OS, CPU, taille du disque C, taille restante du disque C, RAM
#Evolution du script : certains attributs non utilisés sont récupérés pour pouvoir éventuellement augmenter le nombre d'informations récupéré 

#Prérequis 1 : l'utilisateur qui lance ce script doit pouvoir requêter les bases WMI de tout les contrôleurs de domaine (DC) de la forêt
#Prérequis 2 : le script suppose qu'un seul adapteur réseau de chaque DC posséde une ou plusieurs adresses IP
#Prérequis 3 : le script suppose que le système d'exploitation de chaque DC est installé sur C:

#Importe le module Active Directory qui contient des commandes utilisées dans le script
Import-Module ActiveDirectory

#Permet de récupérer le nom des domaines de la forêt de façon dynamique
$Domains = Get-ADForest | Select-Object Domains
$Domains = $Domains.Domains

#Créer un tableau qui contiendra l'ensemble des DC de tout les domaines de la forêt
$DCToGetConfiguration = @()

#Parcours un par un chaque domaine de la forêt
foreach ($Domain in $Domains)
{
	#Pour chaque domaine de la forêt, récupére l'ensemble des DC du domaine
	$DomainControllersFromCurrentDomain = (Get-ADDomainController -Server $Domain -Filter * | Select-Object HostName, Domain, IPv4Address).HostName

	#Pour chaque domaine de la forêt, ajoute l'ensemble des DC du domaine à l'ensemble des DC de la forêt
	$DCToGetConfiguration += $DomainControllersFromCurrentDomain
}

#Créer un tableau qui contiendra chaque DC de la forêt avec sa configuration
$Array = @()

#Parcours un par un chaque DC de chaque domaine de la forêt, récupéré précédemment
foreach ($ServerToGetConfiguration in $DCToGetConfiguration)
{
	#Créer un objet PowerShell qui contiendra la configuration du DC actuellement requêté
    $Line = New-Object PSObject

	#Ajoute à l'objet PowerShell précédemment crée, le nom du DC actuellement requêté
    $Line | Add-Member -MemberType NoteProperty -Name "HostName" -Value $ServerToGetConfiguration

	#Récupére le domaine AD d'appartenance du DC actuellement requêté
	$WMIComputerSystemObject = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $ServerToGetConfiguration | Select-Object Name, Domain

	#Ajoute à l'objet PowerShell précédemment crée, le domaine AD d'appartenance du DC actuellement requêté
	$Line | Add-Member -MemberType NoteProperty -Name "Domain" -Value $WMIComputerSystemObject.Domain

	#Récupére l'adresse IP du DC actuellement requêté
	$WMINetworkAdapterConfigurationObjects = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName $ServerToGetConfiguration | Select-Object PSComputerName, IPAddress, IPSubnet, DefaultIPGateway, DNSServerSearchOrder

	#La commande Get-WmiObject -Class Win32_NetworkAdapterConfiguration récupére les adaptateurs réseaux, certains d'entre eux ne comportent pas de carte réseau
	#La boucle suivante ne permet de récupérer que la carte réseau qui contient une adresse IP
	#Cette portion du script ne marchera pas si plusieurs cartes réseaux contiennent chacune une IP
	foreach ($NetworkAdapterConfigurationObject in $WMINetworkAdapterConfigurationObjects)
	{
		if ($NetworkAdapterConfigurationObject.IPAddress)
		{
			$Line | Add-Member -MemberType NoteProperty -Name "IPAddress" -Value ([string]($NetworkAdapterConfigurationObject.IPAddress))
		}
	}

	#Récupére le système d'exploitation du DC actuellement requêté
	$WMIOperatingSystemObject = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $ServerToGetConfiguration | Select-Object PSComputerName, Caption, BuildNumber

	#Ajoute à l'objet PowerShell précédemment crée, système d'exploitation du DC actuellement requêté
	$Line | Add-Member -MemberType NoteProperty -Name "OperatingSystem" -Value $WMIOperatingSystemObject.Caption
	
	#Récupére les CPU du DC actuellement requêté
    $WMIProcessorObjects = Get-WmiObject -Class Win32_Processor -ComputerName $ServerToGetConfiguration | Select-Object PSComputerName, Name, MaxClockSpeed, Manufacturer, NumberOfCores, NumberOfEnabledCore, NumberOfLogicalProcessors

	#Boucle qui va additioner l'ensemble des CPU du DC requêté pour obtenir le nombre total de CPU
	$CPUNumbers = 0
	foreach ($WMIProcessorObject in  $WMIProcessorObjects)
	{
		$CPUNumbers += 1
	}

	#Ajoute à l'objet PowerShell précédemment crée, le nombre total de CPU du DC actuellement requêté
	$Line | Add-Member -MemberType NoteProperty -Name "CPU_total" -Value $CPUNumbers

	#Récupére l'espace disque du DC actuellement requêté
	$WMILogicalDiskObjects = Get-WMIObject -Class Win32_LogicalDisk -ComputerName $ServerToGetConfiguration | Select-Object PSComputerName, DeviceID, FileSystem, MaximumComponentLength, Size, FreeSpace

	#Boucle qui va parcourir chaque disque du DC requêté et ajoute à l'objet PowerShell précédemment crée, l'espace disque total et restant de C: et l'affiche en GB
	foreach ($WMILogicalDiskObject in $WMILogicalDiskObjects)
	{
		if ($WMILogicalDiskObject.DeviceID -eq "C:")
		{
			$Line | Add-Member -MemberType NoteProperty -Name "Disk_size(GB)" -Value ([math]::truncate(($WMILogicalDiskObject.Size)/1GB))
			$Line | Add-Member -MemberType NoteProperty -Name "Disk_free(GB)" -Value ([math]::truncate(($WMILogicalDiskObject.FreeSpace)/1GB))
		}
	}

	#Récupére les RAM du DC actuellement requêté
	$WMIPhysicalMemoryObjects = Get-WmiObject -Class Win32_PhysicalMemory -ComputerName $ServerToGetConfiguration | Select-Object PSComputerName, BankLabel, Capacity, Manufacturer

	#Boucle qui va additionner l'ensemble des RAM du DC requêté pour obtenir le nombre total de RAM
	$RAMnumbers = 0 
	foreach ($WMIPhysicalMemoryObject in $WMIPhysicalMemoryObjects)
	{
		$RAMnumbers += $WMIPhysicalMemoryObject.Capacity
	}
	
	#Ajoute à l'objet PowerShell précédemment crée, le nombre total de RAM du DC actuellement requêté
	$Line | Add-Member -MemberType NoteProperty -Name "Memory(MB)" -Value ([math]::truncate(($RAMnumbers)/1MB))

	#Ajoute à la variable globale qui contient l'ensemble des configuration des DC, l'objet PowerShell précédemment crée de l'itération courante
	$Array += $Line

	#Supprime les valeurs des variables propres au DC actuellement requêté
	Clear-Variable Line, WMIComputerSystemObject, WMINetworkAdapterConfigurationObjects, WMIOperatingSystemObject, CPUNumbers, WMILogicalDiskObjects, WMIPhysicalMemoryObject
}

#Affiche sous forme de liste l'ensemble des DC avec leurs configurations
$Array

<#Exemple d'affichage
HostName        : DC01.customer.intern
Domain          : customer.intern
IPAddress       : 192.168.1.50
OperatingSystem : Microsoft Windows Server 2019 Standard
CPU_total       : 4
Disk_size(GB)   : 50
Disk_free(GB)   : 30
Memory(MB)      : 16384

HostName        : DC02.technical.intern
Domain          : technical.intern
IPAddress       : 192.168.1.51
OperatingSystem : Microsoft Windows Server 2022 Standard
CPU_total       : 4
Disk_size(GB)   : 100
Disk_free(GB)   : 60
Memory(MB)      : 16384
#></pre>