
Outil d'inventaire client et de détection de dérive basé sur Azure qui collecte les données de configuration Windows (antivirus, correctifs, Bitlocker) dans LogAnalytics pour des tableaux de bord pilotés par KQL et des alertes Sentinel.

Avez-vous le contrôle ? – ou certains de vos processus d'infrastructure de base comme le patching, l'antivirus, l'activation de BitLocker dérivent-ils ? Ou souhaitez-vous réaliser un inventaire avancé, où vous pouvez consulter votre état de garantie auprès de la garantie Lenovo ou Dell ? Alors continuez à lire.
Découvrez ClientInspector, qui peut vous aider à obtenir une excellente visibilité sur votre environnement client complet.
ClientInspector est gratuit pour la communauté – conçu pour être une vitrine sympa de la manière dont vous pouvez récupérer des données depuis vos clients en utilisant Azure Log Ingestion Pipeline, Azure Data Collection Rules, Azure Log Analytics ; les visualiser avec Azure Monitor & Azure Dashboards – et obtenir des « alertes de dérive » avec Microsoft Sentinel.
Vidéo 3m 01s - Tableaux de bord
ClientInspector (v2) télécharge les données collectées dans des journaux personnalisés dans l'espace de travail Azure Log Analytics – en utilisant l'API d'ingestion de journaux, Azure Data Collection Rules (DCR) et Azure Data Collection Endpoints (DCE).




Il est important pour moi de préciser que je n'essaie pas de construire un outil de gestion séparé qui concurrencerait la pile de sécurité et de gestion Microsoft.
Rien ne surpasse la pile de gestion/sécurité Microsoft Azure/M365. Ce sont des solutions de premier ordre.
Mais je suis vraiment passionné par les capacités de journalisation et le pouvoir de ramener des données depuis les clients, serveurs, cloud et systèmes tiers – et d'en tirer des informations intéressantes et précieuses.
J'ai une solution similaire pour les serveurs – ServerInspector. Malheureusement, elle n'est pas publique.
Un grand merci aux personnes formidables des équipes produits Microsoft – vous êtes des rock stars 😄
Bonne chasse 😄
Quelles données sont collectées ?
Tableaux de bord d'état souhaité – Comment obtenir une visibilité sur mon environnement à partir des données ?
Comment interroger les données ? - Kusto (KQL) est la réponse
Architecture, Schéma & Réseau
Implémentation
Dépendances
Exécution de ClientInspector.ps1 - 3 modes
Exemple de sortie de ClientInspector
Sécurité
Disposition de l'ensemble de données ClientInspector
Mode verbeux et plus d'aide
Coût – Combien coûte le stockage de ces données ?
Bugs découverts, veuillez m'informer
Contact
Vidéo 3m 19s - Exécution de ClientInspector en ligne de commande (mode normal)
Vidéo 1m 40s - Création automatique de 2 tables et de DCR (mode verbeux)
Vidéo 1m 37s - Création automatique de 2 tables et de DCR (mode normal)
Vidéo 1m 34s - Voir le schéma de DCR et de la table
Vidéo 2m 19s - Manipulation des données
Vidéo 1m 58s - Requêtes Kusto sur les données
Vidéo 3m 01s - Tableaux de bord
Vidéo 0m 48s - Exemple d'utilisation des données - consultation de la base de garantie Lenovo
Vidéo 7m 25s - Déploiement via ClientInspector DeploymentKit
ClientInspector peut être utilisé pour collecter beaucoup d'informations précieuses sur vos clients Windows – et envoyer les données vers des tables personnalisées Azure Log Analytics.
Le script collecte les informations suivantes (paramètres, informations, configuration, état) :
N'hésitez pas à ajouter d'autres collectes de données intéressantes pour répondre à vos besoins. Si vous souhaitez participer à la communauté, veuillez m'envoyer un email avec vos collectes, si vous pensez qu'elles peuvent profiter à l'ensemble de la communauté.
Vous pouvez utiliser n'importe quelle source de données qui peut être récupérée dans PowerShell (wmi, cim, données externes, api rest, format xml, format json, format csv, etc.)
Il est très important de comprendre que les données doivent généralement être manipulées avant de les envoyer – pour garantir leur validité et supprimer toute donnée non pertinente.
ClientInspector utilise les 24 fonctions du module PowerShell AzLogDcIngestPS pour gérer la manipulation des données sources – supprimer le « bruit » dans les données, renommer les colonnes interdites dans les tables/DCR – et répondre aux besoins de transparence avec une visibilité supplémentaire comme UserLoggedOn, CollectionTime, Computer :
Write-Output "" Write-Output "Collecting Bios information ... Please Wait !"
$DataVariable = Get-CimInstance -ClassName Win32_BIOS
#-------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------
$DataVariable = Convert-CimArrayToObjectFixStructure -data $DataVariable -Verbose:$Verbose
$DataVariable = Add-CollectionTimeToAllEntriesInArray -Data $DataVariable -Verbose:$Verbose
$DataVariable = Add-ColumnDataToAllEntriesInArray -Data $DataVariable -Column1Name Computer -Column1Data $Env:ComputerName -Column2Name UserLoggedOn -Column2Data $UserLoggedOn -Verbose:$Verbose
$DataVariable = Filter-ObjectExcludeProperty -Data $DataVariable -ExcludeProperty __*,SystemProperties,Scope,Qualifiers,Properties,ClassPath,Class,Derivation,Dynasty,Genus,Namespace,Path,Property_Count,RelPath,Server,Superclass -Verbose:$Verbose
Dans le cadre du déploiement initial utilisant ClientInSpectorV2-DeploymentKit, vous aurez accès à de nombreux tableaux de bord Azure et classeurs Azure.
Vidéo 3m 01s - Tableaux de bord
L'idée des tableaux de bord est de montrer où votre infrastructure s'écarte de l'« état souhaité ». Considérez-les comme des KPI, où l'infrastructure n'est pas sous contrôle.
Au lieu d'avoir une tâche de correction et de gestion de l'antivirus, vous pouvez envisager d'avoir des KPI, qui montreront où les ordinateurs ne sont pas patchés - ou où la protection en temps réel de l'antivirus n'est pas active - ou les machines qui ont eu un écran bleu au cours des dernières 24 heures.
C'est le même concept que le Microsoft Secure Score.















