Summary: Microsoft Scripting Guy, Ed Wilson, talks about using the Windows PowerShell Best Practices module to audit configuration of servers.
Microsoft Scripting Guy, Ed Wilson, is here. Well, tonight is the Charlotte Windows PowerShell user group. We are doing a mini version of the Scripting Games, and so if you are in the area, you should check it out. It is a great learning experience to see how four or five different people approach the same problem.
Exploring the Best Practices module
Today, I decided to play around with the Best Practices module on my domain controller running Windows Server 2012. To find the available cmdlets, I used the Get-Command cmdlet to look at the Best Practices module, as shown here.
PS C:\> Get-Command -Module bestpractices
CommandType Name ModuleName
----------- ---- ----------
Cmdlet Get-BpaModel BestPractices
Cmdlet Get-BpaResult BestPractices
Cmdlet Invoke-BpaModel BestPractices
Cmdlet Set-BpaResult BestPractices
First find the available best practice models
The first thing to do is to check for available best practice models. I do this by using the Get-BPAModel cmdlet and by not supplying anything else. This returns everything from everything as shown here.
PS C:\> Get-BpaModel
Id : Microsoft/Windows/ADRMS
Company : Microsoft Corporation
Name : RightsManagementServices
Version : 1.0
LastScanTime : Never
LastScanTimeUtcOffset :
SubModels :
Parameters :
ModelType : SingleMachine
SupportedConfiguration :
Id : Microsoft/Windows/CertificateServices
Company : Microsoft Corporation
Name : CertificateServices
Version : 1.0
LastScanTime : Never
LastScanTimeUtcOffset :
SubModels :
Parameters :
ModelType : SingleMachine
SupportedConfiguration : Win8
<OUTPUT TRUNCATED>
For me, a better output is to look at the IDand the LastScanTime. This is because invoking the BPAModel requires the ID and because I want to know when the last time (if ever) the Best Practices Analyzer (BPA) model ran. Here is the command and the associated results.
PS C:\> Get-BpaModel | select id, lastscantime
Id LastScanTime
-- ------------
Microsoft/Windows/ADRMS Never
Microsoft/Windows/CertificateServices Never
Microsoft/Windows/DHCPServer Never
Microsoft/Windows/DirectoryServices 11/18/2012 11:57:12 AM
Microsoft/Windows/DNSServer Never
Microsoft/Windows/FileServices Never
Microsoft/Windows/Hyper-V Never
Microsoft/Windows/LightweightDirectoryS... Never
Microsoft/Windows/NPAS Never
Microsoft/Windows/RemoteAccessServer Never
Microsoft/Windows/TerminalServices Never
Microsoft/Windows/UpdateServices Never
Microsoft/Windows/VolumeActivation Never
Microsoft/Windows/WebServer Never
To focus in on one specific best practices model, use the ID from the above output. I use the Clipboard to avoid a lot of typing. As shown here, the Invoke-BPAModel cmdlet does not appear to like wild cards.
PS C:\> Invoke-BpaModel -Id *dir*
Invoke-BpaModel: There has been a Best Practice Analyzer error for Model Id '*dir*'. The Model is not installed.
At line:1 char:1
+ Invoke-BpaModel -Id *dir*
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [Invoke-BpaModel], CommandLetException
+ FullyQualifiedErrorId : ModelNotFound,Microsoft.BestPractices.Cmdlets.RunScan Command
So, I use the Clipboard to paste the real ID name of the Directory Services BPA model to the Invoke-BPAModel cmdlet. This command is shown here along with the associated output from the command.
PS C:\> Invoke-BpaModel -Id Microsoft/Windows/DirectoryServices
ModelId : Microsoft/Windows/DirectoryServices
SubModelId :
Success : True
ScanTime : 11/18/2012 12:28:33 PM
ScanTimeUtcOffset : -05:00:00
Detail : {DC1, DC1}
Retrieving results from the best practices analyzer
To retrieve results after running the Invoke-BPAModel cmdlet, use the Get-BPAResults cmdlet. The command is shown here.
Get-BpaResult -Id Microsoft/Windows/DirectoryServices
The output is extensive and, when unfiltered, goes on for page after page. This is because the cmdlet presents lots of information about each check. The results of the command and the first two checks are shown here.
Well, I might not be an expert on the Best Practices Analyzer, but dude, I certainly know Windows PowerShell. So, I can fix this output easily. To do this, I first pipe the results to the Group-object and sort by the count. This way, I can get the “executive overview” and see the number of runs, hits, and errors.
PS C:\> Get-BpaResult -Id Microsoft/Windows/DirectoryServices | group severity -NoEle
ment | sort count
Count Name
----- ----
1 Error
8 Warning
34 Information
Hey, that is not too bad at all. I guess I will look at the Error first. I filter it out by using the Where-Object cmdlet. Because I am using Windows Server 2012, I have access to Windows PowerShell 3.0 and, therefore, to the new Where-Object syntax. Here is the command I use.
Get-BpaResult -Id Microsoft/Windows/DirectoryServices | where severity -eq error
Even the output from this one error is extensive. It appears (just a bit cut off) in the following figure.
After looking over the output, I decide I am only interested in the Title, Impact, and Resolution properties. The cleaned up output is shown here.
From my previous command, where I grouped the results by severity, I saw there were eight warnings. I now want to examine them. I use the up arrow, and change errorto warning, as shown here.
Get-BpaResult -Id Microsoft/Windows/DirectoryServices | where severity -eq warning | fl title, impact, Resolution
It might also be interesting to see the results by category. The following command shows that most of my results are configuration-related.
PS C:\> Get-BpaResult -Id Microsoft/Windows/DirectoryServices | group category -NoElement
Count Name
----- ----
42 Configuration
1 Operation
If I am curious as to which report is related to operations, I use the following command.
Get-BpaResult -Id Microsoft/Windows/DirectoryServices | where category -eq 'operation'
To get a general overview of the warnings I have, I use the following command.
Get-BpaResult -Id Microsoft/Windows/DirectoryServices | where severity -eq warning | fl title
The command and resulting list of warnings are shown in the following image.
OK, it seems that a lot of the warnings are because I do not have a backup. How about if I filter out the “backup noise” and see what is left. Here is the command I use.
PS C:\> Get-BpaResult -Id Microsoft/Windows/DirectoryServices | ? { $_.title -notmatch 'backed up' -AND $_.severity -eq 'warning'} | select title
Title
-----
All domains should have at least two domain controllers for redundancy
All OUs in this domain should be protected from accidental deletion
The domain controller dc1.nwtraders.msft should comply with the recommended best ...
There is more stuff related to the BPA module, and you can even download updated and additional BPA models. That is about it for now. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy