Get-ADUser и Organization Unit

Возник вопрос: как экспортировать список пользователей из AD с организационным подразделением (Organization Unit или OU).

Get-ADUser user -Properties * показал, что OU присутствует в двух атрибутах:

  • Distinguishedname: CN=user,ou=ou1,ou=ou2,dc=domain,dc=ru;
  • CanonicalName: domain.ru/ou2/ou1/user

В готовом виде OU нет, хотя для целей сортировки удобнее использовать CanonicalName.

Так родился «однострочник», позволяющий вытащить OU в качестве атрибута

get-aduser -filter * -SearchBase ou=ou1,ou=ou2,dc=domain,dc=ru" -Properties cn,canonicalname | select name,userprincipalname,@{Name="OU";expression={$_.Canonicalname.substring(0,$_.canonicalname.length-$_.cn.length)}}

Zerologon check (проверка)

Как вы слышали,  в августе 2020 года была обнаружена критическая уязвимость CVE-2020-1472 в протоколе проверки пользователя контроллером домена.

Критическая она потому, что для эксплуатации этой уязвимости достаточно оказаться в одной сети с контроллером домена.

Microsoft конечно же выпустил обновления, но кто ж их ставит, верно?

В сети есть скрипт, позволяющий провести проверку через эксплуатацию уязвимости, но это вряд ли считается нормальным методом проверки.

Поэтому я написал скрипт, который проверяет наличие требуемых обновлений на контроллерах домена Windows Server 2012 R2.

Список обновлений взят из статьи про уязвимость, а также Catalog MS, указывающего на более новые версии обновлений. В моем списке сентябрьское обновление, два августовских и перекрывающий их апдейт безопасности для Windows 2012 R2.

Обратите внимание, что для Windows 2016/2019 номера апдейтов другие!

Для запуска скрипта требуются права администратора домена, так как скрипт проходит по контроллерам и через WMI получает список установленных обновлений.

$updates="KB4577066","KB4571703","KB4571723","KB4578013";

Get-ADDomainController -filter * | sort name | %{
$result="initial";$hf=$null;
$hf=Get-HotFix -ComputerName $_.name | where{$updates -contains $_.hotfixid};
if($hf -eq $null){$result="WARNING"}
else{$result="";foreach($HFs in $HF){$result+=$HFs.HotfixID+";"}};
$_ | select Name, @{Name="Updates";Expression={$result}}}

Результатом работы скрипта является следующий вывод:

Name           Updates
----           -------
BAD-DC02 WARNING
GOOD-DC01 KB4571723;KB4578013;KB4577066;
GOOD-DC02 KB4571723;KB4578013;KB4577066;
MEDI-DC02 KB4571723;KB4571703;
MEDI-DC03 KB4578013;KB4571703;

WARNING означает, что нужно срочно бежать и ставить обновления.

Наличие сентябрьского обновления означает, что вы молодцы. Наличие августовских — ну не безнадежны, по крайней мере :-).

Приборка групп рассылок в Exchange

В нашей компании используется MS Exchange Server, в нём создано ~2000 групп рассылок: ~1700 обычных и ~300 динамических, и все это хозяйство держит под собой 2800 e-mail адресов.

Хозяев групп нет, а если и есть, то давно уволились, какого-то реестра тоже нет.

В результате, для одного департамента есть такие группы:

  • DISTRIB-Отдел;
  • Distrib_отдел;
  • Отделъ-Пермь;
  • DISTRIB_IT_Otdel.

И столько же динамических:

  • Рассылка-Отдел (Москва);
  • Рассылка-Отдел (Общая);
  • Рассылка Пермский ф-л (Отдел);
  • DST-PRM_NOT_OTDEL.

Читать далее «Приборка групп рассылок в Exchange»

Развертывание виртуальной машины vSphere через PowerSHell часть 1

Стал задаваться вопросом — как автоматизировать выполнение рутинных операций в vSphere?

Лучше бы не задавался 🙂

Начал с задачи «развернуть виртуальную машину из шаблона с указанной кастомизацией гостевой операционной системы».

Основные проблемы, с которыми я столкнулся:

  • мною использовалась настройка кастомизации ОС «Prompt User», спрашивающая только IP-адрес (подразумевается, что развертывание происходит в одно и то же адресное пространство). Как оказалось, проще использовать передачу «всех» параметров IP в скрипте;
  • перемещение учетной записи сервера после ее развертывания для применения групповых политик в другой контейнер Active Directory;
  • поле «Notes» получает строку. Как передать ей несколько строк, если потребуется перевод строки, я пока не разбирался;
  • за кадром остались процессы дальнейшей настройки сервера — установка обновлений и дополнительного ПО. Это будет рассмотрено в следующих частях статьи.

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

А вот что получил:

