
Инструмент инвентаризации клиентов и обнаружения отклонений на базе Azure, который собирает данные конфигурации Windows (антивирус, установка обновлений, BitLocker) в LogAnalytics для создания панелей мониторинга на основе KQL и оповещений Sentinel.

Вы контролируете ситуацию? — или некоторые из ваших основных процессов инфраструктуры, такие как патчинг, антивирус, включение BitLocker, отклоняются? Или вы хотите проводить расширенную инвентаризацию, где можете проверить гарантийный статус по гарантии Lenovo или Dell? Тогда читайте дальше.
Ознакомьтесь с ClientInspector, который поможет вам получить отличное представление о вашей полной клиентской среде.
ClientInspector бесплатен для сообщества — создан как крутая демонстрация того, как можно получать данные от клиентов, используя Azure Log Ingestion Pipeline, Azure Data Collection Rules, Azure LogAnalytics; просматривать их с помощью Azure Monitor и Azure Dashboards — и получать «оповещения об отклонениях» с помощью Microsoft Sentinel.
ClientInspector (v2) загружает собранные данные в пользовательские журналы в рабочей области Azure LogAnalytics — используя Log Ingestion API, Azure Data Collection Rules (DCR) и Azure Data Collection Endpoints (DCE).




Для меня важно заявить, что я не пытаюсь создать отдельный инструмент управления, который будет конкурировать с набором средств безопасности и управления Microsoft.
Ничто не превзойдет стек управления и безопасности Microsoft Azure/M365. Это решения уровня рок-звёзд.
Но я действительно увлечен возможностями журналирования и силой возвращать данные от клиентов, серверов, облачных и сторонних систем — и получать крутую ценную информацию из этих данных.
У меня есть аналогичное решение для серверов — ServerInspector. К сожалению, оно не является общедоступным.
Большое спасибо замечательным людям из продуктовых команд Microsoft — вы рок-звезды 😄
Удачной охоты 😄
Какие данные собираются?
Панели мониторинга желаемого состояния — как получить представление о моей среде из данных?
Как запрашивать данные? — Kusto (KQL) — это ответ
Архитектура, схема и сеть
Реализация
Зависимости
Запуск ClientInspector.ps1 — 3 режима
Пример вывода ClientInspector
Безопасность
Структура набора данных ClientInspector
Подробный режим и дополнительная справка
Стоимость — сколько стоит хранение этих данных?
Обнаружение ошибок, сообщите мне
Контакты
Видео 3м 19с - Запуск ClientInspector с помощью командной строки (обычный режим)
Видео 1м 40с - Автоматическое создание 2 таблиц и DCR (подробный режим)
Видео 1м 37с - Автоматическое создание 2 таблиц и DCR (обычный режим)
Видео 1м 34с - Просмотр схемы DCR и таблицы)
Видео 2м 19с - Манипуляции с данными
Видео 1м 58с - Запросы Kusto к данным
Видео 3м 01с - Панели мониторинга
Видео 0м 48с - Пример использования данных — поиск по базе гарантий Lenovo
Видео 7м 25с - Развертывание с помощью ClientInspector DeploymentKit
ClientInspector можно использовать для сбора множества полезной информации с клиентов Windows — и отправки данных в пользовательские таблицы Azure LogAnalytics.
Скрипт собирает следующую информацию (настройки, данные, конфигурацию, состояние):
Не стесняйтесь добавлять другие полезные сборы данных для своих нужд. Если вы хотите принять участие в сообществе, отправьте мне письмо с вашими сборами данных, если считаете, что они могут быть полезны всему сообществу.
Вы можете использовать любые исходные данные, которые можно получить в PowerShell (WMI, CIM, внешние данные, REST API, XML-формат, JSON-формат, CSV-формат и т.д.)
Очень важно понимать, что данные обычно нужно обрабатывать перед отправкой — чтобы убедиться, что они корректны, и удалить все лишние данные.
ClientInspector использует все 24 функции модуля PowerShell AzLogDcIngestPS для обработки исходных данных: удаления «шума» в данных, переименования запрещенных столбцов в таблицах/DCR — и обеспечения прозрачности с дополнительной информацией, такой как 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
В рамках первоначального развертывания с использованием ClientInSpectorV2-DeploymentKit вы получите доступ к множеству панелей мониторинга Azure и книг Azure.
Видео 3мин 01с - Панели мониторинга
Идея панелей мониторинга заключается в том, что они показывают, где ваша инфраструктура отклоняется от 'желаемого состояния'. Рассматривайте их как KPI, где инфраструктура не находится под контролем.
Вместо того чтобы ставить задачу по установке исправлений и управлению антивирусом, вы можете рассмотреть возможность использования KPI, которые будут показывать, где компьютеры не исправлены - или где защита в реальном времени в антивирусе не запущена - или машины, которые синеэкраннулись за последние 24 часа.
Это та же концепция, что и Microsoft Secure Score.















