Powershell – список групп и их членов


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

Сделать это несложно, но в Powershell 4 это можно сделать красиво в одну строчку, если использовать новую возможность – переменную конвейера (pipelinevariable):

$a=Get-ADGroup -Filter {Name -like "G_Tasks_Monitoring_FNV-Maps_*"} -PipelineVariable a1 `
| Get-ADGroupMember `
| % { Add-Member -InputObject $_ -Name GroupName -Value $a1.Name -MemberType NoteProperty -force -PassThru } `
| select GroupName,name,SamAccountName

Либо тоже самое с выводом во внешний файл:

$a=Get-ADGroup -Filter {Name -like "G_Tasks_Monitoring_FNV-Maps_*"} -PipelineVariable a1 `
| Get-ADGroupMember `
| % { Add-Member -InputObject $_ -Name GroupName -Value $a1.Name -MemberType NoteProperty -force -PassThru } `
| select GroupName,name,SamAccountName `
| sort groupname `
| Export-Csv -NoTypeInformation .\out.txt -Encoding Unicode

Реклама

Как нацелить политику на виртуальные машины?


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

Обычно учётные записи виртуальных машин размещают от отдельной ветке OU и назначают им специальные политики. Но это не всегда удобно, т.к. может привести к дублированию политик, усложнению структуры AD, усложнению делегирования прав. Возникает ситуация аналогичная дуальности архитектуры: вы же не разделяете скорее всего 32-х и 64-х битные компьютеры по разным веткам AD, почему это надо делать для виртуальных и физических машин?

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

С теоретической точки зрения невозможно определить из программы, что она выполняется в виртуальной среде. На практике не всё так плохо, т.к. производители систем виртуализации (гипервизоров) эмулируют вполне определенные аппаратные устройства и присваивают им «хорошо известные» значения некоторых свойств, которые доступны виртуальной машине.

Проверить эти значения можно с помощью WMI запросов:

Get-WmiObject -Query «select * from Win32_BIOS» -ComputerName testcomp

Например для Microsoft Virtual Server 2005:

SMBIOSBIOSVersion : 080002

Manufacturer : American Megatrends Inc.

Name : BIOS Date: 02/22/06 20:54:49 Ver: 08.00.02

SerialNumber : 0197-5009-1700-0693-8099-8415-07

Version : A M I — 2000622

Ключевое значение тут «A M I».

Для VMware ESX:

SMBIOSBIOSVersion : 6.00

Manufacturer : Phoenix Technologies LTD

Name : PhoenixBIOS 4.0 Release 6.0

SerialNumber : VMware-42 32 41 66 15 d5 15 20-92 ea b4 7a 95 7e f2 17

Version : INTEL — 6040000

Ключевое значение тут «VMware».

Более полный список условий можно найти в опубликованном скрипте http://gallery.technet.microsoft.com/scriptcenter/Determine-if-a-computer-is-cdd20473

Любое условие из скрипта можно преобразовать в фильтр WMI.

Пример фильтра для VMware:

Get-WmiObject -Query «select * from Win32_BIOS where SerialNumber like ‘%VMware%'» -ComputerName testcomp

Условие может быть сложным (с использованием «or» и «and»). Но на практике вам вряд ли нужны все условия сразу. Более подробно о построении запросов можно почитать в документации WQL Operators в библиотеке MSDN.

Теперь остаётся только прописать фильтр для целой политики (Create WMI Filters for the GPO) или включить его в Group Policy Preferences (WMI Query Targeting).

Простейший путь оптимизации загрузки и входа пользователя


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

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

Можно ли отказаться от этого традиционного для многих пути и в то же время не оказывать негативное влияние на пользователей? Вполне!

Первое, что надо сделать, это мигрировать логон скрипты на Group Policy Preferences. GPP специально существует для того, чтобы заменить большую часть логон скриптов. Они имеют очень гибкую систему фильтров (Targeting), что позволяет внедрять GPP и заменять существующие логон скрипты постепенно и не спеша. Трудоёмкость процесса низкая – производительность системных администраторов возрастает значительно.

Что делать со скриптами, которые не могут быть заменены средствами GPP? Есть простой путь: запускать подобные скрипты через Планировщик заданий, а сами задания создавать с помощью GPP! На первый взгляд может показаться, что это создаёт больший беспорядок, но фактически, как только эта система заработает, вы убедитесь, что порядка становится больше, обслуживание проще, а поиск неисправностей легче.

Этим же способом можно устанавливать ПО (и удалять его), отказываясь от установки ПО с помощью групповых политик.

В конце этого процесса миграции на GPP остаётся отключить политику ожидания готовности сети и – получить благодарности от пользователей, которые удивятся, насколько быстрее стал грузиться их компьютер и профиль!

Powershell – нормализация регистра учетных записей


Некоторые проблемы живут вечно. Одна из таких проблем постоянно возникает, когда в домене Windows начинает аутентифицироваться какая-нибудь Unix система: такие системы изначально регистрозависимые, и в том числе это касается логинов.

Единственный «универсальный» способ хотя бы частично избавиться от этой проблемы – нормализовать sAMAccountName и UPN, приведя их к нижнему регистру у всех учетных записей.

Сделать это поможет простой скрипт:

$users=Get-ADUser -Filter * | ? SamAccountName -CnotMatch «^[a-z\._]*$»

$users.Count

 

$users | % { Set-ADUser $_ -Replace @{ SamAccountName=$_.SamAccountName.ToLower();UserPrincipalName=$_.UserPrincipalName.ToLower() } }

 

 

 

 

 

Powershell – Настраиваем отображение атрибутов в ADUC


