I wrote this article for the Microsoft TechNet Blog CZ/SK, where it was published as Automated Environment Monitoring Using PowerShell and also published in the Microsoft section on Živě Automated Environment Monitoring Using PowerShell.
However, the basis of monitoring is still sending important events from servers to a central location, where they will be checked and selected events sent, for example, by email. This way, we can monitor failed login attempts, locked accounts, creation of objects in Active Directory, server restarts, and so on.
The second essential area is some standard monitoring that regularly checks the availability of servers and selected services. This way, we can detect a complete server failure, service unavailability (such as the smtp protocol on the mail server), lack of disk space, long-term CPU utilization, etc.
But today, we'll look at something else. We can create simple (and of course, complex) PowerShell scripts that run automatically every day (or another defined period) and send us a certain report. Then, with a quick glance, we can determine the state in a certain area. Similarly, we can create a number of regular checks that will send us a message if something is in an non-standard state. In the following lines, we'll show a few practical examples of how to use this in the Microsoft environment.
Introduction to PowerShell Scripts
We won't go into the basics of PowerShell here, but if you're not familiar with them, you don't need to worry. The usage is not particularly complex, and you may find that it's a really useful tool. We also won't discuss individual PowerShell commands in detail, but we'll show a few simple practical examples. They will always perform one action, and from their notation, we can certainly understand the meaning of the individual parts.
Running PowerShell Scripts
By default, in operating systems, running PowerShell scripts is not allowed, it's a security setting called Execution Policy. We can change this setting in the system using a PowerShell command or using Group Policy (this setting prevents the command from being changed). We can check the current setting with the command:
Get-ExecutionPolicy
We don't have space here to explain the options and security implications. So simply, to be able to run a local unsigned script, we must enter the command:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
If we want to enable script execution for a whole group of servers or for the entire company, it's better to use Group Policy. The setting is located at:
Computer Configuration/Policies/Administrative Templates/Windows Components/Windows PowerShell/Turn on Script Execution
To have this item available, we must have the PowerShellExecutionPolicy.admx file, which contains this template, loaded in the system (or in the Central Store). It's only available on Windows Server 2008 R2 and not in Windows 7 (but can be copied from the server or downloaded from the MS website).
Loading Modules and Snap-ins
In the following examples, we will work with Active Directory and use the Microsoft PowerShell module, which is part of (among other things) Windows Server 2008 R2. And also with Exchange Server 2007, which contains a PowerShell Snap-In. To be able to use the cmdlets from the modules and snap-ins in pure PowerShell (powershell.exe), we must first import them (load them). We can get information about the loaded modules and snap-ins using the commands:
Get-Module Get-PSSnapin
We load the Active Directory module with the command:
Import-Module ActiveDirectory
We load the Exchange Server 2007 Snap-In with the command:
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin
Scheduling Scripts
By default, a PowerShell Script is saved to a file with the ps1 extension. We can run it using the command (it's important to specify the path, although it can be done in other ways):
powershell c:\Scripts\script.ps1
For automatic execution, we'll use the Task Scheduler from Windows. In Windows Server 2008, we add the Start a program event on the Action tab and set powershell as the script and c:\Scripts\script.ps1 as the argument. On the Triggers tab, we add the scheduled task and enter the required run frequency. On the General tab, we set the account under which the script will run. On Windows Server 2003, the situation is similar, but in the Run field, we enter the entire command powershell c:\Scripts\script.ps1.
Checking Accounts in Active Directory
Not only from a security perspective, it's good to have things in order in Active Directory. And some information can only be obtained by asking a specific query. We can automate this with a script, run it regularly every night, and email the result.
Note: In the first example, we will describe the entire script, in the others we will omit loading the module at the beginning and sending the email at the end. The script will always be saved to a file with the ps1 extension on the domain controller, and we will automatically run it using the Task Scheduler under an account with sufficient permissions (read-only access to AD is sufficient). Of course, we can use multiple scripts at once and send one common email.
Inactive Users
For example, we might be interested in a list of users who haven't logged in to the domain for a defined period (here 30 days). This can help us detect that we've forgotten to delete an account or it's no longer needed.
In the script, we first load the module. The second command gets a list of user accounts that haven't logged in for the last 30 days, sorts them alphabetically, returns only the selected columns, and saves them to a file. The last command sends an informational email and attaches the generated file.
Import-Module ActiveDirectory Search-ADAccount -AccountInactive -UsersOnly -TimeSpan "30" | Sort-Object Name | FT Name,LastLogonDate,Enabled,LockedOut -AutoSize | Out-File -FilePath c:\Scripts\users-logon.txt -Width 300 Send-MailMessage -From ad@firm.cz -To monitoring@firm.cz -Subject "Checking AD Users" -SmtpServer mail.firm.local -Attachments c:\Scripts\users-logon.txt -Encoding ([System.Text.Encoding]::Unicode) -Body "Hello,`n`nChecking user accounts that haven't logged in for 30 days.`n`nYour administrator"
Inactive Computers
We can find computers that haven't logged in for 30 days in the same way.
Search-ADAccount -AccountInactive -ComputersOnly -TimeSpan "30" | Sort-Object Name | FT Name,LastLogonDate,Enabled,LockedOut -AutoSize | Out-File -FilePath "c:\Scripts\computers-logon.txt" -Width 300
Disabled User and Computer Accounts
We can create a list of disabled computer and user accounts. We may not need this information every day, but we can add it to the previous ones for an overview.
Search-ADAccount -AccountDisabled -UsersOnly | Sort-Object Name | FT Name -AutoSize | Out-File -FilePath "c:\Scripts\disabled-users.txt" -Width 300 Search-ADAccount -AccountDisabled -ComputersOnly | Sort-Object Name | FT Name -AutoSize | Out-File -FilePath "c:\Scripts\disabled-computers.txt" -Width 300
Locked User Accounts
If we have a policy on locking accounts, we may be interested in a list of locked accounts. Users would probably complain, but for example, we may not be aware that a service account has been locked.
Search-ADAccount -LockedOut -UsersOnly | Sort-Object Name | FT Name -AutoSize | Out-File -FilePath "c:\Scripts\locked-users.txt" -Width 300
New Computer Accounts
We can create a report that contains a list of new, deleted, or renamed computer accounts. We can also get this information from AD DS auditing, but this way we get a clear report.
First, we load the previous state (so the entire script won't work on the first run). Then we get a list of all computers, sort it, and save it to a file. We then load this list again into another variable (due to the type and subsequent comparison). We compare these two lists and save the difference to a file (this file can then be sent as an email). The result shows new records (indicator =>), missing records (indicator
Možná hloupý dotaz začátečníka.
Je možné podmínit odeslání emailu s logem.
Pokud by byl log prázdný email by nebyl odeslán?
respond to [1]PetrM: Samozřejmě, můžeme přidat jednoduchou podmínku, jestli byla vrácena nějaká data nebo kontrolovat vytvořený log, zda je prázdný.
Ukázka je u Kontrola komunikace.