Показаны сообщения с ярлыком Active Directory. Показать все сообщения
Показаны сообщения с ярлыком Active Directory. Показать все сообщения

четверг, 21 июля 2011 г.

Интересно - Невозможно сделать клон работающего контроллера домена Active Directory на ESX.

Недавно при подготовке тестового стенда столкнулся с невозможностью сделать клон контроллера домена, выдавалась ошибка:
Cannot create a quiesced snapshot because the snapshot operation exceeded the time limit for holding off I/O in the frozen virtual machine
а как оказалось в дальнейшем и снапшот. Контроллер домена уже давно был виртуальным. При выяснении этой проблемы с технической поддержкой VmWare, оказалось что действительно есть такая проблема, но она по большей части на стороне Windows(была Windows 2008 R2). Проблема не связана с Volume Shadow Provider и его WMI writers.
Узнать состояние Writer-ов зарегистрированных в системе можно командой
vssadmin list writers
Дело в том, что база Active Directory, расположенная в файле .dit подвержена постоянной нагрузкам по чтению записи и интервал времени необходимый для снятия образа превышает допустимый тайм аут в течении которого в базу .dit не может быть слит лог файл этой базы. В моем случае ошибка выпадала после 10 минут клонирования.

Ссылки по теме:
(причина):
http://social.technet.microsoft.com/Forums/en-US/windowsserver2008r2virtualization/thread/2e913d5c-899b-46b2-88a2-a7bf7a0a584d

(методы борьбы):
http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1018194

вторник, 9 ноября 2010 г.

четверг, 19 августа 2010 г.

Автоматизация создания снапшотов Active Directory на Windows 2008 R2

В интернете нашел несколько статей про такую автоматизацию, но они подошли мне отчасти. Поскольку я поставил задачу со следующими условиями:
1.Делать Snapshot-ы Active Directory ежедневно (Make snapshots per day)
2.Удалять старые Snapshot-ы Active Directory, например, те, которые старше 30 дней.(Delete old snapshot per day)

По тому как создавать снимки Active Directory есть пару не плохих статеек:
http://itew.ru/2009/06/22/518
http://it-professional.at/?p=59

Всё это красиво но как это всё запихнуть в один исполняемый файл, проблема возникает сразу, как только вы попробуете одной командой схранить снапшот ndtsutil и сразу выйти(Утилита NTDSUTIL имеет многоуровневый интерфейс, поэтому команды надо набирать одну за другой), у меня полуилось это сделать так:

Script1(сохранение информации о snapshot-ах - "Active directory snapshots list all to file.bat"):
ntdsutil snapshot "list all">[Path]\snapshots.txt quit quit
результат команды:
ntdsutil: snapshots
napshot: list all
1: 2010/08/19:11:33 {f6910436-b92b-4b6d-b125-8a7b10493887}
2: C: {9f1b44cf-48ed-478c-9552-e0dcffd88210}
3: D: {d1147dde-3db4-4103-ad2e-3942bd6eb109}

4: 2010/08/19:11:33 {1fcd5908-81f2-430c-8610-2a67b3d10daa}
5: C: {1f55b3ed-428a-4d21-9dd4-d6c82c67d510}
6: D: {11ca5468-86c1-46d9-b606-e5f964ab3412}

7: 2010/08/19:11:33 {66d48540-e53d-481a-8f2b-825ade892b14}
8: C: {858e8405-443e-44f4-85e2-148bb3978868}
9: D: {a6e7aab0-e221-4b87-a296-386232618ab1}

10: 2010/08/19:11:34 {e6752416-0534-48a5-8c5e-ed469f63446a}
11: C: {25b607bb-9303-4f1b-9c1f-588bb02d1700}
12: D: {5d340d1a-852c-46c1-9386-ad55235abc21}


Сама автоматизация сводиться к трем файлам(у меня получилось, так, может у кого то будет более изящное решение - через один файл):
Script1(Executor_SnapshotProcessing.bat):
@SET FILENAME="[Path]\snapshots.txt"
@SET FILENAME2="[Path]\2_1_PS_script_snapshot_delete.ps1"

del %FILENAME%ntdsutil snapshot "list all">%FILENAME% quit quit
C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe -executionpolicy unrestricted -file %FILENAME2%


ntdsutil snapshot "activate instance ntds" create quit quit


Script2(2_1_PS_script_snapshot_delete.ps1):
$fileNameSource="[Path]\snapshots.txt"
$fileNameTarget="[Path]\snapshots2.txt"
$fileNameBAT_DeleterSnapshot="[Path]\2_2_Active_directory_snapshot_delete.bat"
$a=get-content $fileNameSource select-string " 1: "$SnapShotID=$("$a".split(" "))[3]
&$fileNameBAT_DeleterSnapshot $SnapShotID

Script3(2_2_Active_directory_snapshot_delete.bat):
ntdsutil snapshot "delete %1" quit quit

Запускной файл Script1, результат команды:
Executor_SnapshotProcessing.bat
del "[Path]\snapshots.txt"
ntdsutil snapshot "list all" quit quit 1>"[Path]\snapshots.txt"
C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe -executionpolicy
unrestricted -file "[Path]\2_1_PS_script_snapshot_delete.ps1"

