Automatizovaná kontrola prostředí pomocí PowerShellu

aneb Pár tipů jak využít PowerShell

Každá síť potřebuje dohled (monitoring, kontrolu) a čím je větší, tím je složitější provádět různé kontroly ručně. Existuje řada systémů, které tyto kontroly budou provádět za nás, ale ty komplexní většinou stojí nemalé peníze. Přitom se dá vše postavit zdarma s menším či větším úsilím. Důležité je si uvědomit, co nás v naší síti zajímá, a na co chceme být upozorněni. Pak můžeme vytvářet jednoúčelové skripty, které nám zajistí potřebný přehled.

Základem monitoringu ale stále zůstává odesílání důležitých událostí ze serverů na jedno centrální místo, kde se budou kontrolovat a vybrané události odesílat třeba na email. Tak můžeme kontrolovat chybné pokusy o přihlášení, zamčení účtu, vytvoření nějakého objektu v Active Directory, restart serveru, apod.

Druhou nezbytnou oblastí je nějaký standardní monitoring, který pravidelně kontroluje dostupnost serverů a vybraných služeb. Tak zjistíme kompletní pád serveru, nedostupnost služby (jako například smtp protokol na poštovním serveru), nedostatek místa na disku, dlouhodobé vytížení procesoru, apod.

Dnes se ale podíváme na něco jiného. Můžeme vytvořit jednoduché (samozřejmě i složité) skripty v PowerShellu, které se automaticky spustí každý den (či jinou definovanou periodu) a odešlou nám určitý report. Potom krátkým pohledem zjistíme stav v určité oblasti. Podobně můžeme vytvořit řadu pravidelných kontrol, které nám pošlou zprávu, pokud je něco v nestandardním stavu. V dalších řádcích si ukážeme pár praktických příkladů, jak toto využít na Microsoft prostředí.

Úvod ke skriptům v PowerShellu

Nebudeme se zde věnovat základům PowerShellu, ale pokud je neznáte, tak se nemusíte obávat. Použití není nikterak složité a možná zjistíte, že je to opravdu užitečný nástroj. Ani dále v článku nebudeme rozebírat jednotlivé příkazy PowerShellu, ale ukážeme si pár jednoduchých praktických příkladů. Ty budou vždy provádět jednu činnost a z jejich zápisu určitě pochopíme význam jednotlivých částí.

Spouštění PowerShell skriptů

Standardně v operačních systémech není povoleno spouštět PowerShell skripty, jde o bezpečnostní nastavení zvané Execution Policy. Toto nastavení můžeme v systému změnit pomocí PowerShell příkazu nebo pomocí Group Policy (toto nastavení znemožní změnu příkazem). Aktuální nastavení zjistíme příkazem:

Get-ExecutionPolicy

Nemáme zde prostor vysvětlovat možnosti a bezpečnostní dopady. Takže jednoduše, abychom mohli spustit lokální nepodepsaný skript, tak musíme zadat příkaz:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

Pokud chceme spouštění povolit pro celou skupinu serverů či na celou firmu, tak je výhodnější použít Group Policy. Nastavení se nachází v položce:

Computer Configuration/Policies/Administrative Templates/Windows Components/Windows PowerShell/Turn on Script Execution

Abychom tuto položku měli k dispozici, tak musíme mít v systému (nebo v Central Store) nahraný soubor PowerShellExecutionPolicy.admx, který obsahuje tuto šablonu. Ten se nachází pouze na Windows Server 2008 R2 a ne třeba ve Windows 7 (ale je možno jej zkopírovat ze serveru nebo stáhnout z webu MS).

Načítání modulů a snap-in

V následujících příkladech budeme pracovat s ActiveDirectory a k tomu využijeme PowerShell modul od Microsoftu, který je součástí (mimo jiné) Windows Server 2008 R2. A také s Exchange Server 2007, který obsahuje Snap-In pro PowerShell. Abychom mohli použít cmdlety z modulů a snapinů v čistém PowerShellu (powershell.exe), tak je musíme nejprve zavést (načíst). Informace o načtených modulech a snapinech získáme pomocí příkazů:

Get-Module
Get-PSSnapin

Načtení ActiveDirectory modulu provedeme příkazem:

Import-Module ActiveDirectory

Načtení Exchange Server 2007 Snap-Inu provedeme příkazem:

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin

Plánování skriptů

Standardně se PowerShell Script ukládá do souboru s příponou ps1. Spustit jej můžeme pomocí příkazu (důležité je zadání cesty, i když to lze samozřejmě i jinak):

powershell c:\Skripty\skript.ps1

