Строим отчеты и анализируем групповые политики с помощью PowerShell

в 8:47, , рубрики: powershell, Блог компании NetWrix, системное администрирование, метки:

Строим отчеты и анализируем групповые политики с помощью PowerShellТема использования PowerShell для администрирования крайне актуальна, и на Хабре появляется все больше и больше статей на эту тему. Предыдущий перевод статьи Джеффри Хикса, который мы опубликовали в прошлую пятницу, вызвал волну интереса. И как тут не вспомнить замечательное выступление того же автора на TechEd North America 2012. Доклад, который Джеффри Хикс проводил вместе с Джереми Московицем (Jeremy Moskowitz), был посвящен анализу объектов групповых политик и формированию отчетов. Оригинальный материал (видео) здесь, мы же приводим крактко содержание + скрипты. В любом случае рекомендуем посмотреть само видео.

В фокусе доклада было два вопроса:

  1. Строит отчеты по групповым политикам
  2. Проводим анализ групповых политик

Подробности – под катом.

Используем PowerShell в связке с групповыми политиками: что для этого нужно?

Чтобы использовать PowerShell при работе с групповыми политиками, нам необходимы:

Последовательность наших действий:

  • Импортируем модуль групповых политик (Import-module GroupPolicy)
  • Получаем объект групповых политик с помощью PowerShell (Get a GPO PowerShell Object)
  • Строим отчет на основе этого объекта
  • Строим HTML/XML-отчеты по объектам групповых политик
  • Парсим и осуществляем поиск в XML для целей анализа
  • Осуществляем поиск с помощью Select-XML и Xpath

Строим отчеты по групповым политикам

Проблема №1. Необходимо получить информацию о том, что в настоящий момент происходит в групповых политиках

PS C:> Import-Module GroupPolicy
PS C:> Get-GPO JeremyGPO

В данном случае вместо JeremyGPO выступает отображаемое имя (DisplayName) объекта групповых политик. Выводится такая табличка

DisplayName      : JeremyGPO
DomainName       : GLOBOMANTICS.local
Owner            : GLOBOMANTICSDomain Admins
Id               : cd73c562-5bfe-40e2-b81e-28da10da425c
GpoStatus        : ComputerSettingsDisabled
Description      :
CreationTime     : 12/28/2011 2:52:37 PM
ModificationTime : 5/21/2012 11:08:26 AM
UserVersion      : AD Version: 4, SysVol Version: 4
ComputerVersion  : AD Version: 1, SysVol Version: 1
WmiFilter        :

Решение проблемы: создаем отчеты.

Например, перед нами стоит задача получить список всех объектов групповых, которые были изменены за последние 30 дней, отсортированные по убыванию (последние наверху) с тремя значениями (отображаемое имя, время изменения, описание). Полученную информацию необходимо экспортировать в .csv файл (GPOModReport.csv в данном примере). Как это выглядит в PowerShell:

PS C:> get-gpo -all | Where {$_.ModificationTime -gt (Get-Date).AddDays(-30)}

... | Sort ModificationTime -Descending | Where {$_.ModificationTime -ge (Get-Date).AddDays(-30)} | Select Displayname,ModificationTime,Description

... | Export-CSV R:GPOModReport.csv
Примеры дополнительных команд

#Созданные и измененные объекты групповых политик
PS C:>get-gpo -all | Sort CreationTime,Modificationtime | Select Displayname,*Time
#Находим все объекты групповых политик, измененные за последние 30 дней 
PS C:>get-gpo -all | Where {$_.ModificationTime -ge (Get-Date).AddDays(-30)}
#Создаем отчет по отдельному объекту групповых политик (Defaul Domain Policy)
PS C:>Get-GPOReport -name "Default Domain Policy" -ReportType HTML -Path "c:workddp.htm"
invoke-item "c:workddp.htm"
#Создаем отчеты по всем объектам групповых политик
PS C:>Get-GPOReport -All -ReportType HTML -Path "c:workallgpo.htm"
invoke-item "c:workallgpo.htm"
#Создаем для каждого объекта групповых политик свой отчет
#заменяем пробелы на _ в имени GPO
PS C:>Get-GPO -all | foreach { 
 $f="{0}.htm" -f ($_.Displayname).Replace(" ","_")
 $htmfile=Join-Path -Path "C:work" -ChildPath $f
 Get-GPOReport -Name $_.Displayname -ReportType HTML -Path $htmfile
 Get-Item $htmfile 
}

Проблема №2. Слишком много GPO, которые не используются.

Задача: найти пустые GPOs

  • Определить объекты групповых политик без настроек
  • Ищем XML ExtensionData
PS C:> Import-Module GroupPolicy
PS C:> [xml]$r = Get-GPOReport -Name MyGPO 
-ReportType XML
PS C:> if ((-Not $r.gpo.user.extensiondata) -AND (-not $r.gpo.computer.extensiondata)) {
 "GPO is empty"
 }
Дополнительные команды

#requires -version 2.0

#find empty gpos in the domain

Function Get-EmptyGPO {

Param (
[Parameter(Position=0,ValueFromPipeline=$True,
ValueFromPipelinebyPropertyName=$True)]
[string]$DisplayName
)

Begin {
#import the GroupPolicy Module
Import-Module GroupPolicy

}

Process {
#create an XML report
[xml]$report=Get-GPOReport -Name $displayname -ReportType XML

 #totally empty
 if ((-Not $report.gpo.user.extensiondata) -AND (-not $report.gpo.computer.extensiondata)) {
    #no extension data so write
    Get-GPO -Name $Displayname
}

} #process

End {}

} #function