only insert string like: delete {eaa5ac99-bf3d-4145-85a8-3a65a7b75702}
ntdsutil snapshot "delete {f6910436-b92b-4b6d-b125-8a7b10493887}" quit quit
ntdsutil: snapshot
snapshot: delete {f6910436-b92b-4b6d-b125-8a7b10493887}
Snapshot {9f1b44cf-48ed-478c-9552-e0dcffd88210} deleted.
Snapshot {d1147dde-3db4-4103-ad2e-3942bd6eb109} deleted.
snapshot: quit
ntdsutil: quit
ntdsutil snapshot "activate instance ntds" create quit quit
ntdsutil: snapshot
snapshot: activate instance ntds
Active instance set to "ntds".
snapshot: create
Creating snapshot...
Snapshot set {a6c5dd08-a38f-47e1-b2c6-5eadf1f46c36} generated successfully.
snapshot: quit
ntdsutil: quit


Далле шедулим Script1 и всё - мы получили скрипт, который удаляет самый давний снапшот Active Directory и делает новый. Но мы не получили хранение тех самых 30 снопшотов ежедневных, которые мы хотим создавать - хранить и удалять через 30 дней.
Для этого нужно до шедулинга скрипта 1 просто напросто их создать. Для этих целей можно создать bat-файл и просто выполнить 30 раз или 30 команд в одном файле bat-файле:

ntdsutil snapshot "activate instance ntds" create quit quit

В PowerShell
помогла ссылка:
http://social.technet.microsoft.com/Forums/ru-RU/scrlangru/thread/14eeebc9-5227-4416-91c6-de730b7630ed

полезные ссылки по PowerShell:

http://sites.google.com/site/lebedevum/voprosy-i-otvety/windows-powershell/windows-powershell-i-komandnaa-stroka-windows

http://window.edu.ru/window_catalog/pdf2txt?p_id=31200&p_page=5

http://www.osp.ru/text/print/302/5560256.html

четверг, 22 июля 2010 г.

Вытаскивание информации из Active Directory по пользователям на WMI и WHS

Перед тем как выполнять скрипт необходимо поправить строку:
Str_LDAP= "LDAP://CN="& StrGroupName &",OU=ASU,OU=Contora,DC=corp,DC=domain,DC=ru"
под свои нужды.
Для выполнения скрипта в домене и сбора множественной информации привелегии не нужны, можно выполнять из-под рядового пользователя домена. Я бы сказал, что это шпионский скрипт )))
содержимое файла .vbs(работает из под Windows XP в доменах с уровнями домена и леса: Windows 2003, Windows 2008, Windows 2008 R2):

'***************************************************************
'Getting information about users from Active Directory
'***************************************************************
' НАЧАЛО ФРАГМЕНТА A
Dim objArgs, strGroupDN, StrGroupName, MyFileName1, Str_LDAP
set objArgs = WScript.Arguments
StrGroupName = "ALL Users"
Str_LDAP= "LDAP://CN="& StrGroupName &",OU=ASU,OU=Contora,DC=corp,DC=domain,DC=ru"
if objArgs.Count <> 1 then
Dim objRootDSE
set objRootDSE = GetObject("LDAP://RootDSE")
strGroupDN = Str_LDAP '& objRootDSE.Get("defaultNamingContext")
Else
strGroupDN = objArgs.Item(0)
end if
' КОНЕЦ ФРАГМЕНТА A
MyFileName1 = GetScriptDirectory & "Члены группы - " & StrGroupName & ".txt"
'***************************************************************
' НАЧАЛО ФРАГМЕНТА B
Dim dicSeenGroupMember
set dicSeenGroupMember = CreateObject("Scripting.Dictionary")
FuncAppendOneStrToTXTFile MyFileName1, "Members of " & strGroupDN & ":"
DisplayMembers strGroupDN, " ", dicSeenGroupMember
Wscript.Echo "Сбор данных о членах группы <" & StrGroupName & "> - завершен" & Chr(10) & "Отчет находится в файле " & MyFileName1 & Chr(10) & "The End"
' КОНЕЦ ФРАГМЕНТА B
'***************************************************************
'----------------функция----------------------------------------
Function DisplayMembers (strGroupADsPath, strSpaces, dicSeenGroupMember)

