
Strumento di inventario client e rilevamento delle derive basato su Azure che raccoglie dati di configurazione di Windows (antivirus, patching, Bitlocker) in LogAnalytics per dashboard basate su KQL e alerting di Sentinel.

Hai il controllo? - o alcuni dei tuoi processi di infrastruttura core come patching, antivirus, abilitazione di BitLocker stanno deviando? O vorresti fare un inventario avanzato, dove puoi cercare lo stato della garanzia contro la garanzia Lenovo o Dell, allora continua a leggere.
Scopri ClientInspector, che può aiutarti ad avere grandi intuizioni sul tuo ambiente client completo.
ClientInspector è gratuito per la comunità - costruito per essere una bella dimostrazione di come puoi riportare dati dai tuoi client utilizzando Azure Log Ingestion Pipeline, Azure Data Collection Rules, Azure LogAnalytics; visualizzarli con Azure Monitor & Azure Dashboards - e ricevere "avvisi di deriva" usando Microsoft Sentinel.
ClientInspector (v2) carica i dati raccolti in log personalizzati in Azure LogAnalytics workspace - usando Log ingestion API, Azure Data Collection Rules (DCR) e Azure Data Collection Endpoints (DCE).




È importante dichiarare che non sto cercando di costruire uno strumento di gestione separato, che possa competere con lo stack di sicurezza e gestione Microsoft.
Niente batte lo stack di gestione e sicurezza Microsoft Azure/M365. Sono soluzioni stellari.
Ma sono davvero appassionato delle capacità di logging e del potere di riportare dati da client, server, cloud e sistemi di terze parti - e ottenere informazioni preziose dai dati.
Ho una soluzione simile per server - ServerInspector. Purtroppo, non è pubblica.
Buona caccia 😄
Quali dati vengono raccolti?
Dashboard dello stato desiderato - Come ottenere visibilità del mio ambiente dai dati?
Come eseguire query sui dati? - Kusto (KQL) è la risposta
Architettura, Schema & Rete
Implementazione
Dipendenze
Esecuzione di ClientInspector.ps1 - 3 modalità
Output di esempio di ClientInspector
Sicurezza
Layout del set di dati di ClientInspector
Modalità verbose & Ulteriore aiuto
Costo - Quanto costa archiviare questi dati?
Bug trovati, per favore informami
Contatti
Video 3m 19s - Esecuzione di ClientInspector tramite riga di comando (modalità normale)
Video 1m 40s - Creazione automatica di 2 tabelle e DCR (modalità verbose)
Video 1m 37s - Creazione automatica di 2 tabelle e DCR (modalità normale)
Video 1m 34s - Visualizzazione dello schema di DCR e tabella)
Video 2m 19s - Manipolazione dei dati
Video 1m 58s - Query Kusto sui dati
Video 3m 01s - Dashboard
Video 0m 48s - Esempio di utilizzo dei dati - ricerca nel database delle garanzie Lenovo
Video 7m 25s - Distribuzione tramite ClientInspector DeploymentKit
ClientInspector può essere utilizzato per raccogliere molte informazioni preziose dai tuoi client Windows - e inviare i dati a Azure LogAnalytics Custom Tables.
Lo script raccoglie le seguenti informazioni (impostazioni, informazioni, configurazione, stato):
Sentiti libero di aggiungere altre raccolte di dati interessanti per adattarle alle tue esigenze. Se vuoi partecipare alla comunità, per favore inviami un'email con le tue raccolte, se pensi che possano essere utili per l'intera comunità.
Puoi utilizzare qualsiasi dato di origine che può essere recuperato in PowerShell (wmi, cim, dati esterni, API REST, formato XML, formato JSON, formato CSV, ecc.)
È molto importante capire che i dati in genere devono essere manipolati prima di inviarli - per assicurarsi che siano validi e che eventuali dati irrilevanti siano stati rimossi.
ClientInspector utilizza tutte le 24 funzioni del modulo PowerShell AzLogDcIngestPS, per gestire la manipolazione dei dati di origine, rimuovere il "rumore" nei dati, rinominare colonne proibite in tabelle/DCR - e supportare le esigenze di trasparenza con informazioni aggiuntive come 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
Per maggiori dettagli sulle funzioni disponibili in AzLogDcrIngestPS - e su come usarle qui
Come parte del deploy iniziale usando ClientInSpectorV2-DeploymentKit, avrai accesso a molti dashboard di Azure e workbook di Azure.
L'idea dei dashboard è che mostreranno dove la tua infrastruttura si sta allontanando dallo 'stato desiderato'. Pensali come KPI, dove l'infrastruttura non è sotto controllo.
Invece di avere un'attività di patch e gestione dell'antivirus, puoi considerare di avere KPI che mostreranno dove i computer non sono patchati - o dove la protezione in tempo reale nell'antivirus non è in esecuzione - o macchine che hanno avuto un bluescreen nelle ultime 24 ore.
Questo è lo stesso concetto di Microsoft Secure Score.