Pro automatické spouštění využijeme plánovač úloh z Windows (Task Scheduler). Ve Windows Server 2008 přidáme na záložce Action událost Start a program a jako script dáme powershell, jako argument dáme c:\Skripty\skript.ps1. Na záložce Triggers přidáme plánovaný úkol a zadáme požadovanou periodu spouštění. Na záložce General nastavíme, pod jakým účtem skript poběží. Na Windows Server 2003 je situace obdobná, pouze do políčka Run zadáme celý příkaz powershell c:\Skripty\skript.ps1.

Kontrola účtů v Active Directory

Nejen z bezpečnostního hlediska je dobré mít v Active Directory pořádek. Přitom některé informace se dozvíme pouze položením určitého dotazu. To můžeme automatizovat skriptem, spouštět pravidelně každou noc a na email si odeslat výsledek.

Pozn.: V prvním příkladu popíšeme celý skript, v dalších již budeme vynechávat načtení modulu na začátku a odeslání emailu na konci. Skript vždy uložíme do nějakého souboru s příponou ps1 na doménovém řadiči a budeme automatizovaně spouštět pomocí Task Scheduler pod účtem s dostatečným oprávněním (stačí čtení AD). Samozřejmě můžeme použít více skriptů najednou a odeslat jeden společný email.

Neaktivní uživatelé

Například nás může zajímat seznam uživatelů, kteří se nepřihlásili nějakou definovanou dobu (zde 30 dní) do domény. Tím můžeme odhalit, že jsme nějaký účet zapomněli smazat nebo již přestal být potřeba.

Ve skriptu nejprve načteme modul. Druhý příkaz získá seznam uživatelských účtů, které se za posledních 30 dní nepřihlásily, ten seřadí podle abecedy, vrátí pouze vybrané sloupce a uloží do souboru. Poslední příkaz odešle informační email a do přílohy vloží vygenerovaný soubor.

Import-Module ActiveDirectory
Search-ADAccount -AccountInactive -UsersOnly -TimeSpan "30" | Sort-Object Name | FT Name,LastLogonDate,Enabled,LockedOut -AutoSize | Out-File -FilePath c:\Skripty\users-logon.txt -Width 300
Send-MailMessage -From ad@firma.cz -To monitoring@firma.cz -Subject "Kontrola uživatelů v AD" -SmtpServer mail.firma.local -Attachments c:\Skripty\users-logon.txt -Encoding ([System.Text.Encoding]::Unicode) -Body "Ahoj,`n`nKontrola uživatelských účtů které se 30 dní nepřihlásili.`n`nVáš administrátor"

Neaktivní počítače

Stejným způsobem můžeme nalézt počítače, které se 30 dní nepřihlásily.

Search-ADAccount -AccountInactive -ComputersOnly -TimeSpan "30" | Sort-Object Name | FT Name,LastLogonDate,Enabled,LockedOut -AutoSize | Out-File -FilePath "c:\Skripty\computers-logon.txt" -Width 300

Zakázané účty uživatelů a počítačů

Můžeme vytvářet seznam počítačových a uživatelských účtů, které jsou zakázané (disabled). Tuto informaci asi nepotřebujeme každý den, ale můžeme ji pro přehled přidat k předchozím.

Search-ADAccount -AccountDisabled -UsersOnly | Sort-Object Name | FT Name -AutoSize | Out-File -FilePath "c:\Skripty\disabled-users.txt" -Width 300

Search-ADAccount -AccountDisabled -ComputersOnly | Sort-Object Name | FT Name -AutoSize | Out-File -FilePath "c:\Skripty\disabled-computers.txt" -Width 300

Zamčené uživatelské účty

Pokud máme politiku na zamykání účtů, tak nás může zajímat seznam zamčených účtů. Uživatelé by se asi ozvali, ale například se nemusíme dozvědět, že se zamknul nějaký servisní účet.

Search-ADAccount -LockedOut -UsersOnly | Sort-Object Name | FT Name -AutoSize | Out-File -FilePath "c:\Skripty\locked-users.txt" -Width 300

Nové počítačové účty

Můžeme vytvářet report, který bude obsahovat seznam nových, smazaných nebo přejmenovaných počítačových účtů. Tyto informace můžeme získat i z auditování AD DS, ale takto dostaneme přehledný report.

