Comment trouver des ordinateurs inactifs dans Active Directory à l’aide de PowerShell ? 

Comprendre la nécessité d’identifier les ordinateurs inactifs dans Active Directory

Les ordinateurs inactifs dans AD (Active Directory) peuvent présenter des risques pour la sécurité et l’efficacité de l’entreprise. Ces machines peuvent ne plus exister physiquement, mais rester à l’état d’entrées dormantes, créant un encombrement et des points d’entrée potentiels pour les acteurs malveillants. L’identification et la suppression régulières de ces entrées permettent de garantir un environnement Active Directory propre et sécurisé.

Ce script PowerShell automatise la tâche consistant à localiser les ordinateurs inactifs depuis un certain nombre de jours. Il fournit aux professionnels de l’informatique des informations exploitables et s’intègre même aux champs personnalisés de NinjaOne pour des rapports rationalisés.

Le script :

#Requires -Version 5.1

<#
.SYNOPSIS
    Gets computers that have been inactive for a specified number of days.
.DESCRIPTION
    Gets computers that have been inactive for a specified number of days.
    The number of days to consider a computer inactive can be specified as a parameter or saved to a custom field.

    By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).

PARAMETER: -InactiveDays 30
    The number of days to consider a computer inactive. Computers that have been inactive for this number of days will be included in the report.
.EXAMPLE
    -InactiveDays 30
    ## EXAMPLE OUTPUT WITH InactiveDays ##
    [Info] Searching for computers that are inactive for 30 days or more.
    [Info] Found 11 inactive computers.

PARAMETER: -InactiveDays 30 -WysiwygCustomField "ReplaceMeWithAnyWysiwygCustomField"
    The number of days to consider a computer inactive. Computers that have been inactive for this number of days will be included in the report.
.EXAMPLE
    -InactiveDays 30 -WysiwygCustomField "ReplaceMeWithAnyWysiwygCustomField"
    ## EXAMPLE OUTPUT WITH WysiwygCustomField ##
    [Info] Searching for computers that are inactive for 30 days or more.
    [Info] Found 11 inactive computers.
    [Info] Attempting to set Custom Field 'Inactive Computers'.
    [Info] Successfully set Custom Field 'Inactive Computers'!

.NOTES
    Minimum OS Architecture Supported: Windows Server 2016
    Release Notes: Initial Release
#>

[CmdletBinding()]
param (
    [Parameter()]
    $InactiveDays,
    [Parameter()]
    [String]$WysiwygCustomField
)