FuncAppendOneStrToTXTFile MyFileName1,"ФИО" & vbTab & "CanonicalName" & vbTab & "userPrincipalName" & vbTab & "LDAP" & vbTab & "OU Native" & vbTab & "phisicalDeliveryOfficeName" & vbTab & "Description" & vbTab & "Mail" & vbTab & "scriptPath" & vbTab & "homeDirectory" & vbTab & "homeDrive" & vbTab & "telephoneNumber" & vbTab & "homeMDB" & vbTab & "logonCount" & vbTab & "lastLogon" & vbTab & "whenCreated" & vbTab & "UserAccountControl" & vbTab & "badPwdCount" & vbTab & "badPasswordTime" & vbTab & "pwdLastSet" & vbTab & "msNPAllowDialin" & vbTab & "msRTCSIP-PrimaryUserAddress" & vbTab & "msRTCSIP-LineServer" & vbTab & "msRTCSIP-Line"
Dim objGroup, objMember, oG, Obj, UserObj
set objGroup = GetObject(strGroupADsPath)
for each objMember In objGroup.Members
FuncAppendOneStrToTXTFile MyFileName1, GetToFileOneCNFromAD(objMember.Get("distinguishedname"))
if objMember.Class = "group" then
if dicSeenGroupMember.Exists(objMember.ADsPath) then
Wscript.Echo strSpaces & " ^ already seen group member " & "(stopping to avoid loop)"
FuncAppendOneStrToTXTFile MyFileName1, strSpaces & " ^ already seen group member " & "(stopping to avoid loop)"
else
dicSeenGroupMember.Add objMember.ADsPath, 1
DisplayMembers objMember.ADsPath, strSpaces & " ", dicSeenGroupMember
end if
end if
Next
End Function
'----------------функция----------------------------------------
Function GetToFileOneCNFromAD(StrLDAP)
GetToFileOneCNFromAD = ""
'-------- результат запроса возвращаем в переменную oGroup
Set Obj = GetObject("LDAP://" & StrLDAP)
On Error Resume Next
OU_Native = Mid(Obj.ADsPath, InStr(1,Obj.ADsPath, "OU"))
if (Err.Number = 0) Then
OU_Native = Mid(Obj.ADsPath, InStr(1,Obj.ADsPath, "OU"))
Else
OU_Native = Obj.ADsPath
Err.Clear
End If
GetToFileOneCNFromAD = Mid(Obj.Name,4,Len(Obj.Name)-3) & vbTab & Obj.Name & vbTab & Obj.userPrincipalName & vbTab & Obj.ADsPath & vbTab & OU_Native & vbTab & Obj.physicalDeliveryOfficeName & vbTab & Obj.description & vbTab & Obj.mail & vbTab & Obj.scriptPath & vbTab & Obj.homeDirectory & vbTab & Obj.homeDrive & vbTab & Obj.telephoneNumber & vbTab & Obj.homeMDB & vbTab & Obj.logonCount & vbTab & FuncConvertTimeStamp( FuncConvertTime(Obj.lastLogon) ) & vbTab & Obj.whenCreated & vbTab & Obj.UserAccountControl & vbTab & Obj.badPwdCount & vbTab & FuncConvertTimeStamp( FuncConvertTime(Obj.badPasswordTime)) & vbTab & FuncConvertTimeStamp( FuncConvertTime(Obj.pwdLastSet)) & vbTab & Obj.msNPAllowDialin & vbTab & GetSIPContact(Obj)
' GetToFileOneCNFromAD = Mid(Obj.Name,4,Len(Obj.Name)-3) & vbTab & Obj.Name & vbTab & Obj.userPrincipalName & vbTab & Obj.ADsPath & vbTab & OU_Native & vbTab & Obj.physicalDeliveryOfficeName & vbTab & Obj.description & vbTab & Obj.mail & vbTab & Obj.scriptPath & vbTab & Obj.homeDirectory & vbTab & Obj.homeDrive & vbTab & Obj.telephoneNumber & vbTab & Obj.homeMDB & vbTab & Obj.logonCount & vbTab & FuncConvertTimeStamp( FuncConvertTime(Obj.lastLogon) ) & vbTab & Obj.whenCreated & vbTab & Obj.UserAccountControl & vbTab & Obj.badPwdCount & vbTab & FuncConvertTimeStamp( FuncConvertTime(Obj.badPasswordTime)) & vbTab & FuncConvertTimeStamp( FuncConvertTime(Obj.pwdLastSet)) & vbTab & GetSIPContact(Obj)
' GetToFileOneCNFromAD = Mid(Obj.Name,4,Len(Obj.Name)-3) & vbTab & Obj.Name & vbTab & Obj.userPrincipalName & vbTab & Obj.ADsPath & vbTab & Obj.physicalDeliveryOfficeName & vbTab & Obj.description & vbTab & Obj.mail & vbTab & Obj.scriptPath & vbTab & Obj.homeDirectory & vbTab & Obj.homeDrive & vbTab & Obj.telephoneNumber & vbTab & Obj.homeMDB & vbTab & Obj.logonCount & vbTab & FuncConvertTimeStamp( FuncConvertTime(Obj.lastLogon) ) & vbTab & Obj.whenCreated & vbTab & Obj.UserAccountControl & vbTab & Obj.badPwdCount & vbTab & FuncConvertTimeStamp( FuncConvertTime(Obj.badPasswordTime)) & vbTab & FuncConvertTimeStamp( FuncConvertTime(Obj.pwdLastSet)) & vbTab & GetSIPContact(Obj)
End Function
'----------------функция----------------------------------------
'---функция берет информацию об SIP свойствах учетных записей --
Function GetSIPContact( objUser)
On Error Resume Next
objUser.Get("msRTCSIP-PrimaryUserAddress")
if (Err.Number = 0) Then
SIPName=objUser.Get("msRTCSIP-PrimaryUserAddress") & vbTab & objUser.Get("msRTCSIP-LineServer") & vbTab & objUser.Get("msRTCSIP-Line")
MyResult = SIPName
Else
GetSIPContact = ""
Err.Clear
MyResult = vbTab & vbTab & vbTab
End If
GetSIPContact = MyResult

End Function
'----------------функция----------------------------------------
'добавляет строчку в текстовый файл
Function FuncAppendOneStrToTXTFile(FileName, StrText)
'------------------------Константы для задания типа открытия файла
Const ForReading = 1, ForWriting = 2, ForAppending = 8, OverwriteTrue = True, OverwriteFalse = False
' Объявляем переменные
Dim objFSO, FOut
' Создаем объект FileSystemObject
Set objFSO=WScript.CreateObject("Scripting.FileSystemObject")
' Открываем выходной файл для записи
Set FOut = objFSO.OpenTextFile (FileName,ForAppending,true)
' Записываем текстовую строку в файл
FOut.WriteLine StrText' & vbcrlf
' Закрываем выходной файл
FOut.Close
FuncAppendOneStrToTXTFile = true
End Function
'----------------функция----------------------------------------
'создает txt - файл 'файл не должен быть создан
Function FuncCreateTXTFile(FileName)
'------------------------Константы для задания типа открытия файла
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Const OverwriteTrue = True, OverwriteFalse = False, UnicodeTrue = True, UnicodeFalse = False
Const ReadOnlyDeletionTrue = True, ReadOnlyDeletionFalse = False
' Объявляем переменные
Dim objFSO, FOut
' Создаем объект FileSystemObject
Set objFSO=WScript.CreateObject("Scripting.FileSystemObject")
' Открываем выходной файл для записи
Dim File
Set File = objFSO.CreateTextFile(FileName, OverwriteTrue,UnicodeFalse)
' Закрываем выходной файл
FuncCreateTXTFile = true
End Function
'----------------функция----------------------------------------
Function GetScriptDirectory()
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
GetScriptDirectory = Mid(WScript.ScriptFullName,1,Len(WScript.ScriptFullName)-Len(WScript.ScriptName))
End Function
'----------------функция----------------------------------------
'функция преобразует дату из числового формата в нормальный
Function FuncConvertTime(x)
Dim StrResult, objShell
' Получение настроек о зонах времени из регистра
Set objShell = CreateObject("Wscript.Shell")
lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\" & "TimeZoneInformation\ActiveTimeBias")
If UCase(TypeName(lngBiasKey)) = "LONG" Then
lngBias = lngBiasKey
ElseIf UCase(TypeName(lngBiasKey)) = "VARIANT()" Then
lngBias = 0
For k = 0 To UBound(lngBiasKey)
lngBias = lngBias + (lngBiasKey(k) * 256^k)
Next
End If
On Error Resume Next
Set objDate = x'lastLogon'lngDate
If Err.Number <> 0 Then
On Error GoTo 0
dtmDate = #1/1/1601#
Else
On Error GoTo 0
lngHigh = objDate.HighPart
lngLow = objDate.LowPart
If lngLow <>
lngHigh = lngHigh + 1
End If
If (lngHigh = 0) And (lngLow = 0 ) Then
StrResult = #1/1/1601#
Else
StrResult = #1/1/1601# + (((lngHigh * (2 ^ 32)) + lngLow)/600000000 - lngBias)/1440
End If
End If
'WScript.Echo StrResult
FuncConvertTime = StrResult
End Function
'----------------функция----------------------------------------
'функция преобразует TimeStamp возвращенный функцией FuncConvertTime(x) в поддающийся сортировке TimeStamp
Function FuncConvertTimeStamp(x)
Dim y,z
y = ""
If ( Len(x)>0 ) Then
'проверка на наличие времени в TimeStamp
If (Len(x) > 11) Then
z = Mid(x,12,Len(x)-11)
End If
'преобразование TimeStamp
If Mid(x,13,1) = ":" Then
y = Mid(x,7,4) & "." & Mid(x,4,2) & "." & Mid(x,1,2) & " " & "0" & z
Else
y = Mid(x,7,4) & "." & Mid(x,4,2) & "." & Mid(x,1,2) & " " & z
End If
'y = Mid(x,7,4) & "." & Mid(x,4,2) & "." & Mid(x,1,2) & "." & Mid() & "." & Mid() & "." & Mid()
End If
FuncConvertTimeStamp = y
End Function


Конечно, теперь есть и другое решение:
http://shss.wordpress.com/2010/07/08/ad-add-telephone-numbers-using-excel-application-as-data-soutce/

просто мой скрипт писался, когда ещё не было Power Shell

среда, 21 июля 2010 г.

Удаление почтового сообщения из почтовых ящиков Microsoft Exchange 2007 скриптом Exchange Power Shell

Возникла необходимость удалить, разосланное всем сообщение из почтовых ящиков пользователей, для этих целей использовал скрипт на Exchange Power Shell:

содержимое файла скрипта "Delete message from many mailboxes.ps1":

#переменная имени файла
$File_Name="D:\MailboxList.txt"
#заполняем массив строками из файла
$mass=Get-Content $File_Name
#админская учетка
$Admin_username="NETBIOSDOMAINNAME\Admin_Exch"
#параметры поиска для удаления письма
#текст в письме
$Text_ContentKeywords="Бла, бла, бла."
#имя вложения
$Text_AttachmentFilenames="Список.xls"
#дата начала поиска
$Text_StartDate="20/07/2010 14:00:00"
#цикл перебора строк из файла
foreach($string in $mass)
{
#присваиваем переменной имени пользователя строку из файла
$user_mailbox=$string
#добавляем права адмиской учетке на ящик
Add-MailboxPermission -identity $user_mailbox -Accessrights FULLACCESS -User $Admin_username
#Удаляем элемент из почтового ящика
Export-Mailbox -Identity $user_mailbox -ContentKeywords $Text_ContentKeywords -AttachmentFilenames $Text_AttachmentFilenames -StartDate $Text_StartDate -DeleteContent -Confirm:$false
}

поскольку файл с почтовыми ящиками содержал >1200 записей - разбил его на 3 части(надо было на большее число частей, что бы ещё быстрее) и запустил на разных серверах Exchange 2007.

Нагрузка(Workload) на 4х процессорный сервер(активная нода CCR кластера почтовых ящиков) с Xeon 3ГГц процессорами была в районе 50%, нагрузка на диски была не большаяпри этом был RAID5 на 4х дисках, а общий объем занимаемый базами почтовых ящиков был чуть больше 320Гб. По памяти на ноде было 16Гб RAM.

Надо сказать, что сообщение, подлежащее удалению, было отозвано отправителем через 40 минут, и ему стали сыпаться уведомления о недоставке. Мы сформировали список пользователей из письма, которым было отправлено это почтовое сообщение (делали в excel), исключили из него тех, у кого сообщение было успешно отозвано(ждали ночное время), и, вытащив из Active Directory имена пользователей (distinguishedname) с логинами(LoginName) и именами почтовых ящиков (mail) (как это делается см. следующий пост) сопоставили через Acces c теми, у кого почта была не отозвана, получив таким образом список почтовых ящиков из которых необходимо было удалить злополучное письмо в виде текстового файла (в скрипте это переменная $File_Name).

Из работы скрипта, а точнее команды Export-Mailbox не понравилось то, что она не ищет во вложенных папках, т.е. если пользователь в Microsoft Outlook клиенте у себя в папке Входящие(Inbox), например, создал еще какую-то папку, и искомое письмо оказалось в ней, то оно не будет удалено скриптом, в том виде скрипта в каком он указан в настоящий момент. Хоть у команды Export-Mailbox и есть ключ -IncludeFolders он не позволяет указывать маску поиска подпапок, а только перечислять конкретные имена папок(проверено).

Кстати, поначалу тоже столкнулся с ошибкой:

The export-mailbox task for mailbox 'test test' failed.

Error: Failed to copy messages to the destination mailbox store with error:

MAPI or an unspecified service provider.

ID no: 00000000-0000-00000000, error code: -1056749164

Даже мысли не возникло, с подозрением на нехватку прав на почтовый ящик, поскольку пользователь из-под которого это всё запускалось был в группах DomainAdmin, Exchange Administrator, Enterprise Administrator, но как оказалось без строки в коде:

#добавляем права адмиской учетке на ящик
Add-MailboxPermission -identity $user_mailbox -Accessrights FULLACCESS -User $Admin_username

Это не работает, всё-равно.

Полезные ссылки:
http://shss.wordpress.com/2010/07/08/ad-add-telephone-numbers-using-excel-application-as-data-soutce/
http://blogs.sysfaq.ru/powershell/category/learn/page/2/
http://window.edu.ru/window_catalog/pdf2txt?p_id=31200&p_page=5
http://mcp.su/2009/09/powershell-exchange-2007-ad/
http://technet.microsoft.com/ru-ru/library/bb676491(EXCHG.80).aspx
http://www.intuit.ru/department/os/compromtwin/19/2.html
http://www.osp.ru/win2000/2007/03/4245842/
http://sysadmins.ru/topic265273.html
http://www.osp.ru/win2000/2007/03/4245842/
http://www.exchangeinbox.com/article.aspx?i=102

четверг, 15 июля 2010 г.

Удаление группы First Storage Group от Exchange 2003 в организации Exchange через ADSIEdit

Удаление группы First Storage Group от Exchange 2003 в организации Exchange 2007.

Этот последний этап возникает, когда корректно не удаляется Exchange 2003 Server с сервера, на котором он был установлен. У нас возник как раз такой случай, мы долго думали - около 2х лет, делать это или нет и вот решились. Благо накануне повысил уровни домена и леса Active Directory c Windows 2008 до Windows 2008 R2. и за день освоил механизм снапшотов Active Directory, благодаря нескольким статьям:
на русском
http://itew.ru/2009/06/22/518
http://itew.ru/2009/06/23/531
http://itew.ru/2009/06/26/567
http://itew.ru/2009/07/11/653
http://itew.ru/2009/06/27/585
на Engish.
http://www.petri.co.il/recovering-deleted-items-active-directory.htm
http://www.petri.co.il/working-active-directory-snapshots-windows-server-2008.htm
http://www.petri.co.il/exporting-active-directory-snapshots-windows-server-2008.htm
и использовал программу DSCT:
http://www.petri.co.il/directory-service-comparison-tool.htm
http://lindstrom.nullsession.com/?page_id=11
или
http://lindstrom.nullsession.com/?cat=3
юзал DSCT 2.0 Beta 3

Надо сказать что Microsoft таки не сделал конфетку своими снапшотами. Механизм восстановления объектов остается очень не удобным, по крайней мере, при использовании средства DSCT, а оно не является разработкой MS, на сколько я понял, объект остается всё-равно isDeleted, пока при помощи LDP.exe не переименуешь его и не удалишь параметр isDeleted, но через неё удобнее восстанавливать различные значения параметров и сравнивать между собой снимок и текущие значения параметров для объектов в Active Directory после изменения.

Так вот, возвращаясь к Exchange, перед началом действий в ADSIEdit в:

CN=Administrative Groups,CN=Kaustik,CN=Microsoft,Exchange,CN=Services, CN=Configuration,DC=corp,DC=ru
отображались две административные группы:
CN=Exchange Administrative Group (FYDIBOHF23SPDLT)
и
CN=First Administrative Group

и, собственно, 2-я была лишняя - это наследие Exchange 2003.Долго думая удали её...

Благо был конец рабочего дня и пользователи не успели выпить озверину....
Вообще минут через 10 у пользователей на Microsoft Outlook -ах 2003 при запуске оного стало возникать сообщение:

(Используемая вами версия Outlook заблокирована администратором сервера Microsoft Exchange Server. Обратитесь к администратору. )

Причем, поголовно у всех пользователей Microsoft Outlook 2003, после чего, нажав на Ok он не подключался к Exchange.

Проконсультировавшись с мега-специалистом, пришел к выводу, что удалил некий дочерний объект внутри контейнера CN=First Administrative Group c именем CN=Folder Hierarchies, который был нужен для работы хранилищ общих папок (Public Folders) на сервере Exchange 2007. После удаления на сервере Exchange 2007 стала появляться ошибка хранилища общих папок:

--------------------------------------------------------
Microsoft Exchange Warning
--------------------------------------------------------
The following warning(s) were reported while loading topology information:

get-PublicFolderDatabase
Completed

Warning:
Object MailCluster-01\Ex2k7_01stSG_Public_Folders\Ex2k7_01stSG_Public_Folders_Database has been corrupted and it is in an inconsistent state. The following validation errors have occurred:

Warning:
PublicFolderHierarchy is mandatory.

Warning:
PublicFolderHierarchy is mandatory.
--------------------------------------------------------
OK
--------------------------------------------------------


Собственно MS Outlook 2003 не может работать без хранилищ общих папок. В этом вся причина неурядиц, в то время как пользователи MS Outlook 2007 преспокойно продолжали работать ничего не замечая.

Я начал танцевать от восстановления объекта CN=Folder Hierarchies, сразу скажу это не верный путь в данном случае (IMHO). Потратив пару часов(помогла статья - делал в первый раз), но восстановив объект CN=Folder Hierarchies и его дочерний объект Public Folder я так и не получил работающих клиентов MS Outlook 2003, думаю просто надо было перезагрузить сервер(а) MS Exchangek 2007 (на самом деле у нас их 3штуки: на 2х развернут CCR кластер на 3-м все остальные роли HUB+CAS...), но даже если бы и заработало мы не получаем требуемого результата в ADSIEdit.msc всё-равно остается мусор от MS Exchange 2003. Я отказался от этого пути

Попробовал пойти от ошибки описанной выше, и сразу же натолкнулся на решение:

http://social.technet.microsoft.com/Forums/en-US/exchangesvravailabilityandisasterrecovery/thread/35769dc6-1b32-4409-a2c2-38d1de37db01

опишу что делал:
1.открываем на контроллере домена adsiedit.msc
2.выбираем:
Configuration->Configuration->Services->Microsoft Exchange-> Organization_Exchange_Name->Administrative Groups->Exchange Administrative Group(in my case CN=Exchange Administrative Group (FYDIBOHF23SPDLT))
3.правой кнопкой на нашей административной группе, в моем случае это была "CN=Exchange Administrative Group (FYDIBOHF23SPDLT)"
4.Выбрать создание нового объекта
5.Выбрать класс создаваемого объекта msExchPublicFolderTreeContainer и нажать Next
6.Ввести значение в поле value: "Folder Hierarchies" и нажать Next
7.Нажать Finish

теперь создаем объект Public Folder как дочерний

1.Правой кнопкой на CN=Folder Hierarchies -> создать новый объект.
2.Класс объекта должен быть msExchPFTree
3.Ввести значение в поле value: "Public Folders" и нажать Next
4.Нажать на кнопку "More Attrobutes", выбрать параметр msExchPFTreeType и задать ему значение = 1, это означает, что это будет MAPI Tree
5.Нажать Finish

теперь необходимо во всех базах хранилищ общих папок выставить свойство.
0.Заходим в свойство вновь созданного объекта "Public Folders" через ADSIEdit.msc и копируем значение параметра distinguishedname, далее нажимаем Cancel.
1.заходим в административную группу CN=Exchange Administrative Group (FYDIBOHF23SPDLT)
2.Далее переходим на CN=Servers
3.Выбираем поочередно каждый сервер на котором есть хранилище общих папок, и заходим в CN=InformationStore
4.Далее выбираем хранилище общих папок, а в нем в правом окне заходим в свойства дочернего объекта - базы данных хранилища общих папок.
5.Находим свойство msExchOwningPFTree и вставляем сюда скопированное и нажимаем Ok.
6.Перезапускаем все сервера Exchange 2007.

После того, как сервера загрузятся всё должно работать.
У меня был Exchange 2007 в версии SP1 RollUp 9.

На всё про всё у меня ушло 3,5 часа с проверками многочисленных клиентов MS Outlook 2003, а можно было управиться и за 20 минут, если считать перезагрузку серверов.

среда, 12 мая 2010 г.

Про роли FSMO в Active Directory

Про роли AD можно почитать здесь. Про Размещение и оптимизация FSMO на контроллерах домена Active Directory можно почитать здесь . Про аудит учетных записей можно почитать здесь.
Выполнение команды netdom query FSMO показывает распределение 5-ти ролей Active Directory между контроллерами домена.
Командой repadmin /showrepl проверяем репликацию между контроллерами домена.
Всю информацию по передаче ролей можно найти здесь
Передача роли хозяина именования домена
1. Нажмите кнопку Пуск и выберите последовательно пункты Программы, Администрирование и Active Directory — домены и доверие.
2. Щелкните правой кнопкой мыши значок Active Directory — домены и доверие и выберите команду Подключение к контроллеру домена. Примечание. Это действие необходимо выполнить, если вы находитесь не на контроллере домена, которому будет передана роль. Если вы подключены к контроллеру домена, чья роль будет передана, выполнять это действие не нужно.
3. Выберите контроллер домена, которому будет передана роль, и нажмите кнопку ОК.
4. Щелкните правой кнопкой мыши компонент Active Directory — домены и доверие и выберите команду Хозяева операций.
5. В диалоговом окне Изменение хозяина операций нажмите кнопку Изменить.
6. Нажмите кнопку OK для подтверждения передачи роли.
7. Нажмите кнопку ОК.
8. Нажмите кнопку Отмена, чтобы закрыть диалоговое окно.