Get-OSCustomizationSpec -Name windows | New-OSCustomizationSpec -Name temp1 -Type NonPersistent
Get-OSCustomizationSpec -Name temp1 | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress '10.0.0.1' -SubnetMask '255.255.255.0' -DefaultGateway '10.0.0.254' -Dns '10.0.0.254','10.0.0.253'
New-VM -Name 'new-vm' -Template (Get-Template windows_template) -OSCustomizationSpec (Get-OSCustomizationSpec 'temp1') -ResourcePool (Get-ResourcePool -Name 'Resources'-Location 'Cluster_Name') -Datastore (Get-DatastoreCluster -Name 'Datastore_Cluster') -Notes "Zdes mogla by byt vasha reklama"
Start-VM -VM new-vm
Do {Get-ADComputer -identity new-vm -ErrorAction SilentlyContinue;write-host "." -nonewline -f red;sleep 3} until(Get-ADComputer -identity new-vm -ErrorAction SilentlyContinue -warningaction silentlycontinue)
Move-ADObject -identity (Get-ADComputer -identity new-vm).distinguishedname -TargetPath "OU=Servers,DC=DOMAIN,DC=COM"
Do {$tools=(Get-VM -Name new-vm).ExtensionData.Guest.ToolsStatus;write-host "." -nonewline -f red;sleep 3} until(($tools -eq "toolsOk") -or($tools -eq "toolsOld"))
Restart-VMGuest -VM new-vm -Confirm:$false
Start-Sleep -Seconds 10
Do {$tools=(Get-VM -Name new-vm).ExtensionData.Guest.ToolsStatus;write-host "." -nonewline -f red;sleep 3} until(($tools -eq "toolsOk") -or($tools -eq "toolsOld"))
Write-Host("Server is ready!")

Данный скрипт берет гостевую кастомизацию «windows» (Guest Customization OS) и создает на ее основе временную кастомизацию «temp1».

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

Далее мы создаем виртуальную машину из шаблона «windows_template», используя подготовленную кастомизацию «temp1». Машина создается в кластере «Cluster_name» с примечанием о том, для чего нужна эта ВМ. Диски шаблона при этом клонируются на кластер хранилищ (Datastore Cluster) с названием «Datastore_Cluster».

Затем мы включаем виртуальную машину и ждем.

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

Как только мы этого дождались, мы перекладываем эту учетную запись ПК в соответствующую OU.

Проверяем статус VMware Tools и, если они работают, перезагружаем наш сервер для применения актуальных групповых политик.

Затем ждем 10 секунд пока VMware Tools 100% остановятся в ходе перезагрузки, ждем пока они будут запущены и выводим на экран сообщение о том, что сервер готов.

Exchange 2013 CU22 и информация об Exchange

Я уже писал о том, что после разворачивания CU22 на Exchange 2013 вы получаете запись в реестре о том, что, оказывается, на сервере-то установлен Exchange 2013 CU20. Microsoft проблему признало и выпустило совет, как можно вручную исправить ключ реестра.

Я же по привычке делюсь скриптом, который исправит этот ключ реестра по всем вашим серверам Exchange, подразумевая что все они — Exhchange 2013 CU22.

Get-ExchangeServer | %{$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$_.name); $regKey= $reg.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Microsoft Exchange v15",$true); $regKey.SetValue("DisplayName","Microsoft Exchange Server 2013 Cumulative Update 22",[Microsoft.Win32.RegistryValueKind]::String);$_.name}

Скрипт пройдется по всем серверам Exchange в организации, поменяет параметр реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Exchange v15\Displayname и выведет имя сервера в качестве интерактива с вами.

Если вам нужно, чтобы обрабатывались не все сервера, а только какой-то список, то:

  • список серверов нужно будет подать на вход вместо командлета Get-ExchangeServer;
  • вместо $_.name использовать более подходящий $_

P.S. История с этим апдейтом напомнила

«Здравствуйте, я бедный албанский вирус. Я пока что ничего не умею, и к сожалению, не могу причинить вред вашему компьютеру. Пожалуйста, будьте так любезны, сотрите один из важных файлов с жесткого диска вашего компьютера самостоятельно и перешлите меня 30 друзьям. И будет вам счастье. Если вы этого не сделаете я обижусь и не будет вам счастья и конфет весь следующий год! Заранее благодарен за понимание и сотрудничество».

Проблемы с бэкапом из-за нецелого размера vmdk-диска

Обратил внимание на то, что некоторые виртуальные машины не бэкапятся через штатный VADP API. Техническая поддержка NetBackup нашла в логах, что причиной этого является дробный (нецелый) размер VMDK-диска.

Создать такой диск очень просто — указать дробный размер для терабайт в «толстом» клиенте:

Если изменить единицы измерения с терабайт на гигабайты, вы увидите, что диск занимает нецелое количество гигабайт (и соответственно, мегабайт).

Веб-клиент в этом плане получше — он сразу показывает наличие проблемы:

Лечится проблема достаточно легко:

  1. Меняете единицы измерения на мегабайты и увеличиваете размер диска в сторону ближайшего целого значения. В приведенном случае вместо 2’086’666,23925781 МБ у вас должно стать 2’086’667 МБ.
  2. Растягиваете размер файловой системы на вновь появившееся место.