begin {
    function Test-IsElevated {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)
        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
    }
    function Set-NinjaProperty {
        [CmdletBinding()]
        Param(
            [Parameter(Mandatory = $True)]
            [String]$Name,
            [Parameter()]
            [String]$Type,
            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]
            $Value,
            [Parameter()]
            [String]$DocumentName
        )
    
        $Characters = $Value | Measure-Object -Character | Select-Object -ExpandProperty Characters
        if ($Characters -ge 10000) {
            throw [System.ArgumentOutOfRangeException]::New("Character limit exceeded, value is greater than 10,000 characters.")
        }
        
        # If we're requested to set the field value for a Ninja document we'll specify it here.
        $DocumentationParams = @{}
        if ($DocumentName) { $DocumentationParams["DocumentName"] = $DocumentName }
        
        # This is a list of valid fields that can be set. If no type is given, it will be assumed that the input doesn't need to be changed.
        $ValidFields = "Attachment", "Checkbox", "Date", "Date or Date Time", "Decimal", "Dropdown", "Email", "Integer", "IP Address", "MultiLine", "MultiSelect", "Phone", "Secure", "Text", "Time", "URL", "WYSIWYG"
        if ($Type -and $ValidFields -notcontains $Type) { Write-Warning "$Type is an invalid type! Please check here for valid types. https://ninjarmm.zendesk.com/hc/en-us/articles/16973443979789-Command-Line-Interface-CLI-Supported-Fields-and-Functionality" }
        
        # The field below requires additional information to be set
        $NeedsOptions = "Dropdown"
        if ($DocumentName) {
            if ($NeedsOptions -contains $Type) {
                # We'll redirect the error output to the success stream to make it easier to error out if nothing was found or something else went wrong.
                $NinjaPropertyOptions = Ninja-Property-Docs-Options -AttributeName $Name @DocumentationParams 2>&1
            }
        }
        else {
            if ($NeedsOptions -contains $Type) {
                $NinjaPropertyOptions = Ninja-Property-Options -Name $Name 2>&1
            }
        }
        
        # If an error is received it will have an exception property, the function will exit with that error information.
        if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions }
        
        # The below types require values not typically given in order to be set. The below code will convert whatever we're given into a format ninjarmm-cli supports.
        switch ($Type) {
            "Checkbox" {
                # While it's highly likely we were given a value like "True" or a boolean datatype it's better to be safe than sorry.
                $NinjaValue = [System.Convert]::ToBoolean($Value)
            }
            "Date or Date Time" {
                # Ninjarmm-cli expects the GUID of the option to be selected. Therefore, the given value will be matched with a GUID.
                $Date = (Get-Date $Value).ToUniversalTime()
                $TimeSpan = New-TimeSpan (Get-Date "1970-01-01 00:00:00") $Date
                $NinjaValue = $TimeSpan.TotalSeconds
            }
            "Dropdown" {
                # Ninjarmm-cli is expecting the guid of the option we're trying to select. So we'll match up the value we were given with a guid.
                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header "GUID", "Name"
                $Selection = $Options | Where-Object { $_.Name -eq $Value } | Select-Object -ExpandProperty GUID
        
                if (-not $Selection) {
                    throw [System.ArgumentOutOfRangeException]::New("Value is not present in dropdown")
                }
        
                $NinjaValue = $Selection
            }
            default {
                # All the other types shouldn't require additional work on the input.
                $NinjaValue = $Value
            }
        }
        
        # We'll need to set the field differently depending on if its a field in a Ninja Document or not.
        if ($DocumentName) {
            $CustomField = Ninja-Property-Docs-Set -AttributeName $Name -AttributeValue $NinjaValue @DocumentationParams 2>&1
        }
        else {
            $CustomField = Ninja-Property-Set -Name $Name -Value $NinjaValue 2>&1
        }
        
        if ($CustomField.Exception) {
            throw $CustomField
        }
    }
}
process {
    if (-not (Test-IsElevated)) {
        Write-Host "[Error] Access Denied. Please run with Administrator privileges."
        exit 1
    }

    # Get Script Variables and override parameters with them
    if ($env:inactiveDays -and $env:inactiveDays -notlike "null") {
        $InactiveDays = $env:inactiveDays
    }
    if ($env:wysiwygCustomField -and $env:wysiwygCustomField -notlike "null") {
        $WysiwygCustomField = $env:wysiwygCustomField
    }

    # Parameter Requirements
    if ([string]::IsNullOrWhiteSpace($InactiveDays)) {
        Write-Host "[Error] Inactive Days is required."
        exit 1
    }
    elseif ([int]::TryParse($InactiveDays, [ref]$null) -eq $false) {
        Write-Host "[Error] Inactive Days must be a number."
        exit 1
    }

    # Check that Active Directory module is available
    if (-not (Get-Module -ListAvailable -Name ActiveDirectory)) {
        Write-Host "[Error] Active Directory module is not available. Please install it and try again."
        exit 1
    }

    try {
        # Get the date in the past $InactiveDays days
        $InactiveDate = (Get-Date).AddDays(-$InactiveDays)
        # Get the SearchBase for the domain
        $Domain = "DC=$(
            $(Get-CimInstance Win32_ComputerSystem).Domain -split "\." -join ",DC="
        )"
        Write-Host "[Info] Searching for computers that are inactive for $InactiveDays days or more."

        # For Splatting parameters into Get-ADComputer
        $GetComputerSplat = @{
            Property   = "Name", "LastLogonTimeStamp", "OperatingSystem"
            # LastLogonTimeStamp is converted to a DateTime object from the Get-ADComputer cmdlet
            Filter     = { (Enabled -eq "true") -and (LastLogonTimeStamp -le $InactiveDate) }
            SearchBase = $Domain
        }

        # Get inactive computers that are not active in the past $InactiveDays days
        $InactiveComputers = Get-ADComputer @GetComputerSplat | Select-Object "Name", @{
            # Format the LastLogonTimeStamp property to a human-readable date
            Name       = "LastLogon"
            Expression = {
                if ($_.LastLogonTimeStamp -gt 0) {
                    # Convert LastLogonTimeStamp to a datetime
                    $lastLogon = [DateTime]::FromFileTime($_.LastLogonTimeStamp)
                    # Format the datetime
                    $lastLogonFormatted = $lastLogon.ToString("MM/dd/yyyy hh:mm:ss tt")
                    return $lastLogonFormatted
                }
                else {
                    return "01/01/1601 00:00:00 AM"
                }
            }
        }, "OperatingSystem"

        if ($InactiveComputers -and $InactiveComputers.Count -gt 0) {
            Write-Host "[Info] Found $($InactiveComputers.Count) inactive computers."
        }
        else {
            Write-Host "[Info] No inactive computers were found."
        }
    }
    catch {
        Write-Host "[Error] Failed to get inactive computers. Please try again."
        exit 1
    }

    # Save the results to a custom field
    if ($WysiwygCustomField) {
        try {
            Write-Host "[Info] Attempting to set Custom Field '$WysiwygCustomField'."
            Set-NinjaProperty -Name $WysiwygCustomField -Value $($InactiveComputers | ConvertTo-Html -Fragment | Out-String)
            Write-Host "[Info] Successfully set Custom Field '$WysiwygCustomField'!"
        }
        catch {
            Write-Host "[Error] Failed to set Custom Field '$WysiwygCustomField'."
            $ExitCode = 1
        }
    }

    $InactiveComputers | Format-Table -AutoSize | Out-String -Width 4000 | Write-Host

    exit $ExitCode
}
end {
    
    
    
}

 