Передача ролей, существующих отдельно для каждого домена: хозяин RID, основной контроллер домена и хозяин инфраструктуры
1. Нажмите кнопку Пуск и выберите команды Программы, Администрирование и Active Directory — пользователи и компьютеры.
2. Щелкните правой кнопкой мыши значок рядом с Active Directory — пользователи и компьютеры и выберите команду Подключение к контроллеру домена. Примечание. Это действие необходимо выполнить, если вы находитесь не на контроллере домена, которому будет передана роль. Если вы подключены к контроллеру домена, чья роль будет передана, выполнять это действие не нужно.
3. Выберите контроллер домена, которому будет передана роль, и нажмите кнопку ОК.
4. Щелкните правой кнопкой компонент Active Directory — пользователи и компьютеры и выберите команду Хозяева операций.
5. В диалоговом окне Изменение хозяина операций выберите для роли, которая будет передаваться, соответствующую вкладку (RID, PDC или Инфраструктура).
6. В диалоговом окне Изменение хозяина операций нажмите кнопку Изменить.
7. Нажмите кнопку OK для подтверждения передачи роли.
8. Нажмите кнопку ОК.
9. Нажмите кнопку Отмена, чтобы закрыть диалоговое окно.
Передача роли хозяина схемы
Для передачи этой роли можно воспользоваться специальным инструментом. Чтобы включить этот инструмент в качестве оснастки в состав консоли управления, необходимо зарегистрировать библиотеку Schmmgmt.dll.

Регистрация инструмента передачи
1. Нажмите кнопку Пуск и выберите команду Выполнить.
2. Введите команду regsvr32 schmmgmt.dll и нажмите кнопку OK. После успешного выполнения регистрации появится соответствующее сообщение.
Передача роли хозяина схемы
1. Нажмите кнопку Пуск, выберите команду Выполнить, введите mmc и нажмите кнопку OK.
2. В меню Консоль выберите команду Добавить или удалить оснастку.
3. Нажмите кнопку Добавить.
4. Выделите оснастку Схема Active Directory.
5. Нажмите кнопку Добавить.
6. Нажмите кнопку Закрыть, чтобы закрыть диалоговое окно Добавить изолированную оснастку.
7. Для добавления оснастки в состав консоли нажмите кнопку ОК.
8. Щелкните правой кнопкой мыши значок Схема Active Directory и выберите команду Изменение контроллера домена. Примечание. Это действие необходимо выполнить, если вы находитесь не на контроллере домена, которому будет передана роль. Если вы подключены к контроллеру домена, чья роль будет передана, выполнять это действие не нужно.
9. В поле Укажите контроллер домена введите имя контроллера домена, которому присваивается роль, и нажмите кнопку ОК.
10. Щелкните правой кнопкой мыши пункт Схема Active Directory и выберите в меню команду Хозяева операций.
11. В диалоговом окне Смена хозяина схемы нажмите кнопку Изменить.
12. Нажмите кнопку ОК.
13. Нажмите кнопку ОК.
14. Нажмите кнопку Отмена, чтобы закрыть диалоговое окно.

среда, 24 марта 2010 г.

Грабли Exchange 2007 - удаление пользователя, а не ящика

Как и любой администратор Exchange 2007, привыкший к интерфейсу Exchange 2003, натогкнулся на следующие грабли, с учетом что я знал о них. И так:
Необходимо было переподключить почтовый ящик с одного пользователя на другой (что делалось уже не одно кратно). Вместо этого была удалена пользовательская учетная запись целеком. Потому как операция удаления на учетной записи через Exchange Management Shell удаляет не почтовый ящик, а учетную запись пользователя целиком. Что же делать!?
сразу скажу очень помогла статья:
Быстрое восстановление случайно удаленных объектов Active Directory
Сразу не понял что мне это не поможет и не нужно, поскольку пользователя мне нужно было удалить и так, а нужен был лишь почтовый ящик его(целевой почтовый ящик). Просто почтовый ящик долго не появлялся (около часа) в Disconnected mailbox. Поэтому:
  • Восстановил учетную запись пользователя из удаленных объектов ActiveDirectory, думая что это ускорит процесс появления удаленного почтового ящика в Disconnected mailbox. (помогла утилита AdRestore.NET читаем здесь и здесь, берем здесь)
  • Нашел команду для Exchange Power Shell для ускорения вычистки хранилища:
    Clean-MailboxDatabase "mailcluster-01.corp.domain.ru\Ex2k7_06thSG_300Limit_Database"
    после чего удаленный почтовый ящик сразу появился в Disconnected mailbox.
  • Прицепил ввостановленный почтовый ящик к совершенно новой учетной записи Active Directory. И назначил SMTP адрес, он автоматом не назначался.