Для экспресс-проверки вашей инфраструктуры вы можете воспользоваться следующим PowerCLI-скриптом:

Get-VM | Get-HardDisk | where {($_.capacityGB-[math]::Truncate($_.capacityGB)) -gt 0} | ft capacityGB, parent -AutoSize

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

Exchange 2013 CU22 и Get-ExchangeEnvironment

Четыре года назад я писал о своем опыте инвентаризации серверов Exchange в организации.

Для инвентаризации серверов мы используем скрипт Get-ExchangeEnvironment, который за последние годы был модернизирован для поддержки Exchange 2016 и большой кучи CU к Exchange 2013 🙂

Вышел Exchange 2013 CU22, закрывающий критические уязвимости в безопасности, и мы его развернули.

При этом мы столкнулись с парой проблем:

  1. Пропатченные сервера Exchange стали прикидываться Exchange 2013 CU20. Неожиданно, но это косяк Microsoft. В качестве лечения предлагается вручную исправить параметр реестра, содержащий номер CU (с «20» на «22»).
  2. Второй подвох ждал нас уже в скрипте инвентаризации: после исправления пункта №1 версия Exchange перестала отображаться.

Реверс инжиниринг скрипта показал, что в скрипте последний «поддерживаемый» CU — CU20:

# 1.5.8 Exchange Service Pack String Mapping 
$ExSPLevelStrings = @{"0" = "RTM" 
                      "1" = "SP1" 
                      "2" = "SP2" 
                      "3" = "SP3" 
                      "4" = "SP4" 
                      "SP1" = "SP1" 
                      "SP2" = "SP2"} 
    # Add many CUs                
    for ($i = 1; $i -le 20$i++) 
    { 
        $ExSPLevelStrings.Add("CU$($i)","CU$($i)");

Соответственно, для отображения корректной версии «Exchange 2013 CU22» вам нужно увеличить число, выделенное жирным и подчеркнутое, до 22.

P.S. Перечитал старую статью — там тоже были проблемы с отображаемыми CU 🙂

Особенно посмеялся со своей фразы «Исправляем таблицу, предположив, что для Exchange 2013 не будет выпущено больше CU10».

PowerCLI — CloneVM

Понадобилось наполнить объект vAPP однотипными клонами одной и той же ВМ.

Клонировать ее вручную показалось трудоемко — изучил возможности PowerCLI и написал себе шпаргалку:

После подключения к vCenter запускаем подобный скрипт:

for($i=2;$i -lt 69;$i++){new-vm -Name ("vm0"+$i+"_bi") -VM vm01_bi -Datastore "VMFS01" -VMHost "esxi" -DiskStorageFormat thin -VApp Big}

После запуска данного скрипта у вас появится 67 однотипных клонов виртуальной машины vm01_bi.

Вместо параметра VApp рекомендуется использовать параметр «ResourcePool»

Балансировка хранилищ Round Robin в VMware vSphere и iops=1

В одном ЦОДе нашей компании используется VMware vSphere и HP EVA 6400. Так получилось, что техподдержка HPE ткнула нас носом в «Best Practice Guide» и посоветовала применить рекомендации по RoundRobin-балансировке и переключению путей на каждый iops.

Я был настроен скептически, так как я прекрасно помню статью Duncan Epping о том, что это (iops=1) — бесполезный совет. Однако я перечитал комментарии и решил, что я был неправ. Если вкратце — то у каждого порта HP EVA (равно как и других массивов) своя очередь в 1000 команд. И, оставив параметр по умолчанию (или вообще используя MRU), легко упереться в эту очередь.

Читать далее «Балансировка хранилищ Round Robin в VMware vSphere и iops=1»

DHCP Option 61 или Client ID в Windows 10

Статья от одного из наших постоянных читателей — philzy :).

Я являюсь совладельцем сервиса cloud-desktop.net, и недавно у меня возникла проблема. Один из клиентов попросил восстановить виртуалку из бэкапа. Я восстановил ночную реплику за 2 мин., однако клиент сказал, что не может получить к ней доступ. Прошло 30 минут траблшутинга — виртуалка из реплики, оказывается, имеет другой MAC-адрес (да и IP), следовательно слетел доступ.

Я в курсе про то, что для таких случаев придуман DNS, но сервис работает именно через IP и этому есть простое объяснение – DNS разрешение имен не всегда корректно работает в haproxy [backend] server. Так как это ключевой элемент системы, то для снижения количества возможных проблем и было выбрано такое решение.

В общем, выдача IP-адреса через MAC-адрес — это не мой метод, и в качестве альтернативы я решил рассмотреть использование Client id или DHCP Option 61, использующий не привязанный к MAC-адресу метод выдачи IP-адресов через DHCP.

Я создал DHCP-пул на mikrotik и решил начать тестирование. Казалось, что это будет просто и понятно. Читать далее «DHCP Option 61 или Client ID в Windows 10»