При миграции в новый лес пришлось переносить рабочие настройки администраторов, в том числе настройки оснастки ADUC Active Domain User and Computers. В частности нужно было отобразить для учетных записей атрибуты с SIP-адресом, табельным номером и т.д. По умолчанию их нет в списке доступных для отображения через настройку View Add/Remove Columns. Чтобы нужные атрибуты появились, необходимо настроить DisplaySpecifiers.

Запускаем ADSIEDIT, открываем контейнер Configuration, контейнер DisplaySpecifiers, находим контейнер соответствующий нужному языку – английскому соответствует 409, русскому 419, затем нам нужен объект default-Display и его атрибут extraColumns, в котором перечислены все доступные для отображения атрибуты.

Причем часто пишется, что достаточно настроить default-Display, но это работает только для контейнеров по умолчанию, для созданных пользовательских OU это не работает – для них нужно править extraColumns (изначально он пустой) в organizationalUnit-Display. Но! Если вы используете в ADUC хранимые запросы Query, то для них применяются настройки из default-Display!

Подробнее можно прочитать тут и тут.

Если посмотрите атрибут extraColumns в default-Display, то увидите достаточно большой список. Переносить такое количество записей вручную трудоемко (extraColumns не суммируются!).

Как всегда на помощь приходит Powershell. Для английского языка:

$dom = «DC=domain,DC=ru»

$a = Get-ADObject -Identity «CN=default-Display,CN=409,CN=DisplaySpecifiers,CN=Configuration,$dom« -Properties extraColumns

 

$b = Get-ADObject -Identity «CN=organizationalUnit-Display,CN=409,CN=DisplaySpecifiers,CN=Configuration,$dom«

 

Set-ADObject $b -Add @{extraColumns=[array]$a.extraColumns}

 

 

Если нужно будет очистить extraColumns, то нужно сделать так:

Set-ADObject $b -Clear extraColumns

 

Теперь добавим нужные нам атрибуты:

$c= @{}

$c.extraColumns=@(’employeeID,Employee ID,0,-1,0′)

$c.extraColumns+=@(‘msRTCSIP-PrimaryUserAddress,Lync Address,0,100,0’)

$c.extraColumns+=@(«operatingSystem,Operating System,0,-1,0»)

$c.extraColumns+=@(«operatingSystemServicePack,Service Pack,0,-1,0»)

#$c.extraColumns+=»»

 

Set-ADObject $a -Add $c

Set-ADObject $b -Add $c

 

Ждем несколько минут, запускаем ADUC и добавляем для отображения нужные атрибуты.

О работе в Powershell с multivalued атрибутами можно почитать тут.

Миграция лесов и Sharepoint 2010. Часть 2.


В статье Миграция лесов и Sharepoint 2010 описана суть вопроса: миграция из двух лесов в один новый. Здесь я просто привожу доработанный скрипт, который можно использовать при миграции пользователей изо дня в день. Скрипт сохраняет в файле список уже обработанных учетных записей и при последующей итерации не выполняет их повторную обработку. Это сильно снижает время работы скрипта. Если вы мигрируете сотни учетных записей в день, то заметите ощутимую экономию времени.

 

Import-Module Activedirectory

 

$cmdpath=«C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN\»

$cmd = $cmdpath+«stsadm.exe»

 

$dserver = «dc0.TOdomain.ru»

$list=Get-ADUser -Filter * -SearchBase «OU=Deps,DC=TOdomain,DC=ru» -Server $dserver | select -ExpandProperty SamAccountName

 

 

$listold = Get-Content c:\install\list-old.txt

$list0 = $list | ? {$listold -notcontains $_ }

 

 

$dserver = «dc.FROMdomain1.ru»

$list1=$list0 | ? { Get-ADUser -Filter {samaccountname -eq $_} -SearchBase «DC=FROMdomain1,DC=ru» -Server $dserver }

 

$dserver = «dc.FROMdomain2.ru»

$list2=$list0 | % { Get-ADUser -Filter {samaccountname -eq $_} -SearchBase «DC=FROMdomain2,DC=ru» -Server $dserver } | select -ExpandProperty SamAccountName

 

$listconflict = $list1 | ? {$list2 -contains $_ }

 

$list11 = $list1 | ? { $listconflict -notcontains $_ }

$list22 = $list2 | ? { $listconflict -notcontains $_ }

 

 

$list11 | % { & $cmd -o migrateuser -oldlogin FROMdomain1\$($_) -newlogin TOdomain\$($_) -ignoresidhistory }

$list22 | % { & $cmd -o migrateuser -oldlogin FROMdomain2\$($_) -newlogin TOdomain\$($_) -ignoresidhistory }

 

$list11 | Out-File -FilePath c:\install\list-old.txt -Append

$list22 | Out-File -FilePath c:\install\list-old.txt -Append

 

Powershell – поиск конфликтов при миграции лесов


При миграции учетных записей из одного леса (домена) в другой может возникнуть неприятная ситуация – одинаковые samaccountname у учетных записей пользователей. В случае использования ADMT в режиме merge обе записи склеиваются (!) – вообще забавно получается, а режиме replace – поди потом пойми кто есть кто. С почтовыми ящиками Exchange тоже будет пазл (нет ничего страшного, но все же неприятно).

В любом случае надо сделать правильно и до миграции найти все возможные конфликты и устранить их. В поиске совпадающих samaccountname поможет следующий скрипт:

$dserver = «domain1.ru«

$list1= Get-ADUser -Filter * -SearchBase «DC=domain1,DC=ru» -Server $dserver  | select -ExpandProperty SamAccountName

 

$dserver = «domain2.ru»

$list2= Get-ADUser -Filter * -SearchBase «DC=domain2,DC=ru» -Server $dserver  | select -ExpandProperty SamAccountName

 

$listconflict = $list1 | ? {$list2 -contains $_ }