Nejprve načteme předchozí stav (takže při prvním spuštění nám celý skript nezafunguje). Potom získáme seznam všech počítačů a seřazený jej uložíme do souboru. Tento seznam znovu načteme do jiné proměnné (kvůli typu a následnému porovnání). Porovnáme tyto dva seznamy a jejich rozdíl uložíme do souboru (tento soubor pak můžeme odeslat jako email). Ve výsledku vidíme nové záznamy (indicator =>) a chybějící záznamy (indicator <=), pokud došlo ke změně jména, tak bude zobrazeno jako odstraněný a nově vložený.

$yesterday = Get-Content c:\skripty\computers.txt
Get-ADComputer -Filter * | Sort-Object Name | FT Name –AutoSize | Out-File -FilePath c:\skripty\computers.txt
$today = Get-Content c:\skripty\computers.txt
Compare-Object $yesterday $today | FT -AutoSize | Out-File -FilePath c:\skripty\computers-changes.txt

Kontrola poštovních schránek na Exchange serveru

Tak jako informace z domény nás může zajímat řada informací na poštovním serveru, hlavní se týkají poštovních schránek (mailboxů).

Pozn.: Opět první skript bude kompletní a dále jen hlavní část. Skript bude v souboru s příponou ps1 a plánovat jej budeme přímo na Exchange serveru (nyní musí mít účet práva na Exchange).

Poštovní schránky s překročeným limitem

Na velikost poštovní schránky se může nastavit několik limitů, při prvním se uživateli posílá upozornění, ale jinak může standardně pracovat. Pokud nás zajímá seznam schránek, které překročili tento limit, tak můžeme použít následující skript.

Nejprve načteme snap-in. Potom vezmeme seznam mailboxů, odstraníme z něj ty, které mají velikost pod limitem, seřadíme podle velikosti a vybrané sloupce uložíme do souboru. Ten pak odešleme emailem.

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin
Get-MailboxStatistics | sort TotalItemSize -Descending | where { $_.StorageLimitStatus -ne "BelowLimit" } | FT DisplayName,TotalItemSize,ItemCount,LastLogonTime,StorageLimitStatus -AutoSize | Out-File -FilePath "c:\Skripty\Mailbox-greater-limit.txt" -Width 300
Send-MailMessage -From exchange@firma.cz -To monitoring@firma.cz -Subject "Kontrola velikosti poštovních schránek" -SmtpServer mail.firma.local -Attachments c:\Skripty\Mailbox-greater-limit.txt -Encoding ([System.Text.Encoding]::Unicode) -Body "Ahoj,`n` nKontrola velikosti poštovních schránek.`n`nVáš administrátor"

Veřejné složky s překročeným limitem

Obdobně můžeme kontrolovat velikost veřejných složek (Public Folders) a vytvořit seznam těch, které jsou větší než zadaná hodnota (zde cca 500MB). Jen je třeba si uvědomit, že podsložky ve veřejných složkách se počítají samostatně.

Get-PublicFolderStatistics | Sort TotalItemSize -Descending | where { $_.TotalItemSize -gt 500000000 } | FT Name,FolderPath,ItemCount,TotalItemSize,LastAccessTime -AutoSize | Out-File -FilePath "c:\Skripty\PF-greater-500MB.txt" -Width 300

Přehled mobilních zařízení

Pokud používáme Exchange ActiveSync, tak se mobilní zařízení, která se serverem synchronizujeme, spárují s účtem a na serveru se o nich vytvoří záznam. K dispozici máme příkaz, který nám napíše několik informací. Uživatelé si mohou připojit různé přístroje a nás může zajímat, že přibylo nové zařízení či obecně přehled o nich.

Můžeme opět naplánovat úlohu, která zjistí seznam všech zařízení, a vytvoří rozdíl oproti předchozímu dni, takže vidíme změny.

$yesterday = Get-Content c:\skripty\ActiveSync.txt
Get-Mailbox | ForEach { Get-ActiveSyncDeviceStatistics -Mailbox:$_.Identity } | FT Identity,DeviceType,DeviceUserAgent,DeviceModel,DeviceIMEI,DeviceOS,DevicePhoneNumber -AutoSize | Out-File -FilePath c:\skripty\ActiveSync.txt -Width 400
$today = Get-Content c:\skripty\ActiveSync.txt
Compare-Object $yesterday $today | Out-File -FilePath c:\skripty\ActiveSync-differences.txt -Width 400

Kontrola komunikace

V řadě situací můžeme využít test, zda přišel nějaký určitý email. Například máme vzdálený systém, který není přímo dostupný z internetu, ale může odesílat emaily. Necháme tedy jednou za hodinu posílat emailový keepalive a máme hrubou kontrolu, že systém žije.