Lien pour voir la liste complète des classeurs Azure fournis
Tous les exemples de tableaux de bord Azure sont créés à partir d'éléments épinglés de classeurs Azure, donc si vous souhaitez explorer en détail, vous pouvez cliquer sur un lien et accéder aux informations détaillées.

Lien pour voir les tableaux de bord Azure fournis
Si vous souhaitez ajouter d'autres tableaux de bord ou classeurs, vous commencerez généralement par examiner les données collectées dans les tables de journaux personnalisées à l'aide de requêtes KQL. Lorsque vous avez trouvé la requête souhaitée, vous pouvez créer de nouvelles vues dans les classeurs - et épingler vos favoris à vos tableaux de bord.
Si vous ne connaissez pas le langage Kusto, je vous recommande de commencer à l'expérimenter, car c'est un langage vraiment puissant.
Vidéo 1m 58s - Requêtes Kusto sur les données
Vidéo 3m 01s - Tableaux de bord
Écrivez votre première requête avec le langage de requête Kusto
Analysez les résultats de requête avec KQL
Voici 4 exemples de requêtes pour vous aider à démarrer - basés sur les données de ClientInspector.
Si vous souhaitez effectuer une recherche avancée, vous pouvez utiliser des requêtes Kusto (KQL) traditionnelles dans les tables
#----------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------
$LogAnalyticsWorkspaceId = "e74ca75a-c0e6-4933-a4f7-e5ae943fe4ac"
#----------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------- $Query = @' InvClientComputerInfoBiosV2_CL | summarize TimeGenerated = arg_max(TimeGenerated,) by Computer | join (InvClientComputerInfoSystemV2_CL | summarize TimeGenerated = arg_max(TimeGenerated,) by Computer) on $left.Computer == $right.Computer | join (InvClientComputerOSInfoV2_CL | summarize TimeGenerated = arg_max(TimeGenerated,*) by Computer) on $left.Computer == $right.Computer | project Computer, UserLoggedOn, SerialNumber, Manufacturer, PCSystemType, SystemFamily, Model, Windows=Caption2, WindowsVersion=Version1, TimeGenerated '@
write-output "Collecting computer information from LogAnalytics" $Query = Invoke-AzOperationalInsightsQuery -WorkspaceId $LogAnalyticsWorkspaceId -Query $Query $ComputerInfoArray = $Query.Results $ComputerInfoArray
</details>
## Exemple de requête 4 : Intégration de données avec d'autres sources (vérification de garantie contre la base de données de garantie Lenovo)
Lorsque nous avons les données dans Azure LogAnalytics, nous pouvons commencer à intégrer les données avec d'autres sources, comme les données de garantie Dell ou Lenovo via une recherche API REST.
[Vidéo 0m 48s - Exemple d'utilisation des données - recherche dans la base de garantie Lenovo](https://youtu.be/3ZDyTwiLU0w)
Voici un exemple de sortie, créée automatiquement par un script PowerShell - extrayant une liste d'ordinateurs et de numéros de série - puis effectuant une recherche dans la base de données de garantie Lenovo pour récupérer des informations sur la date d'achat de l'ordinateur et son état de garantie.
[Exemple de sortie de garantie (Excel), basé sur les données collectées par ClientInspector](https://github.com/KnudsenMorten/ClientInspectorV2/raw/main/img/WarrantyInfo.xlsx)
<br>
# Architecture, schéma et réseau
ClientInspector (v2) télécharge les données collectées dans **les journaux personnalisés** de **l'espace de travail Azure LogAnalytics** - en utilisant **l'API d'ingestion de journaux**, **les règles de collecte de données Azure (DCR)** et **les points de terminaison de collecte de données Azure (DCE)**.

## Schéma
La table DCR et LogAnalytics ont toutes deux un schéma, qui doit correspondre au schéma de l'objet source. Cela est géré en utilisant les fonctions du module AzLogDcrIngestPS.
[Vidéo 1m 40s - Création automatique de 2 tables et DCR (mode verbeux)](https://youtu.be/rIUNs3yT-eI)
[Vidéo 1m 37s - Création automatique de 2 tables et DCR (mode normal)](https://youtu.be/khQMDcON6r8)
[Vidéo 1m 34s - Voir le schéma de la DCR et de la table)](https://youtu.be/NDSNhvpa4Gs)
AzLogDcrIngestPS prend en charge 2 modes de gestion du schéma : **Merge** et **Overwrite**
### SchemaMode = Merge (par défaut)
Si vous définissez SchemaMode = Merge, les nouvelles propriétés de l'objet source seront ajoutées (fusionnées) au schéma actuel de l'analytique des journaux. La DCR importera le schéma de la table d'analytique des journaux pour garantir leur identité.
Le mode par défaut est Merge, si vous ne définissez pas la variable SchemaMode sur les fonctions :
CheckCreateUpdate-TableDr-Structure
CreateUpdate-AzLogAnalyticsCustomLogTableDcr
CreateUpdate-AzDataCollectionRuleLogIngestCustomLog
### SchemaMode = Overwrite
Si vous définissez SchemaMode = Overwrite, le schéma de la DCR et de la table sera écrasé (mis à jour) - en fonction du schéma de l'objet source.
## Réseau
Vous avez 3 options de connectivité à Azure pour le téléchargement des données :
|Méthode de téléchargement|Détails de connectivité|Conformité OS|
|:------------|:-------------------|:------------|
|Accès public|Le point de terminaison REST envoie au DCE via l'adresse IP publique du DCE|Le point de terminaison prend en charge TLS 1.2|
|Accès privé|Le point de terminaison REST envoie au DCE via le lien privé du DCE|Le point de terminaison prend en charge TLS 1.2|
|Log-hub|Le point de terminaison REST envoie les données via [log-hub](https://github.com/KnudsenMorten/AzLogDcrIngestPSLogHub) - un concept que j'ai construit.|Le point de terminaison ne prend pas en charge TLS 1.2.<br> Azure n'acceptera pas la connectivité directe depuis ces appareils.|
### Points de terminaison connectés à Internet - Conformité au niveau OS

Vous devez autoriser les points de terminaison suivants dans votre pare-feu :
|Point de terminaison|Objectif|Port|Direction|Contourner l'inspection HTTPS|
|:-------|:------|:----|:-------|:----------------------|
|global.handler.control.monitor.azure.com|Service de contrôle d'accès|Port 443|Sortant|Oui|
|URI d'ingestion des journaux DCE<br><br>exemple<br>https://dce-log-platform-management-client-demo-p-iur0.westeurope-1.ingest.monitor.azure.com|Ingérer les données des journaux|Port 443|Sortant|Oui|
<br>
### Pas d'accès Internet ou incompatibilité au niveau OS, ex. exécution de TLS 1.0/1.1
[Découvrez le concept log-hub via ce lien](https://github.com/KnudsenMorten/AzLogDcrIngestPSLogHub)

<br>
# Implémentation
Espérons que vous constaterez qu'il est assez simple de tout mettre en place. Les 3 étapes sont décrites ci-dessous.
Avant de commencer, je vous encourage à lire plus en détail les composants dans l'introduction ci-dessous.
<details>
<summary>Introduction des composants Azure utilisés dans ClientInspector</summary>
<br>
Les composants suivants sont nécessaires :
| Ressource Azure | Objectif | Plus d'informations |
| :------------- | :----- | :----- |
| Tout point de terminaison REST | C'est la source qui envoie les données | |
| Log Ingestion API | C'est la nouvelle API qui remplace l'ancienne API HTTP Data Collector | https://learn.microsoft.com/en-us/azure/azure-monitor/logs/logs-ingestion-api-overview |
| Data Collection Endpoint (DCE)| C'est le point d'entrée de la communication depuis le point de terminaison. Les données sont envoyées à un **URI d'ingestion de point de terminaison de collecte de données Azure**. Un seul DCE peut prendre en charge plusieurs DCR, vous pouvez donc spécifier un DCR différent pour différentes sources et tables cibles. | https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/data-collection-endpoint-overview?tabs=portal |
| Data Collection Rules (DCR) | Les règles de collecte de données définissent les données collectées (schéma) et spécifient comment et où ces données doivent être envoyées ou stockées. La DCR doit comprendre la structure des données d'entrée et la structure de la table cible. Si les deux ne correspondent pas, elle peut utiliser une transformation pour convertir les données sources afin qu'elles correspondent à la table cible. Vous pouvez également utiliser la transformation pour filtrer les données sources et effectuer d'autres calculs ou conversions. | https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/data-collection-rule-overview |
| Azure LogAnaltyics Workspace | Les données sont envoyées aux journaux personnalisés dans Azure LogAnalytics | https://learn.microsoft.com/en-us/azure/azure-monitor/logs/log-analytics-overview |
| Azure Workbooks | Dans le cadre du déploiement, des exemples de classeurs seront déployés | https://learn.microsoft.com/en-us/azure/azure-monitor/visualize/workbooks-overview |
| Azure Dashboards | Dans le cadre du déploiement, des exemples de tableaux de bord seront déployés | https://learn.microsoft.com/en-us/azure/azure-monitor/visualize/tutorial-logs-dashboards |
| Kusto (KQL) | Les données peuvent être analysées à l'aide de requêtes Kusto (KQL) | https://learn.microsoft.com/en-us/azure/azure-monitor/logs/get-started-queries |
</details>
Les étapes pour configurer ClientInspector dans votre environnement sont :
1. [Configurer l'environnement à l'aide de ClientInSpectorV2-DeploymentKit](https://github.com/KnudsenMorten/ClientInspectorV2-DeploymentKit)
2. Exécuter ClientInspector la première fois (configuration initiale) - voir plus bas
<details>
<summary>Comment configurer la configuration initiale des tables Azure LogAnalytics et des règles de collecte de données (première fois)</summary>
<br>
Je recommande d'avoir un ordinateur de référence, utilisé pour la gestion des tables/DCR. Ainsi, c'est un processus contrôlé, si des modifications doivent être apportées - par exemple si le schéma de l'objet source change.
<br>
<br>
Configuration :
1. Lorsque vous exécutez le DeploymentKit, il préparera automatiquement le fichier ClientInspector pour vous, il vous suffit donc d'insérer les variables```js
$TenantId = "xxxx"
$LogIngestAppId = "xxxx"
$LogIngestAppSecret = "xxxx"
$DceName = "xxxx"
$LogAnalyticsWorkspaceResourceId = "xxxx"
$AzDcrPrefixClient = "xxx"
$AzDcrSetLogIngestApiAppPermissionsDcrLevel = $false
$AzDcrLogIngestServicePrincipalObjectId = "xxx"
$AzDcrDceTableCreateFromReferenceMachine = @()
$AzDcrDceTableCreateFromAnyMachine = $true
Téléchargez le script de détection ClientInspector_Detection.ps1 (clic droit et choisissez 'Enregistrer le lien sous')
Ouvrez le fichier avec votre éditeur préféré. Ajustez la fréquence à laquelle vous souhaitez que l'inventaire s'exécute.```js ##################################
##################################
$RunEveryHours = 8
$LastRun_RegPath = "HKLM:\SOFTWARE\ClientInspector"
$LastRun_RegKey = "ClientInSpector_System"
3. Maintenant, nous devons créer le travail de correction. Allez dans le portail Microsoft Intune -> Rapports -> Analyse des points de terminaison --> Corrections proactives - et créez un package de script comme indiqué ci-dessous
REMARQUE : Pour le script de correction, utilisez le fichier **ClientInspector.ps1**


### Limitation d'Intune
REMARQUE : Intune a une limitation de 200 Ko pour la taille d'un script de correction.**

Si vous atteignez cette limite, je propose de diviser le script en 2 scripts.


N'oubliez pas d'inclure la section d'en-tête incluant la section UserLoggedOn comme en-tête du deuxième fichier. UserLoggedOn est utilisé pour indiquer quel utilisateur est connecté.
J'ai préparé un [exemple de configuration de script](https://github.com/KnudsenMorten/ClientInspectorV2/tree/main/Sample%20intune%20setup%20if%20file%20size%20is%20more%20than%20200%20Kb), où vous pouvez voir comment les séparer. Remarque : le code n'est PAS mis à jour dans ces scripts, assurez-vous donc de prendre les sections du fichier maître ClientInspector.
Fondamentalement, la structure est :
Le fichier 1 contient l'en-tête + UserLoggedOn (section 1) + sections 2-9 + écrit le drapeau de vérification dans HKLM\Software\ClientInspector\ClientInspector_System_1
Le fichier 2 contient l'en-tête + UserLoggedOn (section 1) + sections 10-18 + écrit le drapeau de vérification dans HKLM\Software\ClientInspector\ClientInspector_System_2



</details>
<details>
<summary>Comment déployer avec ConfigMgr (ou tout autre outil exécutant un fichier CMD) ?</summary>
<br>
Vous exécuterez le script d'inventaire par un package traditionnel + déploiement
1. [Téléchargez le fichier CMD ClientInspector.cmd](https://github.com/KnudsenMorten/ClientInspectorV2/raw/main/ConfigMgr/ClientInspector.cmd) (clic droit et choisissez « Enregistrer la cible sous »)
2. Créez une structure source dans votre répertoire source de package ConfigMgr, par exemple nommée ClientInspector.
3. Copiez les 2 fichiers nécessaires **ClientInspector.cmd** et **ClientInspector.ps1** dans le répertoire
4. Créez un package - et pointez le package pour exécuter **ClientInspector.cmd**
5. Créez un déploiement
</details>
<br>
# Dépendances
## Module PowerShell AzLogDcringestPS - créé par moi (Morten Knudsen)
ClientInspector nécessite le module PowerShell **AzLogDcrIngestPS**
Les fonctionnalités principales du module PowerShell **AzLogDcrIngestPS** comprennent :
* créer/mettre à jour automatiquement les DCR et les tables en fonction du schéma de l'objet source
* valider le schéma pour les problèmes de conventions de nommage. Si des problèmes existent, il les atténue
* mettre à jour le schéma des DCR et des tables si la structure de l'objet source change
* correction automatique si quelque chose se passe mal avec un DCR ou une table
* peut supprimer des données de l'objet source si vous ne souhaitez pas envoyer certaines colonnes de données
* peut convertir des objets source basés sur des objets CIM ou PS en PSCustomObjects/tableau
* peut ajouter des informations pertinentes à chaque enregistrement comme UserLoggedOn, Computer, CollectionTime
Vous pouvez trouver des informations plus détaillées sur le module en utilisant les liens ci-dessous :
[AzLogDcrIngestPS (Github)](https://github.com/KnudsenMorten/AzLogDcrIngestPS)
[AzLogDcrIngestPS (Galerie PowerShell)](https://www.powershellgallery.com/packages/AzLogDcrIngestPS)
[AzLogDcrIngestPSLogHub (Github)](https://github.com/KnudsenMorten/AzLogDcrIngestPSLogHub)
<br>
## Modules PowerShell tiers
Je préfère récupérer les informations sur les mises à jour Windows à l'aide d'un module PowerShell bien connu, PSWindowsUpdate.
|NomModule|Objectif|Plus d'infos|Crédit|
|:---------|:------|:--------|:-----|
|NuGet|Fournisseur de packages courant utilisé pour déployer de nombreux modules PowerShell, y compris AzLogDcrIngestPS<br><br>Le fournisseur de packages sera automatiquement installé sur l'ordinateur lors de l'exécution du script|[Lien](https://www.nuget.org/packages)|
|PSWindowsUpdate|Collecte d'informations sur les mises à jour Windows (mises à jour en attente, installées, etc.)<br><br>Le module sera automatiquement installé sur l'ordinateur lors de l'exécution du script|[Lien](https://www.powershellgallery.com/packages/PSWindowsUpdate)|Michal Gajda
<br>
# Exécution de ClientInspector.ps1 - 3 modes
ClientInspector prend en charge 3 façons d'installer/mettre à jour/importer le module PowerShell nécessaire : **Download**, **PsGallery**, **LocalPath**
Par défaut, il télécharge la dernière version depuis PsGallery dans le scope CurrentUser.
[Vidéo 3m 19s - Exécution de ClientInspector en ligne de commande (mode normal)](https://youtu.be/4kA4BE0zJ9g)
## .\ClientInspector.ps1 -function:LocalPath
ClientInspector recherchera le fichier **AzLogDcrIngest.psm1** dans le répertoire où le script sera exécuté.
Si AzLogDcrIngest.psm1 est manquant, le script se termine - sinon il fera un import-module.
Exemple```
.\ClientInspector.ps1 -verbose:$false -function:localpath
ClientInspector | Inventory of Operational & Security-related information
Developed by Morten Knudsen, Microsoft MVP - for free community use
Using AzLogDcrIngestPS module from local path D:\scripts\ClientInspectorV2
$DataVariable = ValidateFix-AzLogAnalyticsTableSchemaColumnNames -Data $DataVariable -Verbose:$Verbose
$DataVariable = Build-DataArrayToAlignWithSchema -Data $DataVariable -Verbose:$Verbose
Vous pouvez vérifier l'objet source en exécutant cette commande````
# Get insight about the schema structure of an object BEFORE changes. Command is only needed to verify columns in schema
Get-ObjectSchemaAsArray -Data $DataVariable -Verbose:$Verbose







Lancer PowerShell en tant qu'administrateur local
Lancer le script avec cette commande```js C:\ClientInspector\ClientInspector.ps1 -verbose:$true
4. ClientInspector fonctionnera pendant 10 à 20 minutes et créera les tables & règles de collecte de données nécessaires - en fonction de la structure réelle de votre environnement. Veuillez examiner les résultats à l'écran et rechercher les erreurs (en rouge)
5. Lorsque tout semble correct, relancez le script et il sera beaucoup plus rapide. Vérifiez que les données arrivent à l'aide de requêtes Kusto dans les différentes tables. REMARQUE : La première mise en ligne des données peut prendre environ 10 à 15 minutes, car le pipeline doit être créé en arrière-plan.
6. En dernier changement, nous devons modifier 2 paramètres dans les paramètres pour indiquer à ClientInspector de ne faire que des modifications de schéma lors de l'exécution à partir de la machine de référence.```js
$AzLogDcrTableCreateFromReferenceMachine = @("<<MyReferenceMachineComputerName>>") # sample @("ComputerName")
$AzLogDcrTableCreateFromAnyMachine = $false # important so changes can only happen on reference machine
ClientInspector télécharge la dernière version depuis mon dépôt Github et la stocke dans le chemin local à chaque exécution (environ 300 ko)
Exemple``` .\ClientInspector.ps1 -verbose:$false -function:download
ClientInspector | Inventory of Operational & Security-related information Developed by Morten Knudsen, Microsoft MVP - for free community use
Downloading latest version of module AzLogDcrIngestPS from https://github.com/KnudsenMorten/CientInspectorV2 into local path D:\scripts\ClientInspectorV2
## .\ClientInspector.ps1 -function:PsGallery -scope [AllUsers|CurrentUser]
Ce paramètre nécessite un autre paramètre : -scope [AllUsers | CurrentUser]
ClientInspector vérifiera si le module est installé dans la portée choisie.
S'il n'est pas installé, il téléchargera automatiquement la dernière version depuis Powershell Gallery et importera le module.
Si le client exécute la dernière version, il continuera.
Exemple```
.\ClientInspector.ps1 -verbose:$false -function:PSGallery -scope:CurrentUser
ClientInspector | Inventory of Operational & Security-related information
Developed by Morten Knudsen, Microsoft MVP - for free community use
Powershell module was not found !
Installing in scope currentuser .... Please Wait !
" - No, the message ends with "INPUT:" then the response. As an AI, I need to process whatever is after "INPUT:". If it's blank, I should output empty. But that would be odd. Perhaps the user intended to provide chunk content but it got cut off. I'll re-read the instructions: "Translate the following Kitploit tool content. This is chunk 25 of 47 from a longer Markdown document being translated in sequence. ... INPUT:" then nothing. Since I cannot see the actual chunk, I cannot translate. But the rules say "Return ONLY the translated text. No preamble, NO 'Here is the translation'...". If there's no input, maybe I should output nothing. However, I should consider that the input might be absent due to an error. To comply with the instruction, I'll output empty string, but I must not add any text. I'll just return an empty response.``` .\ClientInspector.ps1 -verbose:$false -function:PsGallery -scope:currentuser
ClientInspector | Inventory of Operational & Security-related information Developed by Morten Knudsen, Microsoft MVP - for free community use
Checking latest version at PsGallery for AzLogDcrIngestPS module OK - Running latest version
</details>
<br>
## Exemple de sortie de ClientInspector
[Vidéo 3m 19s - Exécution de ClientInspector en ligne de commande (mode normal)](https://youtu.be/4kA4BE0zJ9g)
<br>
# Sécurité
## Signature de code
Le fichier **ClientInspector.ps1** et le module **AzLogDcrIngestPS (AzLogDcrIngest.psm1)** sont signés avec mon certificat de signature de code (2LINKIT - ma société). Ainsi, vous pouvez l'exécuter si vous exigez que les scripts soient signés. Bien sûr, vous pouvez également choisir de le signer avec votre propre certificat de signature de code interne.

Veuillez [télécharger le certificat de clé publique](https://github.com/KnudsenMorten/ClientInspectorV2/raw/main/Trusted_Publisher_Certificate/2LINKIT-TrustedPublisher.cer) et placez-le dans votre conteneur 'Éditeur approuvé' pour approuver l'éditeur (2LINKIT - ma société). Vous pouvez le déployer à l'aide d'Intune ou d'une stratégie de groupe.



### Le déploiement via Intune ne nécessite pas que l'éditeur approuvé soit en place
Par défaut, Intune effectue un BYPASS lors de l'exécution de scripts de correction.
## Structure
La sécurité de **ClientInspector** est divisée en 4 couches : **data-in** (collecte des données), **data-upload** (envoi au backend) et **data-view** (tableaux de bord) - ainsi que **schema-management** (gestion du schéma).
| Phase | Implémentation de la sécurité | Délégations / Autorisations |
|:------|:------------------------------|:----------------------------|
|Data-in (collecte)|Cette phase est contrôlée par la méthode que vous choisissez pour effectuer la collecte réelle (Intune, ConfigMg ou autre tiers)|Le script doit s'exécuter en tant qu'administrateur local (contexte système) pour pouvoir collecter les données de base du matériel et de Windows|
|Data-upload|L'authentification pour l'API Logs Ingestion est effectuée au niveau du DCE, qui utilise l'authentification standard Azure Resource Manager.<br><br>Une stratégie courante consiste à utiliser un ID d'application et une clé d'application, qui est également la méthode utilisée dans ClientInspector.<br><br>L'ID d'application Azure et la clé secrète sont stockés dans l'en-tête de ClientInspector pour simplifier les choses.<br><br>Il est également possible d'utiliser Azure KeyVault pour stocker l'ID d'application et la clé secrète|[Détails couverts dans ClientInspectV2-DeploymentKit](https://github.com/KnudsenMorten/ClientInspectorV2-DeploymentKit#security-1)|
|Data-view|Autorisations Azure RCAC|Donnez accès à vos espaces de travail Azure Log Analytics, Azure Workbooks et Azure Dashboards|
|Schema-management|Méthode 1 : Azure RBAC (recommandé)<br><br>Méthode 2 : application Azure avec secret ou certificat|[Détails couverts dans ClientInSpectorV2-DeploymentKit](https://github.com/KnudsenMorten/ClientInspectorV2-DeploymentKit#azure-rbac-security-adjustment-separation-of-permissions-between-log-ingestion-and-tabledcr-management)|
<br>
# Structure de l'ensemble de données de ClientInspector
Chacun des ensembles de données (bios, applications, bitlocker, etc.) est construit avec la même structure en 4 phases :
## Phase 1/4 - Variables (nommage - où envoyer les données)```
#-------------------------------------------------------------------------------------------
# Variables
#-------------------------------------------------------------------------------------------
$TableName = 'InvClientComputerInfoSystemV2' # must not contain _CL
$DcrName = "dcr-" + $AzDcrPrefixClient + "-" + $TableName + "_CL"
#-------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------
Write-Output "" Write-Output "Collecting Computer system information ... Please Wait !"
$DataVariable = Get-CimInstance -ClassName Win32_ComputerSystem
## Phase 3/4 - Manipulation des Données (assurez-vous que les données sont au bon format et que tout "noice" est supprimé et que les informations pertinentes sont ajoutées)```
#-------------------------------------------------------------------------------------------
# Preparing data structure
#-------------------------------------------------------------------------------------------
# convert CIM array to PSCustomObject and remove CIM class information
$DataVariable = Convert-CimArrayToObjectFixStructure -data $DataVariable -Verbose:$Verbose
# add CollectionTime to existing array
$DataVariable = Add-CollectionTimeToAllEntriesInArray -Data $DataVariable -Verbose:$Verbose
# add Computer & UserLoggedOn info to existing array
$DataVariable = Add-ColumnDataToAllEntriesInArray -Data $DataVariable -Column1Name Computer -Column1Data $Env:ComputerName -Column2Name UserLoggedOn -Column2Data $UserLoggedOn
# Validating/fixing schema data structure of source data
$DataVariable = ValidateFix-AzLogAnalyticsTableSchemaColumnNames -Data $DataVariable -Verbose:$Verbose
# Aligning data structure with schema (requirement for DCR)
$DataVariable = Build-DataArrayToAlignWithSchema -Data $DataVariable -Verbose:$Verbose
#-------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------
CheckCreateUpdate-TableDcr-Structure -AzLogWorkspaceResourceId $LogAnalyticsWorkspaceResourceId -SchemaMode Merge -AzAppId $LogIngestAppId -AzAppSecret $LogIngestAppSecret -TenantId $TenantId -Verbose:$Verbose
-DceName $DceName -DcrName $DcrName -TableName $TableName -Data $DataVariable -LogIngestServicePricipleObjectId $AzDcrLogIngestServicePrincipalObjectId
-AzDcrSetLogIngestApiAppPermissionsDcrLevel $AzDcrSetLogIngestApiAppPermissionsDcrLevel -AzLogDcrTableCreateFromAnyMachine $AzLogDcrTableCreateFromAnyMachine
-AzLogDcrTableCreateFromReferenceMachine $AzLogDcrTableCreateFromReferenceMachine
#-----------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------
Post-AzLogAnalyticsLogIngestCustomLogDcrDce-Output -DceName $DceName -DcrName $DcrName -Data $DataVariable -TableName $TableName ` -AzAppId $LogIngestAppId -AzAppSecret $LogIngestAppSecret -TenantId $TenantId -Verbose:$Verbose
<br>
**ASTUCE : erreur 513 - l'entité est trop grande**
Par défaut, ClientInspector envoie les données par lots en fonction d'une taille moyenne calculée par enregistrement. Si votre jeu d'enregistrements a une taille différente, vous pouvez recevoir une erreur 513.
La cause est que vous atteignez la limite de 1 Mo pour chaque téléchargement (limitation d'Azure Pipeline). Microsoft souhaite recevoir de nombreux petits morceaux de données, car il s'agit d'un environnement partagé. J'ai rencontré ce problème lors de la récupération de la liste de toutes les applications installées. Apparemment, les applications stockent des informations de tailles très différentes.
Vous pouvez atténuer ce problème en ajoutant le paramètre **-BatchAmount <nombre d'enregistrements à envoyer par lot>** à la commande Post-command. Si vous voulez être sûr, définissez-le sur 1```
Post-AzLogAnalyticsLogIngestCustomLogDcrDce-Output -DceName $DceName `
-DcrName $DcrName `
-Data $DataVariable `
-TableName $TableName `
-AzAppId $LogIngestAppId `
-AzAppSecret $LogIngestAppSecret `
-TenantId $TenantId `
-BatchAmount 1 `
-Verbose:$Verbose `
#-----------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------
$Schema = Get-ObjectSchemaAsArray -Data $Data
$StructureCheck = Get-AzLogAnalyticsTableAzDataCollectionRuleStatus -AzLogWorkspaceResourceId $AzLogWorkspaceResourceId -TableName $TableName
-DcrName $DcrName -SchemaSourceObject $Schema
-SchemaMode $SchemaMode
-AzAppId $AzAppId -AzAppSecret $AzAppSecret
-TenantId $TenantId `
-Verbose:$Verbose
#-----------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------
$Schema = Get-ObjectSchemaAsHash -Data $Data -ReturnType Table
-Verbose:$Verbose
CreateUpdate-AzLogAnalyticsCustomLogTableDcr -AzLogWorkspaceResourceId $AzLogWorkspaceResourceId -SchemaSourceObject $Schema
-SchemaMode $SchemaMode
-TableName $TableName -AzAppId $AzAppId
-AzAppSecret $AzAppSecret -TenantId $TenantId
-Verbose:$Verbose
$Schema = Get-ObjectSchemaAsHash -Data $Data -ReturnType DCR
CreateUpdate-AzDataCollectionRuleLogIngestCustomLog -AzLogWorkspaceResourceId $AzLogWorkspaceResourceId -SchemaSourceObject $Schema
-SchemaMode $SchemaMode
-DceName $DceName -DcrName $DcrName
-TableName $TableName -LogIngestServicePricipleObjectId $LogIngestServicePricipleObjectId
-AzDcrSetLogIngestApiAppPermissionsDcrLevel $AzDcrSetLogIngestApiAppPermissionsDcrLevel -AzAppId $AzAppId
-AzAppSecret $AzAppSecret -TenantId $TenantId
-Verbose:$Verbose
$AzDcrDceDetails = Get-AzDcrDceDetails -DcrName $DcrName -DceName $DceName
-AzAppId $AzAppId -AzAppSecret $AzAppSecret
-TenantId $TenantId `
-Verbose:$Verbose
Post-AzLogAnalyticsLogIngestCustomLogDcrDce -DceUri $AzDcrDceDetails[2] -DcrImmutableId $AzDcrDceDetails[6]
-TableName $TableName -DcrStream $AzDcrDceDetails[7]
-Data $Data -BatchAmount $BatchAmount
-AzAppId $AzAppId -AzAppSecret $AzAppSecret
-TenantId $TenantId `
-Verbose:$Verbose
<br>
# Mode verbose & Plus d'aide
Si vous souhaitez obtenir des informations plus détaillées sur ce qui se passe, vous pouvez activer le mode verbose (-verbose:$true)```
.\ClientInspector.ps1 -verbose:$true -function:localpath
Si vous préférez tester en utilisant Powershell ISE, vous pouvez également activer le mode verbose en utilisant la variable $Verbose``` $Verbose = $false # can be $true or $false
Si vous voulez obtenir de l'aide sur la syntaxe et les exemples du module AzLogDcrLogIngestPS, vous pouvez écrire get-module```
PS get-command -module AzLogDcrIngestPS
CommandType Name Version Source
----------- ---- ------- ------
Function Add-CollectionTimeToAllEntriesInArray 1.1.17 AzLogDcrIngestPS
Function Add-ColumnDataToAllEntriesInArray 1.1.17 AzLogDcrIngestPS
Function Build-DataArrayToAlignWithSchema 1.1.17 AzLogDcrIngestPS
Function CheckCreateUpdate-TableDcr-Structure 1.1.17 AzLogDcrIngestPS
Function Convert-CimArrayToObjectFixStructure 1.1.17 AzLogDcrIngestPS
Function Convert-PSArrayToObjectFixStructure 1.1.17 AzLogDcrIngestPS
Function CreateUpdate-AzDataCollectionRuleLogIngestCusto... 1.1.17 AzLogDcrIngestPS
Function CreateUpdate-AzLogAnalyticsCustomLogTableDcr 1.1.17 AzLogDcrIngestPS
Function Delete-AzDataCollectionRules 1.1.17 AzLogDcrIngestPS
Function Delete-AzLogAnalyticsCustomLogTables 1.1.17 AzLogDcrIngestPS
Function Filter-ObjectExcludeProperty 1.1.17 AzLogDcrIngestPS
Function Get-AzAccessTokenManagement 1.1.17 AzLogDcrIngestPS
Function Get-AzDceListAll 1.1.17 AzLogDcrIngestPS
Function Get-AzDcrDceDetails 1.1.17 AzLogDcrIngestPS
Function Get-AzDataCollectionRuleTransformKql 1.1.17 AzLogDcrIngestPS
Function Get-AzDcrListAll 1.1.17 AzLogDcrIngestPS
Function Get-AzLogAnalyticsTableAzDataCollectionRuleStatus 1.1.17 AzLogDcrIngestPS
Function Get-ObjectSchemaAsArray 1.1.17 AzLogDcrIngestPS
Function Get-ObjectSchemaAsHash 1.1.17 AzLogDcrIngestPS
Function Post-AzLogAnalyticsLogIngestCustomLogDcrDce 1.1.17 AzLogDcrIngestPS
Function Post-AzLogAnalyticsLogIngestCustomLogDcrDce-Output 1.1.17 AzLogDcrIngestPS
Function Update-AzDataCollectionRuleDceEndpoint 1.1.17 AzLogDcrIngestPS
Function Update-AzDataCollectionRuleResetTransformKqlDef... 1.1.17 AzLogDcrIngestPS
Function Update-AzDataCollectionRuleTransformKql 1.1.17 AzLogDcrIngestPS
Function ValidateFix-AzLogAnalyticsTableSchemaColumnNames 1.1.17 AzLogDcrIngestPS
Obtenir de l'aide sur une cmdlet spécifique - get-help Add-CollectionTimeToAllEntriesInArray -full``` get-help Add-CollectionTimeToAllEntriesInArray -full
NAME Add-CollectionTimeToAllEntriesInArray
SYNOPSIS Add property CollectionTime (based on current time) to all entries on the object
SYNTAX Add-CollectionTimeToAllEntriesInArray [-Data] []
DESCRIPTION Gives capability to do proper searching in queries to find latest set of records with same collection time Time Generated cannot be used when you are sending data in batches, as TimeGenerated will change An example where this is important is a complete list of applications for a computer. We want all applications to show up when queriying for the latest data
PARAMETERS -Data Object to modify
Required? true
Position? 1
Default value
Accept pipeline input? false
Accept wildcard characters? false
<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (https:/go.microsoft.com/fwlink/?LinkID=113216).
INPUTS None. You cannot pipe objects
OUTPUTS Updated object with CollectionTime
-------------------------- EXAMPLE 1 --------------------------
PS C:\>#-------------------------------------------------------------------------------------------
# Variables
#-------------------------------------------------------------------------------------------
$Verbose = $true # $true or $false
#-------------------------------------------------------------------------------------------
# Collecting data (in)
#-------------------------------------------------------------------------------------------
$DNSName = (Get-CimInstance win32_computersystem).DNSHostName +"." + (Get-CimInstance win32_computersystem).Domain
$ComputerName = (Get-CimInstance win32_computersystem).DNSHostName
[datetime]$CollectionTime = ( Get-date ([datetime]::Now.ToUniversalTime()) -format "yyyy-MM-ddTHH:mm:ssK" )
$UserLoggedOnRaw = Get-Process -IncludeUserName -Name explorer | Select-Object UserName -Unique
$UserLoggedOn = $UserLoggedOnRaw.UserName
$DataVariable = Get-CimInstance -ClassName Win32_Processor | Select-Object -ExcludeProperty "CIM*"
#-------------------------------------------------------------------------------------------
# Preparing data structure
#-------------------------------------------------------------------------------------------
$DataVariable = Convert-CimArrayToObjectFixStructure -data $DataVariable -Verbose:$Verbose
$DataVariable
# add CollectionTime to existing array
$DataVariable = Add-CollectionTimeToAllEntriesInArray -Data $DataVariable -Verbose:$Verbose
$DataVariable
#-------------------------------------------------------------------------------------------
# Output
#-------------------------------------------------------------------------------------------
VERBOSE: Adding CollectionTime to all entries in array .... please wait !
Caption : Intel64 Family 6 Model 165 Stepping 5
Description : Intel64 Family 6 Model 165 Stepping 5
InstallDate :
Name : Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
Status : OK
Availability : 3
ConfigManagerErrorCode :
ConfigManagerUserConfig :
CreationClassName : Win32_Processor
DeviceID : CPU0
ErrorCleared :
ErrorDescription :
LastErrorCode :
PNPDeviceID :
PowerManagementCapabilities :
PowerManagementSupported : False
StatusInfo : 3
SystemCreationClassName : Win32_ComputerSystem
SystemName : STRV-MOK-DT-02
AddressWidth : 64
CurrentClockSpeed : 2904
DataWidth : 64
Family : 198
LoadPercentage : 1
MaxClockSpeed : 2904
OtherFamilyDescription :
Role : CPU
Stepping :
UniqueId :
UpgradeMethod : 1
Architecture : 9
AssetTag : To Be Filled By O.E.M.
Characteristics : 252
CpuStatus : 1
CurrentVoltage : 8
ExtClock : 100
L2CacheSize : 2048
L2CacheSpeed :
L3CacheSize : 16384
L3CacheSpeed : 0
Level : 6
Manufacturer : GenuineIntel
NumberOfCores : 8
NumberOfEnabledCore : 8
NumberOfLogicalProcessors : 16
PartNumber : To Be Filled By O.E.M.
ProcessorId : BFEBFBFF000A0655
ProcessorType : 3
Revision :
SecondLevelAddressTranslationExtensions : False
SerialNumber : To Be Filled By O.E.M.
SocketDesignation : U3E1
ThreadCount : 16
Version :
VirtualizationFirmwareEnabled : False
VMMonitorModeExtensions : False
VoltageCaps :
PSComputerName :
CollectionTime : 12-03-2023 16:08:33
RELATED LINKS https://github.com/KnudsenMorten/AzLogDcrIngestPS
<br>
# Coût - Combien coûte le stockage de ces données ?
Les données de **500** clients effectuant un inventaire **quotidien** avec ClientInspector vous coûteront environ **200 DKK par mois / 27 USD par mois**
<br>
# Bogues et signalements, veuillez m'en informer
Aujourd'hui, ClientInspectorV1 est utilisé sur des milliers d'ordinateurs (et ServerInspectorV1 sur des milliers de serveurs)
Étant donné que ClientInspectorV2 est une réécriture complète de V1 en cours de déploiement avec, par exemple, une nouvelle convention de nommage, je ne peux pas vous promettre qu'aucun bug ne sera trouvé.
Mais **je peux vous promettre** que je les corrigerai aussi vite que mon temps libre me le permettra. Veuillez m'envoyer un email à [email protected] avec vos constatations.
Pensez à forker le site Github - ou surveillez les mises à jour dans les tableaux de bord / classeurs (workbooks) ou le script ClientInspector.
De plus, ClientInspector est conçu pour couvrir différentes conceptions et plates-formes, mais vous pouvez avoir des configurations uniques qui ne sont pas couvertes par les collections ou les tableaux de bord.
Mais l'approche ouverte vous permet de modifier à la fois les tableaux de bord, les classeurs et le script ClientInspector, pour qu'il fonctionne à 100% pour vous. Considérez-le comme une démonstration pour faire plus avec les technologies de journalisation Azure - ce n'est pas un produit payant avec un support 24h/24 et 7j/7. Il est gratuit pour tout le monde !
<br>
# Contact
Si vous avez des commentaires sur la solution - ou si vous voulez simplement entrer en contact avec moi, veuillez me contacter via ces canaux - j'adorerais échanger :
[Github](https://github.com/KnudsenMorten)
[Twitter](https://twitter.com/knudsenmortendk)
[Blog](https://mortenknudsen.net/)
[LinkedIn](https://www.linkedin.com/in/mortenwaltorpknudsen/)
[Microsoft MVP profile](https://mvp.microsoft.com/en-us/PublicProfile/5005156?fullName=Morten%20Knudsen)
[Sessionize](https://sessionize.com/mortenknudsen/)
[Mail](mailto:[email protected])
<br>
# Un grand merci aux personnes formidables des équipes produit Microsoft - vous êtes des rock stars :smile:
Enfin, je souhaite remercier chaleureusement quelques personnes avec qui j'ai travaillé sur la construction du module PowerShell AzLogDcrIngestPS et dans mon travail quotidien avec les capacités de journalisation et de visualisation Azure :
|Name|Role|
|:---|:---|
|Ivan Varnitski|Chef de programme - Azure Pipeline|
|Evgeny Ternovsky|Chef de programme - Azure Pipeline|
|Nick Kiest|Chef de programme - Azure Data Collection Rules|
|Oren Salzberg|Chef de programme - Azure LogAnalytics|
|Guy Wild|Rédacteur technique - Azure LogAnalytics|
|John Gardner|Chef de programme - Azure Workbooks|
|Shikha Jain|Chef de programme - Azure Workbooks|
|Shayoni Seth|Chef de programme - Azure Monitor Agent|
|Jeff Wolford|Chef de programme - Azure Monitor Agent|
|Xema Pathak|Chef de programme - Azure VMInsight (intégration à Azure Monitor Agent)|
