Резервирование и восстановление объектов групповых политик (GPO)

Майкл Олиг, 18 апреля 2019 года

Вот и финальная заметка из серии о резервировании и восстановлении Active Directory, где мы обсудим резервное копирование и восстановление объектов групповых политик. Хотя технически групповые политики отделены от каталога Active Directory, эти два решения очень тесно связаны. Active Directory не только содержит все объекты пользователей и компьютеров, контролируемые групповыми политиками, но также предоставляет структуру, позволяющую применять данные политики к этим пользователям и компьютерам.

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

Перед тем, как погрузиться в резервирование и восстановление объектов групповых политик (Group Policy Object, GPO), давайте, по сложившейся в этой серии заметок традиции, немного отвлечёмся, разбавив повествование некоторой справочной информацией об этих самых объектах групповой политики.

Создание объекта групповой политики в домене — сфера ответственности контроллера домена Active Directory с FSMO-ролью (Flexible Single Master Operator) эмулятора основного контроллера домена (PDC Emulator). В домене Windows NT было разрешено существование только одного доменного контроллера с возможностью записи данных, он назывался основным контроллером домена (Primary Domain Controller или PDC). Это было следствием архитектуры репликации Windows NT с единственным главным сервером. В противовес этому, Active Directory использует архитектуру с несколькими главными серверами, в которой все доменные контроллеры могут иметь возможность записи данных. Роль эмулятора PDC в Active Directory была разработана как часть стратегии упрощения миграции доменов Windows NT в Active Directory.

Эмулятор PDC имитирует поведение основного контроллера домена Windows NT как единственного главного сервера, делая его идеально подходящим для выполнения определённых функций, таких как минимизация возможности добавления конфликтующих GPO. Он также выполняет ряд столь же важных функций в домене: служит авторитетным источником для синхронизации времени и отвечает за фиксацию и репликацию особенно важной информации, например, при смене пароля.

При создании нового объекта групповой политики эмулятор PDC назначает идентификатор GUID, который используется для именования каждого из двух компонентов, составляющих объект групповой политики. Это гарантирует, что каждый объект групповой политики может быть уникально идентифицирован. Кроме того, это помогает защитить две групповые политики по умолчанию: Политику домена по умолчанию (Default Domain Policy) и Политику контроллеров домена по умолчанию (Default Domain Controllers Policy). Обе они именуются с использованием общеизвестных идентификаторов GUID: Политика домена по умолчанию всегда {31B2F340-016D-11D2-945F-00C04FB984F9}, а Политика контроллеров домена по умолчанию всегда {6AC1786C-016F-11D2-945F-00C04fB984F9}.