Function Test-EmptyGPO {

Param (
[Parameter(Position=0,ValueFromPipeline=$True,
ValueFromPipelinebyPropertyName=$True)]
[string]$DisplayName
)

Begin {
#import the GroupPolicy Module
Import-Module GroupPolicy

}

Process {

    #set default values
    $User=$False
    $Computer=$False
    #create an XML report
    [xml]$report=Get-GPOReport -Name $displayname -ReportType XML

    if ($report.gpo.user.extensiondata) {
     $User=$True
    }
    If ( $report.gpo.computer.extensiondata) {
     $Computer=$True
    }
    #write a custom object to the pipeline
    New-Object -TypeName PSObject -Property @{
    Displayname=$report.gpo.name
    UserData=$User
    ComputerData=$Computer
    }

} #Process

End {}

} #function

#Get-GPO -All | Get-EmptyGPO
#Get-GPO -All | Test-EmptyGPO

Проблема №3.
Кто обращался к объекту групповой политики?
Имеются ли GPO, в которых половина политики деактивирована (“Are there any GPOs with ‘half’ the policy disabled?”)
Имеются ли GPO, в которых все политики деактивированы (“Are there any GPOs with ‘all’ the policy disabled?”)

Применяем фильтр по статусу GPO (GPOStatus). Каждому из трех вопросов выше соответствуют три команды:

PS C:> get-gpo -all | Sort GPOStatus | format-table -GroupBy GPOStatus Displayname,*Time
PS C:> get-gpo -all | where {$_.GPOStatus -match "disabled"} | Select GPOStatus,Displayname
PS C:> get-gpo -all | where {$_.GPOStatus -match "AllSettingsDisabled"}

Анализируем объекты групповых политик

Проблема №4. Обнаруживаем GPO без связей

PS C:> Import-Module ActiveDirectory
Get-ADOrganizationalUnit -filter * | select-object
-ExpandProperty DistinguishedName | get-adobject 
-prop gplink | where {$_.gplink} | Select-object 
-expand gplink | foreach-object { 
foreach ($item in ($_.Split("]["))) {
$links+=$regex.match($item).Value
   } 
} 
Get-GPO -All | Where {$links -notcontains $_.id}

Дополнительные команды

#requires -version 2.0

<#
 Find unlinked GPOs. This requires the Active Directory Module
 This version does not query for site links
 #>

Import-Module ActiveDirectory,GroupPolicy

#GUID regular expression pattern
[Regex]$RegEx = "(([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12})"

#create an array of distinguishednames
$dn=@()
$dn+=Get-ADDomain | select -ExpandProperty DistinguishedName
$dn+=Get-ADOrganizationalUnit -filter * | select -ExpandProperty DistinguishedName

$links=@()

#get domain and OU links
    
foreach ($container in $dn) {

    #pull the GUID and add it to the array of links

    get-adobject -identity $container -prop gplink | 
    where {$_.gplink} | Select -expand gplink | foreach {
      
      #there might be multiple GPO links so split 
            
      foreach ($item in ($_.Split("]["))) {
        $links+=$regex.match($item).Value
      } #foreach item
    } #foreach
} #foreach container

#$links

<#
 get all gpos where the ID doesn't belong to the array
 write the GPO to the pipeline
#>

Get-GPO -All | Where {$links -notcontains $_.id} 

Проблема 5. Объекты групповых политик с излишними настройками в реестре (“Extra Registry Settings”)

Находим излишние настройки в реестре

#Use Xpath with the XML report data
PS C:> [xml]$report = Get-GPOReport -Name MyGPO 
-ReportType XML
PS C:> $ns = @{q3 = "http://www.microsoft.com/GroupPolicy/Settings/Registry"}
PS C:> $nodes = Select-Xml -Xml $report -Namespace $ns -XPath "//q3:RegistrySetting" | select -expand Node | Where {$_.AdmSetting -eq 'false'}

Дополнительные команды

#requires -version 2.0

#find GPOs with extra registry, ie non-ADM settings

Function Test-GPOExtraRegistry {

Param (
[Parameter(Position=0,ValueFromPipeline=$True,
ValueFromPipelinebyPropertyName=$True)]
[string]$DisplayName
)

Begin {
    #import the GroupPolicy Module
    Import-Module GroupPolicy
}

Process {
#create an XML report
[xml]$report=Get-GPOReport -Name $displayname -ReportType XML
#define the XML namespace
$ns=@{q3="http://www.microsoft.com/GroupPolicy/Settings/Registry"}
$nodes=Select-Xml -Xml $report -Namespace $ns -XPath "//q3:RegistrySetting" | 
select -expand Node | Where {$_.AdmSetting -eq 'false'}

if ($nodes) {
  #extra settings were found so get the GPO and write it to the pipeline
  Get-GPO -Name $Displayname
}

}

End {}

} #function

#Import-Module GroupPolicy
#Get-GPO -all | Test-GPOExtraRegistry 

Еще раз обозначим, что мы привели в посте лишь сухой остаток того, что было продемонстрировано в докладе. Сам доклад можно посмотреть здесь.

Бонусы:

Также для построения отчетов по групповым политикам вы можете воспользоваться нашей программой NetWrix Group Policy Change Reporter.

Автор: NetWrixRU

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js