Link per vedere la lista completa dei workbook di Azure forniti
Tutti i dashboard di Azure di esempio sono creati basandosi su parti fissate (pinned) dai workbook di Azure, quindi se vuoi approfondire, puoi cliccare su un link e avrai accesso alle informazioni dettagliate.

Link per vedere i dashboard di Azure forniti
Se vuoi aggiungere altri dashboard o workbook, di solito inizi investigando i dati raccolti nelle tabelle dei log personalizzati usando query KQL. Quando hai trovato la query desiderata, puoi creare nuove viste nei workbook - e fissare le tue preferite ai dashboard.
Se non conosci il linguaggio Kusto, ti consiglio di iniziare a sperimentare con esso, poiché è un linguaggio molto potente.
Video 1m 58s - Query Kusto sui dati
Video 3m 01s - Dashboard
Scrivi la tua prima query con Kusto Query Language
Analizza i risultati delle query usando KQL
Di seguito ci sono 4 esempi di query per iniziare - basati sui dati di ClientInspector.
Se vuoi fare caccia avanzata, puoi usare query Kusto (KQL) tradizionali nelle tabelle
#----------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------
$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>
## Esempio di query 4: Integrazione dei dati con altre fonti (verifica garanzia sul database garanzie Lenovo)
Quando abbiamo i dati in Azure LogAnalytics, possiamo iniziare a integrare i dati con altre fonti, come i dati di garanzia Dell o Lenovo tramite ricerca API REST.
[Video 0m 48s - Esempio di utilizzo dei dati - ricerca nel database garanzie Lenovo](https://youtu.be/3ZDyTwiLU0w)
Ecco un esempio di output, creato automaticamente da uno script PowerShell - che estrae un elenco di computer e numeri di serie - e poi effettua una ricerca nel database garanzie Lenovo per recuperare informazioni su quando il computer è stato acquistato e il suo stato di garanzia.
[Esempio di output di garanzia (Excel), basato sui dati raccolti da ClientInspector](https://github.com/KnudsenMorten/ClientInspectorV2/raw/main/img/WarrantyInfo.xlsx)
<br>
# Architettura, Schema e Rete
ClientInspector (v2) carica i dati raccolti in **log personalizzati** in **Azure LogAnalytics workspace** - utilizzando **Log ingestion API**, **Azure Data Collection Rules (DCR)** e **Azure Data Collection Endpoints (DCE)**.

## Schema
Sia il DCR che la tabella LogAnalytics hanno uno schema, che deve corrispondere allo schema dell'oggetto sorgente. Questo viene gestito utilizzando le funzioni nel modulo AzLogDcrIngestPS.
[Video 1m 40s - Creazione automatica di 2 tabelle e DCR (modalità verbose)](https://youtu.be/rIUNs3yT-eI)
[Video 1m 37s - Creazione automatica di 2 tabelle e DCR (modalità normale)](https://youtu.be/khQMDcON6r8)
[Video 1m 34s - Visualizza schema di DCR e tabella)](https://youtu.be/NDSNhvpa4Gs)
AzLogDcrIngestPS supporta 2 modalità per la gestione dello schema: **Merge** e **Overwrite**
### SchemaMode = Merge (predefinito)
Se si imposta SchemaMode = Merge, le nuove proprietà dall'oggetto sorgente verranno aggiunte (unite) allo schema corrente della log analytics. DCR importerà lo schema dalla tabella log analytics per garantire che siano identici.
La modalità predefinita è Merge, se non si definisce la variabile SchemaMode sulle funzioni:
CheckCreateUpdate-TableDr-Structure
CreateUpdate-AzLogAnalyticsCustomLogTableDcr
CreateUpdate-AzDataCollectionRuleLogIngestCustomLog
### SchemaMode = Overwrite
Se si imposta SchemaMode = Overwrite, lo schema in DCR e tabella verrà sovrascritto (aggiornato) - basato sullo schema dell'oggetto sorgente.
## Rete
Hai 3 opzioni per la connettività ad Azure per il caricamento dei dati:
|Metodo di upload|Dettagli connettività|Conformità OS|
|:------------|:-------------------|:------------|
|Accesso pubblico|L'endpoint REST invia al DCE tramite IP pubblico del DCE|L'endpoint supporta TLS 1.2|
|Accesso privato|L'endpoint REST invia al DCE tramite collegamento privato del DCE|L'endpoint supporta TLS 1.2|
|Log-hub|L'endpoint REST invia i dati tramite [log-hub](https://github.com/KnudsenMorten/AzLogDcrIngestPSLogHub) - un concetto che ho costruito.|L'endpoint non supporta TLS 1.2.<br> Azure non accetterà la connettività direttamente da questi dispositivi|
### Endpoint connessi a Internet - conformità a livello di OS

È necessario consentire i seguenti endpoint nel firewall:
|Endpoint|Scopo|Porta|Direzione|Ignora ispezione HTTPS|
|:-------|:------|:----|:-------|:----------------------|
|global.handler.control.monitor.azure.com|Servizio di controllo accessi|Porta 443|In uscita|Sì|
|dce logs ingestion uri<br><br>sample<br>https://dce-log-platform-management-client-demo-p-iur0.westeurope-1.ingest.monitor.azure.com|Carica dati di log|Porta 443|In uscita|Sì|
<br>
### Nessun accesso a Internet o incompatibilità a livello di OS, ad es. esecuzione di TLS 1.0/1.1
[Scopri il concetto di log-hub utilizzando questo link](https://github.com/KnudsenMorten/AzLogDcrIngestPSLogHub)

<br>
# Implementazione
Spero che tu possa sperimentare che è piuttosto facile mettere tutto in funzione. I 3 passaggi sono delineati di seguito.
Prima di iniziare, ti invito a leggere più in dettaglio i componenti nell'introduzione qui sotto.
<details>
<summary>Introduzione dei componenti Azure utilizzati come parte di ClientInspector</summary>
<br>
I seguenti componenti sono necessari:
| Risorsa Azure | Scopo | Maggiori informazioni |
| :------------- | :----- | :----- |
| Qualsiasi endpoint REST | Questa è la fonte che invia dati | |
| Log Ingestion API | Questa è la nuova API che sostituisce la vecchia HTTP Data Collector API | https://learn.microsoft.com/en-us/azure/azure-monitor/logs/logs-ingestion-api-overview |
| Data Collection Endpoint (DCE)| Questo è il punto di ingresso della comunicazione dall'endpoint. I dati vengono inviati a un **Azure Data Collection Endpoint Ingestion Uri**. Un singolo DCE può supportare più DCR, quindi puoi specificare un DCR diverso per diverse fonti e tabelle di destinazione. | https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/data-collection-endpoint-overview?tabs=portal |
| Data Collection Rules (DCR) | Le regole di raccolta dati definiscono i dati raccolti (schema) e specificano come e dove tali dati devono essere inviati o archiviati. Il DCR deve comprendere la struttura dei dati di input e la struttura della tabella di destinazione. Se i due non corrispondono, può utilizzare una trasformazione per convertire i dati di origine per corrispondere alla tabella di destinazione. Puoi anche utilizzare la trasformazione per filtrare i dati di origine ed eseguire qualsiasi altro calcolo o conversione. | https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/data-collection-rule-overview |
| Azure LogAnaltyics Workspace | I dati vengono inviati a log personalizzati in Azure LogAnalytics | https://learn.microsoft.com/en-us/azure/azure-monitor/logs/log-analytics-overview |
| Azure Workbooks | Come parte della distribuzione, verranno distribuiti workbook di esempio | https://learn.microsoft.com/en-us/azure/azure-monitor/visualize/workbooks-overview |
| Azure Dashboards | Come parte della distribuzione, verranno distribuiti dashboard di esempio | https://learn.microsoft.com/en-us/azure/azure-monitor/visualize/tutorial-logs-dashboards |
| Kusto (KQL) | I dati possono essere analizzati utilizzando query Kusto (KQL) | https://learn.microsoft.com/en-us/azure/azure-monitor/logs/get-started-queries |
</details>
I passaggi per configurare ClientInspector nel tuo ambiente sono:
1. [Configura l'ambiente utilizzando ClientInSpectorV2-DeploymentKit](https://github.com/KnudsenMorten/ClientInspectorV2-DeploymentKit)
2. Esegui ClientInspector la prima volta (configurazione iniziale) - vedi più sotto
<details>
<summary>Come configurare la configurazione iniziale delle tabelle Azure LogAnalytics e delle regole di raccolta dati (prima volta)</summary>
<br>
<br>
Configurazione:
1. Quando esegui il DeploymentKit, preparerà automaticamente il file ClientInspector per te, quindi devi solo inserire le variabili```js
$TenantId = "xxxx"
$LogIngestAppId = "xxxx"
$LogIngestAppSecret = "xxxx"
$DceName = "xxxx"
$LogAnalyticsWorkspaceResourceId = "xxxx"
$AzDcrPrefixClient = "xxx"
$AzDcrSetLogIngestApiAppPermissionsDcrLevel = $false
$AzDcrLogIngestServicePrincipalObjectId = "xxx"
$AzDcrDceTableCreateFromReferenceMachine = @()
$AzDcrDceTableCreateFromAnyMachine = $true
Scarica lo script di rilevamento ClientInspector_Detection.ps1 (fai clic con il tasto destro e scegli 'Salva collegamento come')
Apri il file con il tuo editor preferito. Regola la frequenza con cui desideri eseguire l'inventario.```js ##################################
##################################
$RunEveryHours = 8
$LastRun_RegPath = "HKLM:\SOFTWARE\ClientInspector"
$LastRun_RegKey = "ClientInSpector_System"
3. Ora dobbiamo creare il job di remediation. Vai nel portale Microsoft Intune -> Reports -> Endpoint Analysis --> Proactive remediations - e crea un pacchetto di script come mostrato qui sotto
NOTA: Per lo script di remediation, usa il file **ClientInspector.ps1**


### Limitazione di Intune
NOTA: Intune ha una limitazione di 200 Kb per la dimensione di uno script di remediation.**

Nel caso in cui si raggiunga questo limite, propongo di dividere lo script in 2 script.


Ricordati di includere la sezione header inclusa la sezione UserLoggedOn come header del secondo file. UserLoggedOn viene utilizzato per mostrare quale utente è connesso.
Ho preparato un [sample script-setup](https://github.com/KnudsenMorten/ClientInspectorV2/tree/main/Sample%20intune%20setup%20if%20file%20size%20is%20more%20than%20200%20Kb), dove puoi vedere come separarli. Nota: il codice NON è aggiornato in questi script, quindi assicurati di prendere le sezioni dal file master ClientInspector.
In pratica la struttura è:
Il file 1 contiene header + UserLoggedOn (sezione 1) + sezioni 2-9 + scrive un flag di controllo in HKLM\Software\ClientInspector\ClientInspector_System_1
Il file 2 contiene header + UserLoggedOn (sezione 1) + sezioni 10-18 + scrive un flag di controllo in HKLM\Software\ClientInspector\ClientInspector_System_2



</details>
<details>
<summary>Come distribuire usando ConfigMgr (o qualsiasi altro strumento che esegue un file CMD) ?</summary>
<br>
Eseguirai lo script di inventario tramite un pacchetto tradizionale + distribuzione
1. [Scarica il file CMD ClientInspector.cmd](https://github.com/KnudsenMorten/ClientInspectorV2/raw/main/ConfigMgr/ClientInspector.cmd) (clic con il destro e scegli 'Salva link con nome')
2. Crea una struttura sorgente nella directory dei sorgenti del pacchetto ConfigMgr, ad esempio chiamata ClientInspector.
3. Copia i 2 file necessari **ClientInspector.cmd** e **ClientInspector.ps1** nella directory
4. Crea un pacchetto - e punta il pacchetto ad eseguire **ClientInspector.cmd**
5. Esegui una distribuzione
</details>
<br>
# Dipendenze
## Modulo Powershell AzLogDcringestPS - creato da me (Morten Knudsen)
ClientInspector richiede il modulo Powershell **AzLogDcrIngestPS**
Le funzionalità principali del modulo Powershell **AzLogDcrIngestPS** includono:
* creare/aggiornare automaticamente DCR e tabelle in base allo schema dell'oggetto sorgente
* validare lo schema per problemi di convenzione di denominazione. Se vengono trovati problemi, li mitiga
* aggiornare lo schema di DCR e tabelle, se la struttura dell'oggetto sorgente cambia
* auto-riparazione in caso di problemi con un DCR o una tabella
* può rimuovere dati dall'oggetto sorgente, se ci sono colonne di dati che non si vogliono inviare
* può convertire oggetti sorgente basati su oggetti CIM o PS in PSCustomObjects/array
* può aggiungere informazioni rilevanti a ciascun record come UserLoggedOn, Computer, CollectionTime
Puoi trovare informazioni più dettagliate sul modulo usando i link qui sotto:
[AzLogDcrIngestPS (Github)](https://github.com/KnudsenMorten/AzLogDcrIngestPS)
[AzLogDcrIngestPS (Powershell Gallery)](https://www.powershellgallery.com/packages/AzLogDcrIngestPS)
[AzLogDcrIngestPSLogHub (Github)](https://github.com/KnudsenMorten/AzLogDcrIngestPSLogHub)
<br>
## Moduli Powershell di terze parti
Preferisco recuperare le informazioni su Windows Update utilizzando un noto modulo Powershell, PSWindowsUpdate.
|ModuleName|Purpose|More info|Credit|
|:---------|:------|:--------|:-----|
|NuGet|Provider di pacchetti comune utilizzato per distribuire molti moduli Powershell, inclusi AzLogDcrIngestPS<br><br>Il Provider di pacchetti verrà installato automaticamente sul computer quando lo script viene eseguito|[Link](https://www.nuget.org/packages)|
|PSWindowsUpdate|Raccolta di informazioni su Windows Update (aggiornamenti in sospeso, aggiornamenti installati, ecc.)<br><br>Il modulo verrà installato automaticamente sul computer quando lo script viene eseguito|[Link](https://www.powershellgallery.com/packages/PSWindowsUpdate)|Michal Gajda
<br>
# Esecuzione di ClientInspector.ps1 - 3 modalità
ClientInspector supporta 3 modi per installare/aggiornare/importare il modulo Powershell necessario: **Download**, **PsGallery**, **LocalPath**
Per impostazione predefinita, scaricherà l'ultima versione da PsGallery nell'ambito CurrentUser.
[Video 3m 19s - Running ClientInspector using commandline (normal mode)](https://youtu.be/4kA4BE0zJ9g)
## .\ClientInspector.ps1 -function:LocalPath
ClientInspector cercherà il file **AzLogDcrIngest.psm1** nella directory da cui verrà eseguito lo script.
Se AzLogDcrIngest.psm1 è mancante, lo script terminerà - altrimenti eseguirà un import-module.
Esempio```
.\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
Puoi verificare l'oggetto sorgente eseguendo questo comando````
# 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







Avvia PowerShell come amministratore locale
Avvia lo script usando questo comando```js C:\ClientInspector\ClientInspector.ps1 -verbose:$true
4. ClientInspector verrà eseguito per 10-20 minuti e creerà le tabelle necessarie e le Regole di Raccolta Dati - basate sulla struttura effettiva del tuo ambiente. Esamina i risultati sullo schermo e cerca eventuali errori (in rosso)
5. Quando tutto sembra a posto, esegui di nuovo lo script e procederà molto più velocemente. Verifica che i dati stiano arrivando utilizzando query Kusto nelle diverse tabelle. NOTA: possono essere necessari circa 10-15 minuti per il primo caricamento dei dati, poiché la pipeline deve essere creata nel backend
6. Come ultima modifica, dobbiamo cambiare 2 parametri nei parametri per dire a ClientInspector di effettuare solo modifiche allo schema quando viene eseguito dalla macchina di riferimento.```js
$AzLogDcrTableCreateFromReferenceMachine = @("<<MyReferenceMachineComputerName>>") # sample @("ComputerName")
$AzLogDcrTableCreateFromAnyMachine = $false # important so changes can only happen on reference machine
ClientInspector scaricherà l'ultima versione dal mio repository Github e la salverà nel percorso locale ogni volta che viene eseguito (circa 300 kb)
Esempio``` .\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]
Questo parametro richiede un altro parametro: -scope [AllUsers | CurrentUser]
ClientInspector verificherà se il modulo è installato nell'ambito scelto.
Se non è installato, scaricherà automaticamente l'ultima versione da PowerShell Gallery e importerà il modulo.
Se il client sta eseguendo l'ultima versione, procederà.
Esempio```
.\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 !
.``` .\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>
## Esempio di output di ClientInspector
[Video 3m 19s - Esecuzione di ClientInspector tramite riga di comando (modalità normale)](https://youtu.be/4kA4BE0zJ9g)
<br>
# Sicurezza
## Firma del codice
Sia il file **ClientInspector.ps1** che il **modulo AzLogDcrIngestPS (AzLogDcrIngest.psm1)** sono firmati con il mio certificato di firma del codice (2LINKIT - la mia azienda). In questo modo puoi eseguirli se richiedi che gli script siano firmati. Ovviamente puoi anche scegliere di firmarli con il tuo certificato di firma del codice interno.

Scarica il [certificato della chiave pubblica](https://github.com/KnudsenMorten/ClientInspectorV2/raw/main/Trusted_Publisher_Certificate/2LINKIT-TrustedPublisher.cer) e inseriscilo nel contenitore 'editore attendibile' per fidarti dell'editore (2LINKIT - la mia azienda). Puoi distribuire questo utilizzando Intune o Criteri di gruppo.



### La distribuzione tramite Intune non richiede l'editore attendibile
Per impostazione predefinita, Intune esegue un BYPASS quando esegue script di correzione.
## Struttura
La sicurezza di **ClientInspector** è suddivisa in 4 livelli: **data-in**, **data-upload** (invio al backend) e **data-view** (dashboard) - e **schema-management**
| Fase | Implementazione della sicurezza | Deleghe / Autorizzazioni |
|:-----|:-------------------------------|:-------------------------|
|Data-in (raccolta)|Questa fase è controllata dal metodo scelto per effettuare la raccolta effettiva (Intune, ConfigMg o altro software di terze parti)|Lo script deve essere eseguito come amministratore locale (contesto di sistema) per poter raccogliere i dati principali dall'hardware e da Windows|
|Data-upload|L'autenticazione per l'API di inserimento log viene eseguita al DCE, che utilizza l'autenticazione standard di Azure Resource Manager.<br><br>Una strategia comune è utilizzare un ID applicazione e una chiave applicazione, che è anche il metodo utilizzato in ClientInspector.<br><br>Azure AppId e Secret sono memorizzati nell'intestazione di ClientInspector per semplicità.<br><br>È anche possibile utilizzare Azure Keyvault per archiviare AppId e Secret|[Dettagli trattati in ClientInspectV2-DeploymentKit](https://github.com/KnudsenMorten/ClientInspectorV2-DeploymentKit#security-1)|
|Data-view|Autorizzazioni RCAC di Azure|Concedere l'accesso ad Azure LogAnalytics, Azure Workbooks e Azure Dashboards|
|Schema-management|Metodo 1: Azure RBAC (consigliato)<br><br>Metodo 2: Applicazione Azure con segreto o certificato|[Dettagli trattati in ClientInSpectorV2-DeploymentKit](https://github.com/KnudsenMorten/ClientInspectorV2-DeploymentKit#azure-rbac-security-adjustment-separation-of-permissions-between-log-ingestion-and-tabledcr-management)|
<br>
# Layout del set di dati di ClientInspector
Ciascuno dei set di dati (bios, applications, bitlocker, ecc.) è costruito con la stessa struttura in 4 fasi:
## Fase 1/4 - Variabili (denominazione - dove inviare i dati)```
#-------------------------------------------------------------------------------------------
# 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
## Fase 3/4 - Manipolazione dei Dati (assicurati che i dati siano nel formato corretto e che qualsiasi "rumore" venga rimosso e vengano aggiunte informazioni rilevanti)```
#-------------------------------------------------------------------------------------------
# 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>
**SUGGERIMENTO: errore 513 - entità troppo grande**
Per impostazione predefinita, ClientInspector invia i dati in lotti basati su una dimensione media calcolata per record. Nel caso in cui il tuo recordset abbia dimensioni diverse, potresti ricevere un errore 513.
La causa è che stai raggiungendo il limite di 1 MB per ogni upload (limite di Azure Pipeline). Microsoft desidera ricevere molti blocchi di dati più piccoli, poiché si tratta di un ambiente condiviso. Ho riscontrato questo problema durante il recupero dell'elenco di tutte le applicazioni installate. Apparentemente le applicazioni memorizzano informazioni di dimensioni molto diverse.
Puoi mitigare questo problema aggiungendo il parametro **-BatchAmount <numero di record da inviare per lotto>** al comando Post. Se vuoi essere sicuro, impostalo su 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>
# Verbose-mode & Ulteriore aiuto
Se vuoi ottenere informazioni più dettagliate su ciò che sta accadendo, puoi abilitare la modalità verbose (-verbose:$true)```
.\ClientInspector.ps1 -verbose:$true -function:localpath
Se preferisci testare usando Powershell ISE, puoi anche abilitare la modalità verbose utilizzando la variabile $Verbose``` $Verbose = $false # can be $true or $false
Se desideri ottenere aiuto con la sintassi e gli esempi del modulo AzLogDcrLogIngestPS, puoi scrivere 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
Ottieni aiuto con un cmdlet specifico - 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>
# Costo - Quanto costa archiviare questi dati?
I dati di **500** clienti che eseguono l'inventario ClientInspector **giornaliero** ti costeranno circa **DKK 200 al mese / USD 27 al mese**
<br>
# Bug/scoperte, per favore informami
Oggi ClientInspectorV1 è utilizzato su migliaia di computer (e ServerInspectorV1 su migliaia di server)
Poiché ClientInspectorV2 è una completa riscrittura rispetto a V1, ora in fase di distribuzione con ad esempio una nuova convenzione di denominazione, non posso prometterti che non verranno trovati bug.
Ma **posso prometterti** che li risolverò il più velocemente possibile nel mio tempo libero. Per favore, inviami un'email a [email protected] con le tue scoperte.
Considera di fare un fork del sito Github - o tieni d'occhio gli aggiornamenti nei dashboard/workbook o nello script ClientInspector.
Inoltre, ClientInspector è progettato per coprire diversi design e piattaforme, ma potresti avere configurazioni uniche non coperte dalle raccolte o dai dashboard.
Tuttavia, l'approccio aperto ti permette di modificare sia i dashboard, i workbook che lo script ClientInspector, in modo che funzioni al 100% per te. Consideralo un esempio per fare di più con le tecnologie di logging di Azure - non è un prodotto a pagamento con supporto 24x7. È gratuito per tutti!
<br>
# Contatti
Se hai commenti sulla soluzione - o semplicemente vuoi connetterti con me, per favore contattami attraverso questi canali - mi farebbe piacere entrare in contatto:
[Github](https://github.com/KnudsenMorten)
[Twitter](https://twitter.com/knudsenmortendk)
[Blog](https://mortenknudsen.net/)
[LinkedIn](https://www.linkedin.com/in/mortenwaltorpknudsen/)
[Profilo Microsoft MVP](https://mvp.microsoft.com/en-us/PublicProfile/5005156?fullName=Morten%20Knudsen)
[Sessionize](https://sessionize.com/mortenknudsen/)
[Email](mailto:[email protected])
<br>
# Un grande grazie alle fantastiche persone dei team di prodotto Microsoft - siete delle rock star :smile:
Infine, vorrei ringraziare sentitamente alcune persone con cui ho collaborato per creare il modulo Powershell AzLogDcrIngestPS e nel mio lavoro quotidiano con le capacità di logging e visualizzazione di Azure:
|Nome|Ruolo|
|:---|:---|
|Ivan Varnitski|Program Manager - Azure Pipeline|
|Evgeny Ternovsky|Program Manager - Azure Pipeline|
|Nick Kiest|Program Manager - Azure Data Collection Rules|
|Oren Salzberg|Program Manager - Azure LogAnalytics|
|Guy Wild|Technical Writer - Azure LogAnalytics|
|John Gardner|Program Manager - Azure Workbooks|
|Shikha Jain|Program Manager - Azure Workbooks|
|Shayoni Seth|Program Manager - Azure Monitor Agent|
|Jeff Wolford|Program Manager - Azure Monitor Agent|
|Xema Pathak|Program Manager - Azure VMInsight (integrazione in Azure Monitor Agent)|