Первый компонент объекта групповой политики — шаблон групповой политики (Group Policy Template, GPT), состоящий из набора директорий внутри общей папки SYSVOL ("C:\Windows\SYSVOL\domain\Policies\{GUID}\"). Эти директории используются для хранения большей части содержимого объекта групповой политики (например, шаблонов, настроек, сценариев, сведений о пакетах MSI и т. д.). GPT реплицируются на каждый контроллер домена с помощью Службы репликации файлов (File Replication Service, FRS) или Репликации распределенной файловой системы (Distributed File System Replication, DFSR) в зависимости от версии Windows. Фактически, объекты групповой политики имеют эффект лишь в пределах домена, поскольку SYSVOL реплицируется только внутри домена.

Второй компонент объекта групповой политики — контейнер групповой политики (Group Policy Container, GPC), представляющий собой объект Active Directory groupPolicyContainer, располагающийся в ветке CN=System,CN=Policies в контексте именования домена. Атрибуты этого объекта используются для хранения справочной информации, относящейся к объекту групповой политики. В частности, в атрибуте gPCFileSysPath содержится путь к шаблону GPT объекта групповой политики в SYSVOL. В отличие от GPT, GPC реплицируется Доменными службами Active Directory (Active Directory Domain Services) в соответствии с настроенными стоимостью, расписанием и интервалом репликации.

После создания объекта групповой политики его можно связать с одним или несколькими объектами Active Directory. Эта связь поддерживается не на уровне объекта групповой политики, а в каждом объекте Active Directory, связанном с данным объектом групповой политики.

Такие связи являются внешними по отношению к самому GPO и содержатся в атрибуте gPLink, доступном в трёх классах объектов Active Directory: Organizational Unit ("OU"), Domain и Site. Значение атрибута gPLink представляет собой список путей к GPC каждого объекта групповой политики, с которым связан данный объект. При создании или удалении связи GPO с каким-либо объектом фактически модифицируется только значение атрибута gPLink соответствующего объекта.

(Примечание: Хотя репликация SYSVOL ограничивает эффект применения объекта групповой политики лишь конкретным доменом, тот факт, что объекты групповой политики могут быть связаны с объектом узла (Site), означает, что информация, связанная с объектом групповой политики, не обязательно ограничена доменом. Объекты узла хранятся в разделе Configuration Active Directory, который реплицируется на все контроллеры домена в лесу. В результате этого путь к GPC объекта групповой политики, содержащийся в атрибуте gPLink, так или иначе выводится за рамки конкретного домена во время репликации Active Directory.)

Порядок обработки групповой политики

Объекты Organizational Unit, Domain и Site также играют важную роль при определении приоритета применения политик в ситуациях, когда имеются конфликтующие друг с другом политики.

Active Directory применяет GPO в следующем порядке: локальные политики, политики узла, политики домена, политики контейнера OU, причём "побеждает" последняя применяемая групповая политика (если не была использована опция "Enforce", предотвращающая переопределение групповой политики со стороны следующих применяемых групповых политик). Групповые политики, привязанные к контейнерам Organizational Unit, обрабатываются, начиная с корня дерева каталога, поэтому объект групповой политики, связанный с вложенным контейнером OU, будет иметь приоритет над объектом групповой политики, связанным с его родительским контейнером OU.

И последнее, на что следует обратить внимание: объекты групповой политики содержат две подгруппы: Конфигурация компьютера (Computer Configuration) и Конфигурация пользователя (User Configuration). В обеих подгруппах находятся практически идентичные наборы параметров политики. Принципиальное различие между каждой из подгрупп заключается в том, когда эти параметры политики применяются.

Параметры конфигурации компьютера применяются к компьютерам во время загрузки, а параметры конфигурации пользователя применяются при входе в систему. Это означает, что параметры в подгруппе Конфигурация компьютера групповой политики всегда применяются к связанным с этой политикой компьютерам, а параметры в подгруппе Конфигурация пользователя применяются только тогда, когда пользователь c учётной записью, связанной с этой политикой, входит в систему на компьютере.

Если пользователь вошёл в систему на каком-то компьютере и возник конфликт между параметрами Конфигурации компьютера и Конфигурации пользователя, то параметры Конфигурации компьютера всегда будут превалировать над параметрами Конфигурации пользователя.

Ну а теперь давайте вернёмся к нашей основной теме и обсудим резервное копирование и восстановление объектов групповой политики.

Начнём с командлетов PowerShell Group Policy, доступных как часть пакета Windows Remote Server Administration Tools от Microsoft, включающего в себя командлеты Backup-GPO и Restore-GPO. С помощью командлета Backup-GPO очень просто создать снапшот как всех объектов групповой политики в домене, так и одного конкретного объекта групповой политики. Командлет Restore-GPO может восстановить объект групповой политики до его состояния, зафиксированного в резервной копии, созданной командлетом Backup-GPO.

В следующем PowerShell-скрипте используется командлет Backup-GPO с параметром -All для создания резервных копий всех GPO в домене с явно заданным именем с использованием контроллера домена, который также указан явно. Поддерживается многократное резервное копирование в одно и то же место, но в данном случае при каждом выполнении скрипта создаётся уникальная папка для выгрузки данных:

$BackupPath = '\\HOSTNAME\GPOBackup\'
$Domain = 'domain.com'
$DomainController = 'DC.domain.com'

$BackupFolder = New-Item -Path $BackupPath -Name (Get-Date -format yyyyMMddTHHmmss) -ItemType Directory
Backup-GPO -All -Domain $Domain -Server $DomainController -Path $BackupFolder

Выгружаемые данные командлета Backup-GPO состоят из отдельных подпапок для резервной информации каждого GPO, а также файла manifest.xml, содержащего информацию, необходимую для связывания каждой из этих подпапок с соответствующими объектами групповой политики.

Подпапки именуются с использованием специфичных для резервной копии идентификаторов GUID, генерируемых во время выполнения командлета, что практически исключает вероятность возникновения конфликта имён в результате многократного резервного копирования в одно и то же место.

Заглянув внутрь одной из таких подпапок, мы обнаружим, что каждая резервная копия состоит из одной папки и трёх XML-файлов.

В папке содержится копия GPT объекта групповой политики, а XML-файлы содержат данные из GPC объекта групповой политики, информацию, относящуюся к выполнению резервного копирования, а также отчёт, который описывает содержимое объекта групповой политики.

Как уже упоминалось выше, разделение выгружаемых данных при каждом выполнения скрипта на уникальные папки не является строго необходимым. Однако такая стратегия создает преимущество при выполнении командлета Restore-GPO. Командлет Restore-GPO позволяет восстановить все GPO сразу, но он будет использовать самую последнюю резервную копию каждого из объектов групповой политики согласно информации из файла manifest.xml. При разделении наборов резервных копий по отдельным папкам, каждый такой набор получает свой собственный файл manifest.xml. Это позволяет выполнить восстановление всех GPO из любого такого набора за одну операцию.

Недостатком использования параметра -All командлета Backup-GPO в приведённом выше сценарии является то, что он производит резервное копирование всех объектов групповой политики в домене, независимо от того, были они изменены или нет, при каждом его исполнении.

Поскольку мы работаем с PowerShell, мы можем попытаться обойти эту проблему, например, так, как представлено ниже:

$BackupPath = '\\HOSTNAME\GPOBackup'
$Domain = 'domain.com'
$DomainController = 'DC.domain.com'

if((Test-Path "$BackupPath\lastBackup")) {
    $LastBackup = Get-Content -Path "$BackupPath\lastBackup"
    Set-Content -Path "$BackupPath\lastBackup" -Value (Get-Date)
    $GPOs = Get-GPO -All -Domain $Domain -Server $DomainController
    $GPOs | Where-Object { $_.ModificationTime -gt $LastBackup } | ForEach-Object {
        Backup-GPO -Guid $_.Id -Domain $Domain -Server $DomainController -Path $BackupPath
    }
}
else {
    Set-Content -Path "$BackupPath\lastBackup" -Value (Get-Date)
    Backup-GPO -All -Domain $Domain -Server $DomainController -Path $BackupPath
} 

В этом скрипте PowerShell командлет Backup-GPO выполняется дифференцировано в зависимости от содержимого файла, который создается в папке обновлений и хранит отметку времени последнего выполнения сценария. Если данный файл существует, скрипт создаёт резервные копии только тех GPO домена, которые были изменены позднее той отметки времени, которая хранится в файле. Если же данного файла не существует, скрипт создаёт его, помещает в него отметку времени, и создаёт резервные копии всех GPO домена.

Хотя данный подход экономит дисковое пространство за счёт ограничения количества ненужных копий, все созданные им резервные копии в итоге оказываются в одной папке, что затрудняет восстановление объектов групповой политики до состояния на определенный момент времени.

Ничто не мешает нам скомбинировать подходы из обоих скриптов и решить тем самым все наши проблемы:

$BackupPath = '\\HOSTNAME\GPOBackup'
$Domain = 'domain.com'
$DomainController = 'DC.domain.com'

$BackupFolder = New-Item -Path $BackupPath -Name (Get-Date -format yyyyMMddTHHmmss) -ItemType Directory

if((Test-Path "$BackupPath\lastBackup")) {
    $LastBackup = Get-Content -Path "$BackupPath\lastBackup"
    Set-Content -Path "$BackupPath\lastBackup" -Value (Get-Date)
    $GPOs = Get-GPO -All -Domain $Domain -Server $DomainController
    $GPOs | Where-Object { $_.ModificationTime -gt $LastBackup } | ForEach-Object {
        Backup-GPO -Guid $_.Id -Domain $Domain -Server $DomainController -Path $BackupFolder
    }
}
else {
    Set-Content -Path "$BackupPath\lastBackup" -Value (Get-Date)
    Backup-GPO -All -Domain $Domain -Server $DomainController -Path $BackupFolder
} 

Но оказывается, что изоляция каждого из результатов дифференцированного резервного копирования в их собственных папках на самом деле делает всё намного хуже. Ведь при данном подходе также изолируются в отдельных папках и файлы manifest.xml, что с одной стороны лишает нас возможности одновременного восстановления всех объектов групповой политики, а с другой стороны значительно усложняет процесс поиска резервной копии, связанной с каким-либо конкретным объектом групповой политики.

На практике некоторые ограничения, с которыми сталкиваются рассмотренные нами подходы, — это ограничения, накладываемые относительно скромными возможностями командлета Restore-GPO.

# Восстановление одного GPO из его самой последней резервной копии
Restore-GPO -Name 'GpoName' -Path '\\HOSTNAME\GPOBackup' -Domain 'domain.com' -Server 'DC.domain.com'

# Восстановление одного GPO из конкретной резервной копии
Restore-GPO -BackupId 12345678-09ab-cdef-1234-567890abcdef -Path '\\HOSTNAME\GPOBackup' -Domain 'domain.com' -Server 'DC.domain.com' 

# Восстановление всех GPO домена из их самой последней резервной копии
Restore-GPO -All -Path '\\HOSTNAME\GPOBackup' -Domain 'domain.com' -Server 'DC.domain.com'

Restore-GPO может восстанавливать конкретный объект групповой политики либо из самой последней резервной копии, указанной в файле manifest.xml, либо из заданной резервной копии. Но восстановление всех GPO домена сразу ограничено использованием самых последних резервных копий из указанного файла manifest.xml.

Когда объект групповой политики восстанавливается из резервной копии, версия этого объекта увеличивается (то есть увеличение версии — часть процесса восстановления).

Данное увеличение версии предусмотрено для того, чтобы при репликации предпочтение отдавалось восстановленной копии объекта групповой политики.

Придётся нам ещё немного отвлечься.

Вывод командлета Restore-GPO включает два набора номеров версий: один для Конфигурации компьютера, второй — для Конфигурации пользователя.

GPT и GPC раздельно ответственны за поддержание своего собственного номера версии, причём отдельные значения UserVersion и ComputerVersion рассчитываются на основе соответствующих номеров версий Конфигурации пользователя и Конфигурации компьютера. Это становится возможным из-за применяемого метода увеличения номера версии. Он увеличивается на 1 при изменении Конфигурации компьютера объекта групповой политики, и на 65536 каждый раз при изменении Конфигурации пользователя.

Всё это важно, поскольку, как обсуждалось ранее, GPT и GPC объектов групповых политик реплицируются отдельно друг от друга разными сервисами, в результате чего номера версий GPT и GPC какой-либо групповой политики на каком-то контроллере домена могут оказаться рассинхронизированными (не совпадать). Пока объект групповой политики находится в этом состоянии, при его обработке будет возникать сбой. После того, как номера версий придут в состояние синхронизации, GPO вновь будут успешно обрабатываться.

А мы вновь возвращаемся к нашему повествованию.

Задокументированное ограничение командлета Restore-GPO — то, что он не может быть использован для восстановления объекта групповой политики, который был удалён. Попытка сделать это приведёт к примерно такой ошибке:

Причина, по которой работа командлета Restore-GPO завершается неудачей в данной ситуации — то, что он не может найти компонент GPC объекта групповой политики в каталоге Active Directory.

Если Вы сможете сначала восстановить GPC, то тогда Restore-GPO фактически может быть использован для восстановления объекта групповой политики. Посмотрите:

Когда GPC снова на месте (в последнем примере для полного восстановления компонента объекта групповой политики, хранящегося в Active Directory, из корзины Active Directory был использован командлет Restore-ADObject), командлет Restore-GPO способен восстановить GPO.

Хотя с помощью данного процесса можно восстановить удалённый GPO, но при этом не получится восстановить значения gPLink, существовавшие до того, как этот GPO был удалён. Всё потому, что, как мы уже упоминали, данные значения не были частью объекта групповой политики, а находились в самих связанных с этим GPO объектах каталога. Единственный безопасный способ обойти это ограничение — использовать отдельно созданные резервные копии Active Directory, содержащие данные значения gPLink.

Кроме командлетов PowerShell для работы с объектами групповой политики, Microsoft также предлагает Консоль управления групповыми политиками (Group Policy Management Console, GPMC), оснастку MMC, которая может использоваться для резервного копирования и восстановления объектов групповых политик. Как и командлет Backup-GPO, она может создавать резервные копии как отдельного заданного объекта групповой политики, так и всех GPO домена. В отличие от командлета Restore-GPO, её возможности ограничены восстановлением единственного GPO за раз.

GPMC предоставляет метод восстановления удалённого объекта групповой политики из резервной копии. Но на самом деле он не восстанавливает удалённый GPO, а просто создаёт новый и заполняет его параметры, используя информацию из резервной копии.

Ещё одним преимуществом GPMC является улучшенная наглядность представления содержимого резервных копий GPO, хотя по-прежнему сложно сравнивать параметры, содержащиеся в резервной копии, с текущими параметрами действующего объекта групповой политики.

Инструмент Microsoft Расширенное управление групповой политикой (Advanced Group Policy Management, AGPM), доступный как часть пакета Microsoft Desktop Optimization Pack, дополняет функциональные возможности GPMC за счёт внедрения в неё функции контроля версий. Это помогает расширить возможности просмотра и понимания содержимого созданных резервных копий.

Однако преимущества AGPM нивелируются с одной стороны тем, что он не очень-то хорошо поддерживается, а также тем, что он, по-видимому, плохо совместим с другими инструментами (например, модификация GPO, управляемого AGPM, произведённая за рамками AGPM, может привести к разрушению базы данных AGPM).

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

Ну вот и подошла к концу данная серия заметок.

Хотя в этой серии было рассмотрено довольно много методов, с помощью которых можно резервировать и восстанавливать различные части Active Directory, большинство из них нужно использовать с осторожностью, и, кроме того, ни один из них не способен полностью решить поставленную перед ним задачу самостоятельно.

Вот почему, в двух словах, существуют такие инструменты, как StealthRECOVER. StealthRECOVER предоставляет единый унифицированный веб-интерфейс с возможностью полнофункционального поиска по резервным копиям, рассылкой оповещений на электронную почту, возможностью резервировать в единый снапшот объекты Active Directory и групповых политик, а также расширенные возможности восстановления, в том числе восстановление удалённых объектов и откат изменений атрибутов у "живых" объектов каталога. Кроме того, восстанавливаются удалённые объекты групповых политик и связанные с ними значения атрибутов gPLink. Хотите проверить это? Свяжитесь с нами сегодня же!