Ссылка для просмотра полного списка предоставленных книг Azure
Все образцы панелей мониторинга Azure созданы на основе закрепленных частей из книг Azure, поэтому если вы хотите углубиться, вы можете нажать на ссылку и получите доступ к подробной информации.

Ссылка для просмотра предоставленных панелей мониторинга Azure
Если вы хотите добавить больше панелей мониторинга или книг, вы обычно начинаете с изучения собранных данных в таблицах пользовательских журналов с помощью запросов KQL. Когда вы найдете нужный запрос, вы можете создать новые представления в книгах - и закрепить избранное на своих панелях мониторинга.
Если вы не знаете язык Kusto, я рекомендую вам начать с ним играть, так как это действительно мощный язык.
Видео 1мин 58с - Запросы Kusto к данным
Видео 3мин 01с - Панели мониторинга
Напишите свой первый запрос с помощью языка запросов Kusto
Анализ результатов запросов с помощью KQL
Ниже приведены 4 примера запросов, чтобы вы могли начать - на основе данных из ClientInspector.
Если вы хотите выполнить расширенный поиск, вы можете использовать традиционные запросы Kusto (KQL) в таблицах
#----------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------
$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>
## Пример запроса 4: Интеграция данных с другими источниками (проверка гарантии по базе данных Lenovo)
Когда данные находятся в Azure LogAnalytics, мы можем начать интегрировать их с другими источниками, например, с данными о гарантии Dell или Lenovo через REST API запрос.
[Видео 0м 48с - Пример использования данных - запрос к базе гарантий Lenovo](https://youtu.be/3ZDyTwiLU0w)
Вот пример вывода, который был автоматически создан PowerShell-скриптом: извлечение списка компьютеров и серийных номеров, а затем запрос к базе данных гарантий Lenovo для получения информации о дате покупки компьютера и его гарантийном статусе.
[Пример вывода гарантии (Excel), основанный на данных, собранных ClientInspector](https://github.com/KnudsenMorten/ClientInspectorV2/raw/main/img/WarrantyInfo.xlsx)
<br>
# Архитектура, схема и сеть
ClientInspector (v2) загружает собранные данные в **пользовательские журналы** в **рабочее пространство Azure LogAnalytics**, используя **Log ingestion API**, **Azure Data Collection Rules (DCR)** и **Azure Data Collection Endpoints (DCE)**.

## Схема
Как DCR, так и таблица LogAnalytics имеют схему, которая должна соответствовать схеме исходного объекта. Это обрабатывается с помощью функций модуля AzLogDcrIngestPS.
[Видео 1м 40с - Автоматическое создание 2 таблиц и DCR (подробный режим)](https://youtu.be/rIUNs3yT-eI)
[Видео 1м 37с - Автоматическое создание 2 таблиц и DCR (обычный режим)](https://youtu.be/khQMDcON6r8)
[Видео 1м 34с - Просмотр схемы DCR и таблицы](https://youtu.be/NDSNhvpa4Gs)
AzLogDcrIngestPS поддерживает 2 режима управления схемой: **Merge** и **Overwrite**
### SchemaMode = Merge (по умолчанию)
Если вы установите SchemaMode = Merge, то новые свойства из исходного объекта будут добавлены (объединены) в текущую схему log analytics. DCR импортирует схему из таблицы log analytics, чтобы обеспечить их идентичность.
Режим по умолчанию — Merge, если вы не задаете переменную SchemaMode в функциях:
CheckCreateUpdate-TableDr-Structure
CreateUpdate-AzLogAnalyticsCustomLogTableDcr
CreateUpdate-AzDataCollectionRuleLogIngestCustomLog
### SchemaMode = Overwrite
Если вы установите SchemaMode = Overwrite, то схема в DCR и таблице будет перезаписана (обновлена) на основе схемы исходного объекта.
## Сеть
У вас есть 3 варианта подключения к Azure для загрузки данных:
|Метод загрузки|Детали подключения|Соответствие ОС|
|:------------|:-------------------|:------------|
|Публичный доступ|REST-конечная точка отправляет данные в DCE через публичный IP DCE|Конечная точка поддерживает TLS 1.2|
|Частный доступ|REST-конечная точка отправляет данные в DCE через приватный канал DCE|Конечная точка поддерживает TLS 1.2|
|Log-hub|REST-конечная точка отправляет данные через [log-hub](https://github.com/KnudsenMorten/AzLogDcrIngestPSLogHub) — концепцию, которую я создал.|Конечная точка не поддерживает TLS 1.2.<br> Azure не будет принимать подключения от этих устройств напрямую|
### Интернет-подключенные конечные точки - соответствие на уровне ОС

Вам необходимо разрешить следующие конечные точки в вашем брандмауэре:
|Конечная точка|Назначение|Порт|Направление|Пропустить проверку HTTPS|
|:-------|:------|:----|:-------|:----------------------|
|global.handler.control.monitor.azure.com|Служба управления доступом|Порт 443|Исходящий|Да|
|dce logs ingestion uri<br><br>образец<br>https://dce-log-platform-management-client-demo-p-iur0.westeurope-1.ingest.monitor.azure.com|Загрузка данных журналов|Порт 443|Исходящий|Да|
<br>
### Нет доступа к Интернету или несоответствие на уровне ОС, напр. работа с TLS 1.0/1.1
[Ознакомьтесь с концепцией log-hub по этой ссылке](https://github.com/KnudsenMorten/AzLogDcrIngestPSLogHub)

<br>
# Реализация
Надеюсь, вы убедитесь, что все довольно просто настроить и запустить. Ниже описаны 3 шага.
Прежде чем начать, рекомендую подробнее ознакомиться с компонентами во введении ниже.
<details>
<summary>Введение в компоненты Azure, используемые в ClientInspector</summary>
<br>
Необходимы следующие компоненты:
| Ресурс Azure | Назначение | Дополнительная информация |
| :------------- | :----- | :----- |
| Любая REST-конечная точка | Это источник, отправляющий данные | |
| Log Ingestion API | Это новый API, заменяющий старый HTTP Data Collector API | https://learn.microsoft.com/en-us/azure/azure-monitor/logs/logs-ingestion-api-overview |
| Data Collection Endpoint (DCE)| Это точка входа для связи с конечной точкой. Данные отправляются на **Azure Data Collection Endpoint Ingestion Uri**. Один DCE может поддерживать несколько DCR, поэтому вы можете указать разные DCR для разных источников и целевых таблиц. | https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/data-collection-endpoint-overview?tabs=portal |
| Data Collection Rules (DCR) | Правила сбора данных определяют собираемые данные (схему) и указывают, как и куда эти данные должны быть отправлены или сохранены. DCR должен понимать структуру входных данных и структуру целевой таблицы. Если они не совпадают, можно использовать преобразование для преобразования исходных данных в соответствие целевой таблице. Также можно использовать преобразование для фильтрации исходных данных и выполнения других вычислений или преобразований. | https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/data-collection-rule-overview |
| Azure LogAnaltyics Workspace | Данные отправляются в пользовательские журналы в Azure LogAnalytics | https://learn.microsoft.com/en-us/azure/azure-monitor/logs/log-analytics-overview |
| Azure Workbooks | В рамках развертывания будут развернуты образцы книг | https://learn.microsoft.com/en-us/azure/azure-monitor/visualize/workbooks-overview |
| Azure Dashboards | В рамках развертывания будут развернуты образцы книг | https://learn.microsoft.com/en-us/azure/azure-monitor/visualize/tutorial-logs-dashboards |
| Kusto (KQL) | Данные можно анализировать с помощью запросов Kusto (KQL) | https://learn.microsoft.com/en-us/azure/azure-monitor/logs/get-started-queries |
</details>
Шаги по настройке ClientInspector в вашей среде:
1. [Настройка среды с помощью ClientInSpectorV2-DeploymentKit](https://github.com/KnudsenMorten/ClientInspectorV2-DeploymentKit)
2. Запустите ClientInspector в первый раз (первоначальная настройка) - подробнее ниже
<details>
<summary>Как настроить первоначальную настройку таблиц Azure LogAnalytics и правил сбора данных (в первый раз)</summary>
<br>
Я рекомендую иметь эталонный компьютер, который используется для управления таблицами/DCR. Таким образом, процесс будет контролируемым, если потребуется внести изменения — например, если изменится схема исходного объекта.
<br>
<br>
Конфигурация:
1. Когда вы запускаете DeploymentKit, он автоматически подготовит для вас файл ClientInspector, так что вам нужно только вставить переменные```js
$TenantId = "xxxx"
$LogIngestAppId = "xxxx"
$LogIngestAppSecret = "xxxx"
$DceName = "xxxx"
$LogAnalyticsWorkspaceResourceId = "xxxx"
$AzDcrPrefixClient = "xxx"
$AzDcrSetLogIngestApiAppPermissionsDcrLevel = $false
$AzDcrLogIngestServicePrincipalObjectId = "xxx"
$AzDcrDceTableCreateFromReferenceMachine = @()
$AzDcrDceTableCreateFromAnyMachine = $true
Скачайте скрипт обнаружения ClientInspector_Detection.ps1 (щелкните правой кнопкой мыши и выберите 'сохранить ссылку как')
Откройте файл в вашем любимом редакторе. Настройте частоту, с которой вы хотите запускать инвентаризацию```js ##################################
##################################
$RunEveryHours = 8
$LastRun_RegPath = "HKLM:\SOFTWARE\ClientInspector"
$LastRun_RegKey = "ClientInSpector_System"
3. Теперь нам нужно создать задачу исправления. Перейдите в портал Microsoft Intune -> Отчеты -> Анализ конечных точек -> Активные исправления и создайте пакет сценария, как показано ниже.
ПРИМЕЧАНИЕ: Для сценария исправления используйте файл **ClientInspector.ps1**


### Ограничение Intune
ПРИМЕЧАНИЕ: Intune имеет ограничение в 200 Кб на размер сценария исправления.**

В случае, если вы столкнулись с этим, я предлагаю разделить скрипт на 2 скрипта.


Не забудьте включить раздел заголовка, включая раздел UserLoggedOn, в качестве заголовка второго файла. UserLoggedOn используется для отображения того, какой пользователь вошел в систему.
Я подготовил [пример настройки скрипта](https://github.com/KnudsenMorten/ClientInspectorV2/tree/main/Sample%20intune%20setup%20if%20file%20size%20is%20more%20than%20200%20Kb), где вы можете увидеть, как их разделить. Примечание: код в этих скриптах НЕ обновлен, поэтому обязательно берите разделы из главного файла ClientInspector.
В основном структура такая:
Файл 1 содержит заголовок + UserLoggedOn (раздел 1) + разделы 2-9 + записывает флаг проверки в HKLM\Software\ClientInspector\ClientInspector_System_1
Файл 2 содержит заголовок + UserLoggedOn (раздел 1) + разделы 10-18 + записывает флаг проверки в HKLM\Software\ClientInspector\ClientInspector_System_2



</details>
<details>
<summary>Как развернуть с помощью ConfigMgr (или любого другого инструмента, запускающего CMD-файл)?</summary>
<br>
Вы будете запускать скрипт инвентаризации с помощью традиционного пакета + развертывание
1. [Скачайте CMD-файл ClientInspector.cmd](https://github.com/KnudsenMorten/ClientInspectorV2/raw/main/ConfigMgr/ClientInspector.cmd) (щелкните правой кнопкой мыши и выберите 'Сохранить ссылку как')
2. Создайте структуру источника в каталоге источника пакета ConfigMgr, например, с именем ClientInspector.
3. Скопируйте 2 необходимых файла **ClientInspector.cmd** и **ClientInspector.ps1** в этот каталог
4. Создайте пакет и укажите пакету запускать **ClientInspector.cmd**
5. Создайте развертывание
</details>
<br>
# Зависимости
## Модуль PowerShell AzLogDcrIngestPS - создан мной (Morten Knudsen)
ClientInspector требует модуль PowerShell **AzLogDcrIngestPS**
Основные возможности модуля PowerShell **AzLogDcrIngestPS** включают:
* автоматическое создание/обновление DCR и таблиц на основе схемы исходного объекта
* проверка схемы на соответствие правилам именования. При обнаружении проблем будут приняты меры по их устранению
* обновление схемы DCR и таблиц, если структура исходного объекта изменяется
* автоматическое исправление, если что-то пошло не так с DCR или таблицей
* может удалять данные из исходного объекта, если есть столбцы данных, которые вы не хотите отправлять
* может преобразовывать исходные объекты на основе CIM или PS объектов в PSCustomObjects/массив
* может добавлять соответствующую информацию к каждой записи, например UserLoggedOn, Computer, CollectionTime
Вы можете найти более подробную информацию о модуле по ссылкам ниже:
[AzLogDcrIngestPS (Github)](https://github.com/KnudsenMorten/AzLogDcrIngestPS)
[AzLogDcrIngestPS (Powershell Gallery)](https://www.powershellgallery.com/packages/AzLogDcrIngestPS)
[AzLogDcrIngestPSLogHub (Github)](https://github.com/KnudsenMorten/AzLogDcrIngestPSLogHub)
<br>
## Сторонние модули PowerShell
Я предпочитаю получать информацию об обновлениях Windows с помощью известного модуля PowerShell, PSWindowsUpdate.
|Имя модуля|Назначение|Дополнительная информация|Автор|
|:---------|:---------|:------------------------|:----|
|NuGet|Общий поставщик пакетов, используемый для развертывания многих модулей PowerShell, включая AzLogDcrIngestPS<br><br>Поставщик пакетов будет автоматически установлен на компьютере при запуске скрипта|[Ссылка](https://www.nuget.org/packages)||
|PSWindowsUpdate|Сбор информации об обновлениях Windows (ожидающие обновления, установленные обновления и т.д.)<br><br>Модуль будет автоматически установлен на компьютере при запуске скрипта|[Ссылка](https://www.powershellgallery.com/packages/PSWindowsUpdate)|Michal Gajda|
<br>
# Запуск ClientInspector.ps1 - 3 режима
ClientInspector поддерживает 3 способа установки/обновления/импорта необходимого модуля PowerShell: **Download**, **PsGallery**, **LocalPath**
По умолчанию он загружает последнюю версию из PsGallery в область CurrentUser.
[Видео 3м 19с - Запуск ClientInspector с помощью командной строки (обычный режим)](https://youtu.be/4kA4BE0zJ9g)
## .\ClientInspector.ps1 -function:LocalPath
ClientInspector будет искать файл **AzLogDcrIngest.psm1** в каталоге, откуда будет запущен скрипт.
Если AzLogDcrIngest.psm1 отсутствует, скрипт завершится, в противном случае он выполнит импорт модуля.
Пример```
.\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
Вы можете проверить исходный объект, выполнив эту команду````
# 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







Запустите PowerShell от имени локального администратора
Запустите скрипт с помощью этой команды```js C:\ClientInspector\ClientInspector.ps1 -verbose:$true
4. ClientInspector будет выполняться 10–20 минут и создаст необходимые таблицы и правила сбора данных на основе фактической структуры в вашей среде. Пожалуйста, просмотрите результаты на экране и обратите внимание на любые ошибки (выделены красным).
5. Когда всё выглядит нормально, запустите скрипт повторно — он выполнится намного быстрее. Проверьте поступление данных с помощью запросов Kusto в различных таблицах. ПРИМЕЧАНИЕ: первая загрузка данных может занять примерно 10–15 минут, так как в фоновом режиме необходимо создать конвейер.
6. В качестве последнего изменения нам нужно поменять 2 параметра в parameters, чтобы указать ClientInspector вносить изменения схемы только при запуске с эталонной машины.```js
$AzLogDcrTableCreateFromReferenceMachine = @("<<MyReferenceMachineComputerName>>") # sample @("ComputerName")
$AzLogDcrTableCreateFromAnyMachine = $false # important so changes can only happen on reference machine
ClientInspector будет загружать последнюю версию из моего репозитория GitHub и сохранять её в локальном пути каждый раз при запуске (примерно 300 кб).
Пример``` .\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]
Этот параметр требует дополнительный параметр: -scope [AllUsers | CurrentUser]
ClientInspector проверит, установлен ли модуль в выбранной области. Если не установлен, он автоматически загрузит последнюю версию из Powershell Gallery и выполнит import-module. Если клиент использует последнюю версию, он продолжит работу.
Пример```
.\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 !
Мы представляем собой специализированный инструмент перевода контента по кибербезопасности для Kitploit, каталога инструментов безопасности с открытым исходным кодом. Наша единственная функция — производить точные, идиоматические и лаконичные переводы содержимого Markdown с одного языка на другой.``` .\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>
## Пример вывода ClientInspector
[Видео 3m 19s — Запуск ClientInspector из командной строки (обычный режим)](https://youtu.be/4kA4BE0zJ9g)
<br>
# Безопасность
## Подпись кода
Как **файл ClientInspector.ps1**, так и **модуль AzLogDcrIngestPS (AzLogDcrIngest.psm1)** подписаны моим сертификатом подписи кода (2LINKIT — моя компания). Таким образом, вы можете запускать скрипт, если требуются подписанные скрипты. Конечно, вы также можете подписать его своим собственным внутренним сертификатом подписи кода.

Пожалуйста, [скачайте сертификат открытого ключа](https://github.com/KnudsenMorten/ClientInspectorV2/raw/main/Trusted_Publisher_Certificate/2LINKIT-TrustedPublisher.cer) и поместите его в контейнер «доверенный издатель», чтобы доверять издателю (2LINKIT — моя компания). Вы можете развернуть это с помощью Intune или групповой политики.



### Развёртывание Intune не требует установки доверенного издателя
По умолчанию Intune выполняет BYPASS при запуске скриптов исправлений.
## Структура
Безопасность **ClientInspector** разделена на 4 слоя: **ввод данных**, **выгрузка данных** (отправка в бэкенд) и **просмотр данных** (панели мониторинга) — а также **управление схемой**.
| Этап | Реализация безопасности |Делегирование / Разрешения|
|:------|:------------------------|:------------------------|
|Ввод данных (сбор)|Этот этап контролируется выбранным методом сбора (Intune, ConfigMg или другое стороннее ПО)|Скрипт должен выполняться с правами локального администратора (контекст системы), чтобы иметь возможность собирать основные данные об оборудовании и Windows|
|Выгрузка данных|Аутентификация для API приема журналов выполняется в DCE, который использует стандартную аутентификацию Azure Resource Manager.<br><br>Обычная стратегия — использовать идентификатор приложения и ключ приложения, что также является методом, используемым в ClientInspector.<br><br>Идентификатор приложения Azure и секрет хранятся в заголовке ClientInspector для простоты.<br><br>Также возможно использовать Azure Keyvault для хранения идентификатора приложения и секрета|[Подробности описаны в ClientInspectV2-DeploymentKit](https://github.com/KnudsenMorten/ClientInspectorV2-DeploymentKit#security-1)|
|Просмотр данных|Разрешения Azure RCAC|Предоставьте доступ к вашему Azure LogAnalytics, Azure Workbooks и Azure Dashboards|
|Управление схемой|Метод 1: Azure RBAC (рекомендуется)<br><br>Метод 2: приложение Azure с секретом или сертификатом|[Подробности описаны в ClientInSpectorV2-DeploymentKit](https://github.com/KnudsenMorten/ClientInspectorV2-DeploymentKit#azure-rbac-security-adjustment-separation-of-permissions-between-log-ingestion-and-tabledcr-management)|
<br>
# Структура набора данных ClientInspector
Каждый набор данных (bios, applications, bitlocker и т. д.) построен по одной и той же 4-фазной структуре:
## Фаза 1/4 - Переменные (именование - куда отправлять данные)```
#-------------------------------------------------------------------------------------------
# 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
## Этап 3/4 - Обработка данных (обеспечить правильный формат данных, удалить любой 'шум' и добавить релевантную информацию)```
#-------------------------------------------------------------------------------------------
# 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>
**СОВЕТ: ошибка 513 - объект слишком большой**
По умолчанию ClientInspector отправляет данные пакетами в зависимости от рассчитанного среднего размера каждой записи. Если ваш набор записей имеет другой размер, вы можете получить ошибку 513.
Причина в том, что вы достигаете ограничения в 1 МБ на каждую загрузку (ограничение Azure Pipeline). Microsoft хочет получать много небольших фрагментов данных, поскольку это общая среда. Я сталкивался с этой проблемой при получении списка всех установленных приложений. По-видимому, приложения хранят информацию с очень разной степенью размера.
Вы можете смягчить эту проблему, добавив параметр **-BatchAmount <количество записей для отправки за пакет>** в Post-команду. Если хотите быть уверены, установите его на 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 & Дополнительная справка
Если вы хотите получить более подробную информацию о том, что происходит, вы можете включить подробный режим (-verbose:$true)```
.\ClientInspector.ps1 -verbose:$true -function:localpath
Если вы предпочитаете тестировать с помощью Powershell ISE, вы также можете включить подробный режим, используя переменную $Verbose``` $Verbose = $false # can be $true or $false
Если вы хотите получить справку по синтаксису и примерам из модуля AzLogDcrLogIngestPS, вы можете написать
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
Получить справку по конкретному командлету - 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>
# Стоимость – сколько стоит хранение этих данных?
Данные от **500** клиентов, выполняющих **ежедневную** инвентаризацию ClientInspector, обойдутся вам примерно в **200 датских крон в месяц / 27 долларов США в месяц**
<br>
# Обнаружение ошибок, сообщите мне
Сегодня ClientInspectorV1 используется на тысячах компьютеров (а ServerInspectorV1 – на тысячах серверов).
Поскольку ClientInspectorV2 — это полная переработка V1, которая сейчас внедряется с, например, новыми правилами именования, я не могу гарантировать, что ошибок не будет.
Но **я могу вам пообещать**, что исправлю их так быстро, как позволит моё свободное время. Пожалуйста, отправляйте мне письмо на [email protected] с вашими находками.
Рекомендую сделать форк репозитория на GitHub — или следить за обновлениями в панелях мониторинга/книгах или скрипте ClientInspector.
Кроме того, ClientInspector создан для покрытия различных конфигураций и платформ, но у вас могут быть уникальные настройки, не охваченные коллекциями или панелями мониторинга.
Однако открытый подход позволяет вам настроить как панели мониторинга, книги, так и скрипт ClientInspector, чтобы он работал на 100% для вас. Считайте это демонстрацией возможностей для работы с технологиями журналирования Azure — это не платный продукт с круглосуточной поддержкой. Он бесплатен для всех!
<br>
# Контакты
Если у вас есть комментарии к решению — или вы просто хотите связаться со мной, обращайтесь через эти каналы — буду рад знакомству:
[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>
# Большое спасибо замечательным людям из команд продуктов Microsoft — вы рок-звёзды :smile:
В завершение хочу выразить огромную благодарность нескольким людям, с которыми я работал над созданием модуля PowerShell AzLogDcrIngestPS и в своей повседневной работе с возможностями журналирования и просмотра Azure:
|Имя|Роль|
|:---|:---|
|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 (integration to Azure Monitor Agent)|