Gagnez du temps grâce à plus de 300 scripts du Dojo NinjaOne.

Obtenir l’accès

Fonctionnement du script PowerShell

Ce script est conçu pour les professionnels de l’informatique qui gèrent des environnements AD et nécessite PowerShell 5.1 ou une version plus récente. Voici une description détaillée de son fonctionnement :

Prérequis

  • Privilèges administratifs : Le script vérifie l’existence de privilèges élevés, ce qui garantit qu’il s’exécute de manière sûre et efficace.
  • Module Active Directory : Le script s’appuie sur le module Active Directory PowerShell pour interagir avec les objets AD.
  • Configuration des champs personnalisés (facultatif) : Si vous utilisez NinjaOne, le script peut écrire les résultats dans un champ personnalisé pour faciliter le suivi.

Composants clés

  1. Traitement des paramètres :
    Le script accepte deux paramètres :

    1. -InactiveDays : spécifie le seuil (en jours) à partir duquel un ordinateur est considéré comme inactif.
    2. -WysiwygCustomField : paramètre optionnel pour enregistrer les résultats dans un champ personnalisé dans NinjaOne.
  2. Remplacement des variables d’environnement :
    Le script peut extraire des valeurs de configuration des variables d’environnement, ce qui permet des ajustements dynamiques sans codage en dur des paramètres.
  3. Recherche informatique inactive :
    Avec “Get-ADComputer”, le script recherche dans AD les ordinateurs dont le LastLogonTimeStamp (horodatage de la dernière connexion) est plus ancien que le seuil spécifié. Il convertit le LastLogonTimeStamp dans un format lisible par l’homme afin d’améliorer les rapports.
  4. Intégration de champs personnalisés :
    Si l’option -WysiwygCustomField est spécifiée, le script utilise une fonction Set-NinjaProperty pour enregistrer les résultats au format HTML dans les champs personnalisés de NinjaOne.
  5. Gestion des erreurs :
    Le script comprend des contrôles d’erreur efficaces pour la disponibilité des modules, la validation des paramètres et le traitement des résultats, ce qui garantit une exécution en toute simplicité.

Cas d’utilisation pratiques

Scénario : Nettoyer un réseau dormant

Une entreprise MSP gérant le réseau d’une entreprise de taille moyenne remarque un pic dans les échecs de connexion et soupçonne les comptes d’ordinateur inactifs dans AD de contribuer aux vulnérabilités de sécurité. Grâce à ce script, l’équipe informatique identifie rapidement les ordinateurs inactifs depuis plus de 60 jours et exporte les résultats pour examen. Grâce à ces informations, ils nettoient AD, améliorant ainsi l’efficacité et la sécurité du réseau.

Scénario : Maintenance proactive

Une entreprise implémente le script dans le cadre de sa routine de maintenance trimestrielle, afin de s’assurer que son Active Directory reste léger et à jour. L’intégration du script avec NinjaOne permet à l’équipe informatique de conserver un historique des ordinateurs inactifs à des fins d’audit.

Comparaison de ce script avec d’autres méthodes

Requêtes manuelles :

Alors que les administrateurs informatiques peuvent interroger manuellement AD à l’aide de cmdlets PowerShell tels que “Get-ADComputer”, ce script automatise le processus, garantissant des résultats cohérents et réduisant les erreurs humaines.

Outils tiers :

Les outils commerciaux de nettoyage AD offrent des fonctionnalités similaires mais ont un coût. Ce script propose une alternative gratuite et personnalisable, avec l’avantage supplémentaire d’une intégration avec NinjaOne.

Outils GUI intégrés :

L’utilisation des outils d’administration AD pour cette tâche peut s’avérer fastidieuse et chronophage. Le script rationalise le processus, en particulier pour les environnements de grande taille.

Questions fréquentes

Puis-je utiliser ce script sans NinjaOne ?

Tout à fait. Le script fonctionne de manière autonome pour identifier les ordinateurs inactifs. L’intégration de NinjaOne est facultative.

Comment le script détermine-t-il l’inactivité ?