$mails = Get-MessageTrackingLog -EventID "RECEIVE" -Sender "server@nekde.cz" -Recipients "monitor@firma.cz" -Start (Get-Date).AddHours(-1) -End $time | FT Timestamp, Sender, MessageSubject -AutoSize

if($mails -eq $null) { Send-MailMessage -From dohled@firma.cz -To monitoring@firma.cz -Subject "Kontrolní email ze serveru" -SmtpServer mail.firma.local -Encoding ([System.Text.Encoding]::Unicode) -Body "Za poslední hodinu nedorazil kontrolní email!" }

Systémové kontroly

Ještě se podíváme na dva příklady, které nespadají do předchozích kategorií. Navíc se jedná o malinko složitější skripty.

Kontrola zálohy

Pokud provádíme nějaké jednoduché zálohy, například dump z linuxového serveru, který v taru kopírujeme na souborový server s Windows, tak můžeme testovat, jestli se v danou dobu soubor vytvořil a jestli není jeho velikost nulová.

Do proměnné $files si uložíme seznam souborů (bez adresářů), které byly změněny (tedy i nově vznikly) za poslední den v adresáři c:\backup (mohli bychom hledat pouze soubory určitého jména). Potom porovnáme, jestli je v seznamu alespoň jeden soubor (nemůžeme použít jednodušší $files.Count, protože nefunguje na prázdný seznam). Pokud nějaké soubory existují, tak ověříme, jestli nemají nulovou velikost (můžeme testovat zadanou minimální velikost). Pokud došlo k problému, tak odešleme informaci emailem.

$message = ""
$files = Get-ChildItem c:\backup | Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-1) -and ! $_.PSIsContainer }
if(($files | Measure-Object).Count -eq 0) {
$message = "Za poslední den nevznikl žádný soubor."
} else {
$files | ForEach-Object { if($_.Length -eq 0) { $message += "Soubor " + $_.name + " má nulovou velikost. " } }
}
if($message -ne "") { Send-MailMessage -From zalohovani@firma.cz -To monitoring@firma.cz -Subject "Zálohování selhalo" -SmtpServer mail.firma.local -Encoding ([System.Text.Encoding]::Unicode) -Body $message }

Změny na DHCP serveru

Sice je řada možností, jak zabezpečit připojení "cizího" zařízení do sítě, ale dokonalé zabezpečení je většinou v praxi nemožné. Pro zvýšení našeho přehledu o zařízeních v síti si můžeme posílat report zařízení, která dostala IP adresu od DHCP. Není to myšleno jako metoda odhalení nepovolených zařízení v síti, také bychom mohli využít auditování DHCP serveru, je to pouze ukázka možností.

Ani v poslední verzi Windows serveru neobsahuje PowerShell cmdlety pro ovládání DHCP serveru. Nic nám ale nebrání využít z PowerShellu klasický příkaz netsh (v neinteraktivním režimu) a zpracovat jeho výsledky. Takže si vypíšeme seznam aktivních DHCP Scope, z nich vybereme prvních 15 znaků (což je síťová IP adresa) a uložíme do proměnné. Potom pro každou adresu scopu vypíšeme seznam pronajatých adres (lease). Výsledek uložíme do souboru. Porovnáváme stav z předchozího dne s aktuálním a výsledkem jsou změny.

$leases_yesterday = Get-Content c:\skripty\dhcp.txt
$scopes = netsh dhcp server \\pdc show scope | Where-Object { $_.Contains("Active") } | ForEach-Object { $_.Substring(0, 15) }
$leases = $scopes | ForEach-Object { netsh dhcp server \\pdc scope $_.Trim() show clients 1 } | Where-Object { $_.Contains("-D-") -or $_.Contains("-U-") -or $_.Contains("-R-") }
$leases | Out-File -FilePath c:\skripty\dhcp.txt
Compare-Object $leases_yesterday $leases | FT -AutoSize | Out-File -FilePath d:\dhcp-changes.txt

Závěr

Pokud jste dočetli až sem, tak vám děkuji a doufám, že pro vás měl článek nějaký přínos. Jeho cílem bylo ukázat, že můžeme jednoduše získat přehled o tom, co se děje v našem prostředí. A nebude nás to stát příliš času ani peněz. Potom také, že PowerShell není špatná ani složitá technologie. Hlavní je rozmyslet, o čem v síti chceme být informováni. Sestavení skriptu již nemusí být složité a hodně nám pomůže internetový vyhledávač. Samozřejmě příklady v článku jsou docela triviální, daly by se vylepšit, aby měly větší inteligenci, ale to by obnášelo trochu více kódu a složitosti.

- Petr Bouška