Обезличивание данных Active Directory с очисткой корзины
В разделе описывается последовательность шагов по обезличиванию данных Active Directory (AD) на сервере с ОС Windows Server, включая очистку корзины.
Предварительные требования
Для успешного выполнения описываемых шагов обеспечьте соблюдение следующих требований:
-
все действия выполняются от имени пользователя с правами на выгрузку и загрузку данных в БД AD и выполнение указанных командлет PowerShell;
-
команды выполняются на машине с установленным модулем Active Directory для Windows Powershell непосредственно на сервере либо с использованием средств удаленного администрирования;
-
последовательности команд могут выполняться непосредственно в терминале Windows PowerShell, в том числе в среде Windows PowerShell ISE, либо в виде скриптов (для удобства приводятся оба варианта);
-
для выполнения отдельных шагов требуется следующее дополнительное программное обеспечение:
-
Microsoft Excel любой версии;
-
оснастка ADSI Edit (adsiedit.msc);
-
утилита ldp для подключения к БД по LDAP с целью выполнения контрольных проверок.
-
Выгрузка данных пользователей
-
Выгрузите данные любым из двух способов:
-
выполните в терминале Windows PowerShell или среде Windows PowerShell ISE следующую последовательность команд, указав в качестве входных параметров полное доменное имя сервера (
server.domain.name
), имя домена (domain.name
), путь к CSV-файлу с данными пользователей (path-to-user-list-file
) и путь к текстовому файлу со списком удаляемых пользователей (path-to-users-to-delete
):$domainController = "<server.domain.name>" $domain = "<domain.name>" $outputFile = "<path-to-user-list-file>\UserList.csv" $path = "<path-to-users-to-delete>\UsersToDelete.txt" $users = Get-ADUser -Filter * -Properties * -Server $domainController $output = @() $output += "OU;Name;GivenName;SurName;DisplayName;Title;SamAccountName;UserPrincipalName;EmailAddress" foreach ($user in $users) { $ou = ($user.DistinguishedName -split ",", 2)[1] $userLine = "$ou;$($user.Name);$($user.GivenName);$($user.SurName);$($user.DisplayName);$($user.Title);$($user.SamAccountName);$($user.UserPrincipalName);$($user.EmailAddress)" $output += $userLine } $output | Out-File $outputFile Get-ADUser -filter * | select SamAccountName | Out-File -FilePath $path $content = Get-Content $path $content | Foreach {$_.TrimEnd()} | ? {$_.trim() -ne "" } | Set-Content $path
-
с помощью скрипта:
-
загрузите на сервер скрипт или создайте файл export_users.ps1 следующего содержания:
Скрипт для выгрузки данных пользователей AD и списка пользователей
param ( [string]$domainController, [string]$domain, [string]$outputFile, [string]$path ) $users = Get-ADUser -Filter * -Properties * -Server $domainController $output = @() $output += "OU;Name;GivenName;SurName;DisplayName;Title;SamAccountName;UserPrincipalName;EmailAddress" foreach ($user in $users) { $ou = ($user.DistinguishedName -split ",", 2)[1] $userLine = "$ou;$($user.Name);$($user.GivenName);$($user.SurName);$($user.DisplayName);$($user.Title);$($user.SamAccountName);$($user.UserPrincipalName);$($user.EmailAddress)" $output += $userLine } $output | Out-File $outputFile Get-ADUser -filter * | select SamAccountName | Out-File -FilePath $path $content = Get-Content $path $content | Foreach {$_.TrimEnd()} | ? {$_.trim() -ne "" } | Set-Content $path
-
запустите скрипт в терминале Windows PowerShell:
./export_users.ps1 <server.domain.name> <domain.name> <path-to-user-list-file> <path-to-users-to-delete-file>
Входные параметры:
-
server.domain.name
— полное доменное имя сервера; -
domain.name
— имя домена; -
path-to-user-list-file
— путь и имя для CSV-файла с данными пользователей; -
path-to-users-to-delete-file
— путь и имя для текстового файла со списком удаляемых пользователей.
Пример команды запуска скрипта:
./export_users.ps1 WINDOWS-OT89IIK.testl.lan testl.lan C:\temp\UserList.csv C:\temp\UsersToDelete.txt
-
-
-
-
Откройте созданный файл UserList.csv в текстовом редакторе, чтобы убедиться в корректности выгрузки.
Он должен иметь следующий формат:OU;Name;GivenName;SurName;DisplayName;Title;SamAccountName;UserPrincipalName;EmailAddress CN=Users,DC=domain,DC=name;Administrator;;;;;Administrator;; CN=Users,DC=domain,DC=name;Guest;;;;;Guest;; CN=Users,DC=domain,DC=name;krbtgt;;;;;krbtgt;; CN=Users,DC=domain,DC=name;Ivan Ivanov;Ivan;Ivanov;Ivan Ivanov;;iivanov;iivanov@domain.name;ivanov@mail.com CN=Users,DC=domain,DC=name;Petr Petrov;Petr;Petrov;Petr Petrov;;ppetrov;ppetrov@domain.name;petrov@mail.com
-
Откройте файл UsersToDelete.txt в текстовом редакторе, чтобы убедиться в корректности выгрузки.
Он должен иметь следующий формат:SamAccountName -------------- Administrator Guest krbtgt iivanov ppetrov
-
В файле UsersToDelete.txt:
-
удалите заголовок;
-
удалите из списка сервисных пользователей (Administrator, Guest и т. д.);
-
удостоверьтесь, что в списке присутствуют только значения атрибута
SamAccountName
тех пользователей, данные которых требуется удалить. На каждой строке должно быть только одно значениеSamAccountName
.Например:
iivanov ppetrov
-
Обезличивание данных пользователей
Чтобы обезличить данные пользователей, выгруженные в файл UserList.csv:
-
Создайте пустую книгу в Microsoft Excel.
-
На вкладке Данные нажмите Из текстового/CSV-файла.
Рис. 1. Вкладка «Данные» в Microsoft Excel -
В диалоговом окне выберите CSV-файл с выгруженными данными и нажмите Импорт.
-
В окне предварительного просмотра убедитесь в корректности отображения данных. При необходимости внесите изменения в настройки отображения и нажмите Загрузить.
Рис. 2. Окно предварительного просмотра импортируемых данных -
В качестве имени листа с импортированными данными укажите "deface".
Рис. 3. Переименование листа -
Откройте вкладку Конструктор и снимите флажок Строка заголовка. Если первая строка в таблице пустая, удалите ее. Таким образом, в первой строке рабочего листа должны быть заголовки столбцов из CSV-файла.
Рис. 4. Удаление строки заголовка -
Нажмите Alt+F11.
-
В окне Microsoft Visual Basic for Applications нажмите F7.
-
В области редактора кода вставьте текст скрипта:
Скрипт для обезличивания данных AD
Sub Main() ChangeValuesToGenerated ChangeValueToHeaderValue ReplaceEmails CanonicalNameProc legacyExchangeDNProc DistinguishedNameProc HomeDirectoryClean End Sub Sub ChangeValuesToGenerated() Dim ws As Worksheet Dim headerArray As Variant ' Create array of headers Dim rng As Range Dim cell As Range Dim i As Integer Dim j As Integer Set ws = ThisWorkbook.Sheets("deface") ' Change your sheet name to deface headerArray = Array("CN", "DisplayName", "GivenName", "Name", "SamAccountName", "sn", "Surname") ' array of headers For j = LBound(headerArray) To UBound(headerArray) i = 1 Set rng = ws.Rows(1).Find(What:=headerArray(j), LookIn:=xlValues, LookAt:=xlWhole) If Not rng Is Nothing Then For Each cell In rng.Offset(1).Resize(ws.Cells(ws.Rows.Count, rng.Column).End(xlUp).Row).Cells If Not IsEmpty(cell.Value) Then cell.Value = 1005000 + i i = i + 1 End If Next cell End If Next j End Sub Sub ChangeValueToHeaderValue() Dim ws As Worksheet Dim headerArray As Variant ' Create array of headers Dim rng As Range Dim cell As Range Dim i As Integer Dim j As Integer Set ws = ThisWorkbook.Sheets("deface") ' Change your sheet name to deface headerArray = Array("Department", "Description", "extensionAttribute5", "City", "City_1", "Title", "userCertificate") ' array of headers For j = LBound(headerArray) To UBound(headerArray) Set rng = ws.Rows(1).Find(What:=headerArray(j), LookIn:=xlValues, LookAt:=xlWhole) If Not rng Is Nothing Then For Each cell In rng.Offset(1).Resize(ws.Cells(ws.Rows.Count, rng.Column).End(xlUp).Row).Cells If Not IsEmpty(cell.Value) Then cell.Value = headerArray(j) End If Next cell End If Next j End Sub Sub ReplaceEmails() Dim ws As Worksheet Dim headerArray As Variant ' Create array of headers Dim rng As Range Dim cell As Range Dim i As Integer Dim j As Integer Dim atIndex As Integer Dim cellValue As String Set ws = ThisWorkbook.Sheets("deface") ' Change your sheet name to deface headerArray = Array("EmailAddress", "mail", "UserPrincipalName") ' array of headers For j = LBound(headerArray) To UBound(headerArray) i = 1 Set rng = ws.Rows(1).Find(What:=headerArray(j), LookIn:=xlValues, LookAt:=xlWhole) If Not rng Is Nothing Then For Each cell In rng.Offset(1).Resize(ws.Cells(ws.Rows.Count, rng.Column).End(xlUp).Row).Cells If Not IsEmpty(cell.Value) Then cellValue = cell.Value atIndex = InStr(cellValue, "@") If atIndex > 0 And atIndex < Len(cellValue) Then cell.Value = 100500 + i & "@" & Mid(cellValue, atIndex + 1) ' Get all text data after "@" i = i + 1 Else cell.Value = "" ' If "@" is not found or it is in the end of the string i = i + 1 End If End If Next cell End If Next j End Sub Sub CanonicalNameProc() Dim ws As Worksheet Dim rng As Range Dim cell As Range Dim i As Integer Dim cellValue As String Dim lastBackslashIndex As Integer Set ws = ThisWorkbook.Sheets("deface") ' Change your sheet name to deface i = 1 ' processing "CanonicalName" Set rng = ws.Rows(1).Find(What:="CanonicalName", LookIn:=xlValues, LookAt:=xlWhole) If Not rng Is Nothing Then For Each cell In rng.Offset(1).Resize(ws.Cells(ws.Rows.Count, rng.Column).End(xlUp).Row).Cells If Not IsEmpty(cell.Value) Then cellValue = cell.Value lastBackslashIndex = InStrRev(cellValue, "/") ' Cut everything after "/" character If lastBackslashIndex > 0 Then cell.Value = Left(cellValue, lastBackslashIndex - 1) & "/" & 100500 + i End If i = i + 1 Else cell.Value = "" End If Next cell End If End Sub Sub legacyExchangeDNProc() Dim ws As Worksheet Dim rng As Range Dim cell As Range Dim i As Integer Dim cellValue As String Dim lastBackslashIndex As Integer Set ws = ThisWorkbook.Sheets("deface") ' Change your sheet name to deface i = 1 ' processing "legacyExchangeDN" Set rng = ws.Rows(1).Find(What:="legacyExchangeDN", LookIn:=xlValues, LookAt:=xlWhole) If Not rng Is Nothing Then For Each cell In rng.Offset(1).Resize(ws.Cells(ws.Rows.Count, rng.Column).End(xlUp).Row).Cells If Not IsEmpty(cell.Value) Then cellValue = cell.Value lastBackslashIndex = InStrRev(cellValue, "-") ' Cut everything after "-" character If lastBackslashIndex > 0 Then cell.Value = Left(cellValue, lastBackslashIndex - 1) & "-" & 100500 + i End If i = i + 1 Else cell.Value = "" End If Next cell End If End Sub Sub DistinguishedNameProc() Dim ws As Worksheet Dim rng As Range Dim cell As Range Dim i As Integer Dim cellValue As String Dim equalSignIndex As Integer Dim commaIndex As Integer Set ws = ThisWorkbook.Sheets("deface") ' Change your sheet name to deface i = 1 ' processing "DistinguishedName" Set rng = ws.Rows(1).Find(What:="DistinguishedName", LookIn:=xlValues, LookAt:=xlWhole) If Not rng Is Nothing Then For Each cell In rng.Offset(1).Resize(ws.Cells(ws.Rows.Count, rng.Column).End(xlUp).Row).Cells If Not IsEmpty(cell.Value) Then cellValue = cell.Value equalSignIndex = InStr(1, cellValue, "=") ' Find the place of first "=" commaIndex = InStr(equalSignIndex, cellValue, ",") ' Find the place of next ',' If equalSignIndex > 0 And commaIndex > 0 Then cell.Value = Left(cellValue, equalSignIndex) & 100500 + i & Mid(cellValue, commaIndex) End If i = i + 1 Else cell.Value = "" End If Next cell End If End Sub Sub HomeDirectoryClean() Dim ws As Worksheet Dim rng As Range Dim cell As Range Dim cellValue As String Set ws = ThisWorkbook.Sheets("deface") ' Change your sheet name to deface ' processing "HomeDirectory" Set rng = ws.Rows(1).Find(What:="HomeDirectory", LookIn:=xlValues, LookAt:=xlWhole) If Not rng Is Nothing Then For Each cell In rng.Offset(1).Resize(ws.Cells(ws.Rows.Count, rng.Column).End(xlUp).Row).Cells If Not IsEmpty(cell.Value) Then cell.Value = "" End If Next cell End If End Sub
-
Для запуска скрипта переместите курсор на имя функции
Main()
и нажмите кнопку на панели инструментов или клавишу F5.Рис. 5. Запуск скрипта -
Убедитесь, что все требуемые атрибуты обезличены.
-
Сохраните лист как CSV-файл.
Например, нажмите F12 и в раскрывающемся списке в поле Тип файла выберите CSV UTF-8 (разделитель — запятая) (*.csv)
. При этом в итоговом файле в качестве разделителя будет использоваться точка с запятой. -
Убедитесь, что у файла установлена корректная кодировка (например, UTF-8), а в качестве разделителя столбцов используется точка с запятой (
;
).
Удаление пользователей
Перед удалением откройте файл UsersToDelete.txt и еще раз убедитесь в том, что в нем отсутствуют сервисные пользователи (Administrator, Guest и т. п.)! |
-
Для удаления пользователей выполните в терминале Windows PowerShell или среде Windows PowerShell ISE следующую последовательность команд, указав в качестве входного параметра путь к файлу со списком удаляемых пользователей (
path-to-users-to-delete-file
):$Users = Get-Content -Path <path-to-users-to-delete>\UsersToDelete.txt Foreach ($Sser in $Users){ Remove-ADUser -identity $Sser }
Например:
$Users = Get-Content -Path C:\temp\UsersToDelete.txt Foreach ($Sser in $Users){ Remove-ADUser -identity $Sser }
-
Подтвердите необходимость удаления.
-
Убедитесь, что перечисленные в файле пользователи удалены корректно. Например, откройте оснастку Active Directory Users and Computers, выберите имя домена в дереве каталога, выберите Users и выполните визуальную проверку списка пользователей в области просмотра справа.
Изменение срока хранения объектов в корзине
-
Запустите оснастку ADSI Edit (adsiedit.msc).
-
В основном меню нажмите Action, выберите Connect to…, в выпадающем списке Select a well known Naming Context выберите Configuration и в диалоговом окне нажмите OK.
Рис. 6. Выбор контекста именования Configuration для подключения -
В дереве в панели слева выберите Configuration → CN=Configuration → CN=Services → CN=Windows NT → CN=Directory Service. Нажмите правую кнопку мыши на пункте CN=Directory Service и в контекстном меню выберите Properties.
Рис. 7. Путь к атрибуту MSDS-DeletedObjectLifeTime -
В окне свойств дважды щелкните строку с атрибутом
MSDS-DeletedObjectLifeTime
. В диалоговом окне редактора атрибута введите2
в поле ввода и нажмите OK.Рис. 8. Изменение значения атрибута MSDS-DeletedObjectLifeTime -
Нажмите Apply и OK. Закройте оснастку ADSI Editor.
-
Выждите двое суток до полной очистки корзины.
Загрузка обезличенных данных пользователей
-
Загрузите на сервер скрипт или создайте файл import_users.ps1 следующего содержания:
Скрипт для загрузки обезличенных данных пользователей AD
Param ( [string]$path, [string]$UPN, [string]$pass ) $ADUsers = Import-Csv $path -Delimiter ";" # Import active directory module for running AD cmdlets Import-Module ActiveDirectory # Define $password = ConvertTo-SecureString $pass -AsPlainText -Force # Loop through each row containing user details in the CSV file foreach ($User in $ADUsers) { try { # Define the parameters using a hashtable $UserParams = @{ SamAccountName = $User.name UserPrincipalName = "$($User.name)@$UPN" Name = $User.name GivenName = $User.GivenName Surname = $User.Surname Enabled = $True DisplayName = "$($User.GivenName) $($User.Surname)" Path = $User.ou EmailAddress = $User.EmailAddress Title = $User.Title AccountPassword = $password ChangePasswordAtLogon = $False } # Check to see if the user already exists in AD if (Get-ADUser -Filter "SamAccountName -eq '$($User.name)'") { # Give a warning if user exists Write-Host "A user with username $($User.name) already exists in Active Directory." -ForegroundColor Yellow } else { # User does not exist then proceed to create the new user account # Account will be created in the OU provided by the $User.ou variable read from the CSV file New-ADUser @UserParams # If user is created, show message. Write-Host "The user $($User.name) is created." -ForegroundColor Green } } catch { # Handle any errors that occur during account creation Write-Host "Failed to create user $($User.name) - $_" -ForegroundColor Red } }
-
Запустите скрипт в терминале Windows PowerShell:
./import_users.ps1 <path-to-user-list-file> <upn-suffix> <password>
Параметры вызова:
-
path-to-user-list-file
— путь к CSV-файлу с обезличенными данными пользователей; -
upn-suffix
— суффикс UPN для импортируемых пользователей (имя домена); -
password
— пароль, который будет задан для всех импортируемых пользователей.
Например:
./import_users.ps1 C:\temp\UserList.csv testl.lan PasswD123!
Рис. 9. Результат работы скрипта загрузки обезличенных данных пользователей -
Проверка отсутствия персональных и других чувствительных данных
Для проверки может использоваться, например, утилита ldp:
-
Нажмите клавиши Windows + R, наберите в поле ввода название утилиты ldp и нажмите OK.
-
В строке меню выберите Options →Controls, в раскрывающемся списке Load Predefined последовательно выберите
Return deleted objects
иReturn recycled objects
.Рис. 10. Настройка отображения удаленных объектов и объектов, помещенных в корзину, в утилите ldp -
Для подключения по LDAP:
-
в строке меню выберите Connection → Connect и нажмите OK;
-
в строке меню выберите Connection → Bind и нажмите OK.
-
-
Для просмотра ветки с удаленными объектами:
-
в строке меню выберите View → Tree, в выпадающем списке выберите строку
DC=domain,DC=name
и нажмите OK;Рис. 11. Выбор области просмотра дерева -
в дереве каталога раскройте список
DC=domain,DC=name
и выберите веткуCN=DeletedObjects,DC=domain,DC=name
.Рис. 12. Выбор ветки
-
-
Убедитесь, что в ветке отсутствуют записи.