Il vérifie l’attribut LastLogonTimeStamp des comptes d’ordinateur et le compare au seuil spécifié.

Ce script peut-il être utilisé en toute sécurité ?

Oui, mais veillez à ce qu’il fonctionne dans un environnement sécurisé et avec les autorisations appropriées. Testez dans un environnement de non-production si vous n’êtes pas sûr.

Puis-je modifier le script pour d’autres objets AD, comme les utilisateurs ?

Oui, en apportant des modifications mineures à la cmdlet “Get-ADComputer”, vous pouvez cibler des utilisateurs ou d’autres objets AD.

Ce qu’implique l’utilisation de ce script

Le nettoyage des ordinateurs inactifs réduit la surface d’attaque de votre réseau, minimise l’encombrement et améliore les performances d’Active Directory. En utilisant régulièrement ce script, les entreprises peuvent maintenir une sécurité plus stricte et assurer la conformité avec les politiques de gouvernance informatique.

Recommandations pour l’utilisation de ce script

  1. Exécutez en tant qu’administrateur : veillez à exécuter le script avec des privilèges élevés.
  2. Testez en environnement contrôlé avant de le déployer en production, testez le script dans un environnement contrôlé pour vous assurer qu’il fonctionne comme prévu.
  3. Automatisez les processus : Planifiez l’exécution régulière du script à l’aide du planificateur de tâches ou d’un outil similaire.
  4. Utilisez-le avec NinjaOne : Tirez parti de l’intégration pour maintenir des rapports complets au sein de votre plateforme RMM.

Conclusion

La gestion des ordinateurs inactifs dans Active Directory est une tâche essentielle pour les professionnels de l’informatique. Ce script PowerShell fournit une solution efficace et flexible, automatisant le processus d’identification et s’intégrant de manière fluide avec NinjaOne pour un reporting amélioré. En intégrant ces outils dans leurs flux de travail, les équipes informatiques peuvent améliorer la sécurité, rationaliser les opérations et maintenir un environnement Active Directory propre.

Pour les professionnels de l’informatique qui cherchent à simplifier la gestion d’AD, NinjaOne offre des outils puissants qui complètent les scripts de ce type, permettant une surveillance rationalisée et une maintenance proactive.

Pour aller plus loin

Pour créer une équipe informatique efficace et performante, il est essentiel d'avoir une solution centralisée qui joue le rôle de nœud principal pour vos services. NinjaOne permet aux équipes informatiques de surveiller, gérer, sécuriser et prendre en charge tous les appareils, où qu'ils soient, sans avoir besoin d'une infrastructure complexe sur site. Pour en savoir plus sur NinjaOne Endpoint Management, participez à une visite guidée, ou profitez d'un essai gratuit de la plateforme NinjaOne.

Catégories :

Vous pourriez aussi aimer

×

Voir NinjaOne en action !

En soumettant ce formulaire, j'accepte la politique de confidentialité de NinjaOne.

Termes et conditions NinjaOne

En cliquant sur le bouton “J’accepte” ci-dessous, vous indiquez que vous acceptez les termes juridiques suivants ainsi que nos conditions d’utilisation:

  • Droits de propriété: NinjaOne possède et continuera de posséder tous les droits, titres et intérêts relatifs au script (y compris les droits d’auteur). NinjaOne vous accorde une licence limitée pour l’utilisation du script conformément à ces conditions légales.
  • Limitation de l’utilisation: Les scripts ne peuvent être utilisés qu’à des fins personnelles ou professionnelles internes légitimes et ne peuvent être partagés avec d’autres entités.
  • Interdiction de publication: Vous n’êtes en aucun cas autorisé à publier le script dans une bibliothèque de scripts appartenant à, ou sous le contrôle d’un autre fournisseur de logiciels.
  • Clause de non-responsabilité: Le texte est fourni “tel quel” et “tel que disponible”, sans garantie d’aucune sorte. NinjaOne ne promet ni ne garantit que le script sera exempt de défauts ou qu’il répondra à vos besoins ou attentes particulières.
  • Acceptation des risques: L’utilisation du script est sous votre propre responsabilité. Vous reconnaissez qu’il existe certains risques inhérents à l’utilisation du script, et vous comprenez et assumez chacun de ces risques.
  • Renonciation et exonération de responsabilité: Vous ne tiendrez pas NinjaOne pour responsable des conséquences négatives ou involontaires résultant de votre utilisation du script, et vous renoncez à tout droit ou recours légal ou équitable que vous pourriez avoir contre NinjaOne en rapport avec votre utilisation du script.
  • EULA: Si vous êtes un client de NinjaOne, votre utilisation du script est soumise au contrat de licence d’utilisateur final qui vous est applicable (End User License Agreement (EULA)).