При попытках подключиться к почтовому ящику из Outlook 2003 получаем ошибку(панель управления-почта и т.д. настраиваем на Exchange):
"Не удается открыть указанное хранилище по умолчанию. Убедитесь, что к нему имеется доступ, и повторите попытку." При изменении настройки "Размещать новую почту в" и направлении на файл данных .pst все нормально, но нам оно не надо.
Точно также нет доступа через OWA:
"При попытке использование почтового ящика произошла ошибка. обратитесь в службу технической поддержки организации."
Сведения об ошибке:
RequestUrl: https://mail-ht-01.corp.domain.ru:443/owa/lang.owaUser host address: 10.1.233.229
ExceptionException type: Microsoft.Exchange.Data.Storage.MailboxUnavailableExceptionException message: Cannot open mailbox /o=ExchangeOrganization/ou=first administrative group/cn=recipients/cn=Username.fi.
Call stack
Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString, Boolean secondTry) Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString, Boolean secondTry) Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString) Microsoft.Exchange.Data.Storage.MailboxSession.Initialize(LogonType logonType, ExchangePrincipal owner, DelegateLogonUser delegateUser, Object identity, OpenMailboxSessionFlags flags) Microsoft.Exchange.Data.Storage.MailboxSession.CreateMailboxSession(LogonType logonType, ExchangePrincipal owner, DelegateLogonUser delegateUser, Object identity, OpenMailboxSessionFlags flags, CultureInfo cultureInfo, String clientInfoString) Microsoft.Exchange.Data.Storage.MailboxSession.Open(ExchangePrincipal mailboxOwner, WindowsPrincipal authenticatedUser, CultureInfo cultureInfo, String clientInfoString) Microsoft.Exchange.Clients.Owa.Core.OwaWindowsIdentity.CreateMailboxSession(ExchangePrincipal exchangePrincipal, CultureInfo cultureInfo) Microsoft.Exchange.Clients.Owa.Core.RequestDispatcher.DispatchLanguagePostLocally(OwaContext owaContext, OwaIdentity logonIdentity, CultureInfo culture, String timeZoneKeyName, Boolean isOptimized) Microsoft.Exchange.Clients.Owa.Core.RequestDispatcher.DispatchLanguagePostRequest(OwaContext owaContext) Microsoft.Exchange.Clients.Owa.Core.RequestDispatcher.PrepareRequestWithoutSession(OwaContext owaContext, UserContextCookie userContextCookie) Microsoft.Exchange.Clients.Owa.Core.RequestDispatcher.InternalDispatchRequest(OwaContext owaContext) Microsoft.Exchange.Clients.Owa.Core.RequestDispatcher.DispatchRequest(OwaContext owaContext) System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Inner ExceptionException type: Microsoft.Mapi.MapiExceptionUnknownUserException message: MapiExceptionUnknownUser: Unable to open message store. (hr=0x80004005, ec=1003) Diagnostic context: Lid: 18969 EcDoRpcExt2 called [length=821] Lid: 27161 EcDoRpcExt2 returned [ec=0x0][length=172][latency=0] Lid: 23226 --- ROP Parse Start --- Lid: 27962 ROP: ropLogon [254] Lid: 17082 ROP Error: 0x3EB Lid: 26937 Lid: 21921 StoreEc: 0x3EB Lid: 27962 ROP: ropExtendedError [250] Lid: 1494 ---- Remote Context Beg ---- Lid: 26426 ROP: ropLogon [254] Lid: 22086 Lid: 23110 Lid: 17990 Lid: 16966 StoreEc: 0x8004010F Lid: 22086 Lid: 23110 Lid: 17990 Lid: 16966 StoreEc: 0x8004010F Lid: 32457 StoreEc: 0x3EB Lid: 23241 StoreEc: 0x3EB Lid: 32186 Lid: 8620 StoreEc: 0x3EB Lid: 1750 ---- Remote Context End ---- Lid: 26849 Lid: 21817 ROP Failure: 0x3EB Lid: 26297 Lid: 16585 StoreEc: 0x3EB Lid: 32441 Lid: 1706 StoreEc: 0x3EB Lid: 24761 Lid: 20665 StoreEc: 0x3EB Lid: 25785 Lid: 29881 StoreEc: 0x3EB
Call stack
Microsoft.Mapi.MapiExceptionHelper.ThrowIfError(String message, Int32 hresult, Int32 ec, DiagnosticContext diagCtx) Microsoft.Mapi.ExRpcConnection.OpenMsgStore(OpenStoreFlag storeFlags, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, MapiStore msgStorePrivate, String& correctServerDn, ClientIdentityInfo clientIdentityAs, String userDnAs, String applicationId, CultureInfo cultureInfo) Microsoft.Mapi.ConnectionCache.OpenMapiStore(String mailboxDn, Guid mailboxGuid, Guid mdbGuid, ClientIdentityInfo clientIdentity, String userDnAs, OpenStoreFlag openStoreFlags, CultureInfo cultureInfo, String applicationId) Microsoft.Mapi.ConnectionCache.OpenMailbox(String mailboxDn, Guid mailboxGuid, Guid mdbGuid, WindowsIdentity windowsIdentityAs, String userDnAs, OpenStoreFlag openStoreFlags, CultureInfo cultureInfo, String applicationId) Microsoft.Exchange.Data.Storage.ConnectionCachePool.OpenMailbox(String serverDn, String userDn, String mailboxDn, Guid mailboxGuid, Guid mdbGuid, Object identity, ConnectFlag connectFlag, OpenStoreFlag openStoreFlag, CultureInfo cultureInfo, String clientInfoString, Boolean secondTry)


Кроме того почтовый ящик пользователя всё еще отображался в Disconnected mailbox.

Если попробовать подключить почтовый ящик через рабочей станции администратора почтовой системы через Outlook 2007, то получаем:
"Невозможно открыть набор папок. Ошибка при входе на сервер Microsoft Exchange"

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

Возникло такое ощющение что не хватает каких то прав на ящик…

Повторил процедуру подключения на 2-м новом пользователе - всё тоже самое.

Попробовал переместить прицепленный почтовый ящик на другое хранилище, выдает ошибку:

Summary: 1 item(s). 0 succeeded, 1 failed.
Elapsed time: 00:00:01

VIA
Failed

Error:
Error was found for VIA () because: Error occurred in the step: Opening source mailbox. Failed to open mailbox with error: The operation failed., error code: -1056749262

Exchange Management Shell command attempted:
'corp.domain.ru/UO1/OU2/VIA' move-mailbox -TargetDatabase 'MailCluster-01\Ex2k7_04thDisabled_SG\Ex2k7_04thDisabled_Database'

Elapsed Time: 00:00:01


Решение оказалось на поверхности:
1.Необходимо восстановленному пользователю (которого удалили в самом начале) создать новый пользовательский ящик. При этом будет обнаружено что все mail алиасы которые ранее были у прользователя будут применены для этого созданного ящика.
2.Отключить и включить востановленную учетку.
3.Перецепить целевой почтовый ящик - оригинальный для востановленного пользователя от того пользователя (нового созданного), которому мы его подцепили. и Прицепить к тому пользователю, которому наш целевой почтовый ящик необходим.