├── LICENSE
├── PSHTML-AD.ps1
└── README.md
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Brad Wyatt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PSHTML-AD.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Generate graphed report for all Active Directory objects.
4 |
5 | .DESCRIPTION
6 | Generate graphed report for all Active Directory objects.
7 | Forked and updated by @vhoudoverdov to support the enumeration of vCenter components.
8 |
9 | .PARAMETER CompanyLogo
10 | Enter URL or UNC path to your desired Company Logo for generated report.
11 |
12 | -CompanyLogo "\\Server01\Admin\Files\CompanyLogo.png"
13 |
14 | .PARAMETER RightLogo
15 | Enter URL or UNC path to your desired right-side logo for generated report.
16 |
17 | -RightLogo "https://www.psmpartners.com/wp-content/uploads/2017/10/porcaro-stolarek-mete.png"
18 |
19 | .PARAMETER ReportTitle
20 | Enter desired title for generated report.
21 |
22 | -ReportTitle "Active Directory Report"
23 |
24 | .PARAMETER Days
25 | Users that have not logged in [X] amount of days or more.
26 |
27 | -Days "30"
28 |
29 | .PARAMETER UserCreatedDays
30 | Users that have been created within [X] amount of days.
31 |
32 | -UserCreatedDays "7"
33 |
34 | .PARAMETER DaysUntilPWExpireINT
35 | Users password expires within [X] amount of days
36 |
37 | -DaysUntilPWExpireINT "7"
38 |
39 | .PARAMETER ADModNumber
40 | Active Directory Objects that have been modified within [X] amount of days.
41 |
42 | -ADModNumber "3"
43 |
44 | .NOTES
45 | Version: 1.0.3
46 | Author: Bradley Wyatt
47 | Date: 12/4/2018
48 | Fork Author: Vasken Houdoverdov
49 | Fork Date: 12/10/2018
50 | Modified: vhoudoverdov 12/10/2018
51 | Modified: JBear 12/5/2018
52 | Bradley Wyatt 12/8/2018
53 | jporgand 12/6/2018
54 | #>
55 |
56 | param (
57 |
58 | #Company logo that will be displayed on the left, can be URL or UNC
59 | [Parameter(ValueFromPipeline = $true, HelpMessage = "Enter URL or UNC path to Company Logo")]
60 | [String]$CompanyLogo = "",
61 | #Logo that will be on the right side, UNC or URL
62 |
63 | [Parameter(ValueFromPipeline = $true, HelpMessage = "Enter URL or UNC path for Side Logo")]
64 | [String]$RightLogo = "https://www.psmpartners.com/wp-content/uploads/2017/10/porcaro-stolarek-mete.png",
65 | #Title of generated report
66 |
67 | [Parameter(ValueFromPipeline = $true, HelpMessage = "Enter desired title for report")]
68 | [String]$ReportTitle = "Active Directory Report",
69 | #Location the report will be saved to
70 |
71 | [Parameter(ValueFromPipeline = $true, HelpMessage = "Enter desired directory path to save; Default: C:\Automation\")]
72 | [String]$ReportSavePath = "C:\Automation\",
73 | #Find users that have not logged in X Amount of days, this sets the days
74 |
75 | [Parameter(ValueFromPipeline = $true, HelpMessage = "Users that have not logged on in more than [X] days. amount of days; Default: 30")]
76 | $Days = 30,
77 | #Get users who have been created in X amount of days and less
78 |
79 | [Parameter(ValueFromPipeline = $true, HelpMessage = "Users that have been created within [X] amount of days; Default: 7")]
80 | $UserCreatedDays = 7,
81 | #Get users whos passwords expire in less than X amount of days
82 |
83 | [Parameter(ValueFromPipeline = $true, HelpMessage = "Users password expires within [X] amount of days; Default: 7")]
84 | $DaysUntilPWExpireINT = 7,
85 | #Get AD Objects that have been modified in X days and newer
86 |
87 | [Parameter(ValueFromPipeline = $true, HelpMessage = "AD Objects that have been modified within [X] amount of days; Default: 3")]
88 | $ADModNumber = 3
89 |
90 | #CSS template located C:\Program Files\WindowsPowerShell\Modules\ReportHTML\1.4.1.1\
91 | #Default template is orange and named "Sample"
92 | )
93 |
94 | ipmo VMware.VimAutomation.Core
95 |
96 | Write-Host "Gathering Report Customization..." -ForegroundColor White
97 | Write-Host "__________________________________" -ForegroundColor White
98 | (Write-Host -NoNewline "Company Logo (left): " -ForegroundColor Yellow), (Write-Host $CompanyLogo -ForegroundColor White)
99 | (Write-Host -NoNewline "Company Logo (right): " -ForegroundColor Yellow), (Write-Host $RightLogo -ForegroundColor White)
100 | (Write-Host -NoNewline "Report Title: " -ForegroundColor Yellow), (Write-Host $ReportTitle -ForegroundColor White)
101 | (Write-Host -NoNewline "Report Save Path: " -ForegroundColor Yellow), (Write-Host $ReportSavePath -ForegroundColor White)
102 | (Write-Host -NoNewline "Amount of Days from Last User Logon Report: " -ForegroundColor Yellow), (Write-Host $Days -ForegroundColor White)
103 | (Write-Host -NoNewline "Amount of Days for New User Creation Report: " -ForegroundColor Yellow), (Write-Host $UserCreatedDays -ForegroundColor White)
104 | (Write-Host -NoNewline "Amount of Days for User Password Expiration Report: " -ForegroundColor Yellow), (Write-Host $DaysUntilPWExpireINT -ForegroundColor White)
105 | (Write-Host -NoNewline "Amount of Days for Newly Modified AD Objects Report: " -ForegroundColor Yellow), (Write-Host $ADModNumber -ForegroundColor White)
106 | Write-Host "__________________________________" -ForegroundColor White
107 |
108 | function LastLogonConvert ($ftDate)
109 | {
110 |
111 | $Date = [DateTime]::FromFileTime($ftDate)
112 |
113 | if ($Date -lt (Get-Date '1/1/1900') -or $date -eq 0 -or $date -eq $null)
114 | {
115 |
116 | "Never"
117 | }
118 |
119 | else
120 | {
121 |
122 | $Date
123 | }
124 |
125 | } #End function LastLogonConvert
126 |
127 | #Check for ReportHTML Module
128 | $Mod = Get-Module -ListAvailable -Name "ReportHTML"
129 |
130 | If ($null -eq $Mod)
131 | {
132 |
133 | Write-Host "ReportHTML Module is not present, attempting to install it"
134 |
135 | Install-Module -Name ReportHTML -Force
136 | Import-Module ReportHTML -ErrorAction SilentlyContinue
137 | }
138 |
139 | #Array of default Security Groups
140 | $DefaultSGs = @(
141 |
142 | "Access Control Assistance Operators"
143 | "Account Operators"
144 | "Administrators"
145 | "Allowed RODC Password Replication Group"
146 | "Backup Operators"
147 | "Certificate Service DCOM Access"
148 | "Cert Publishers"
149 | "Cloneable Domain Controllers"
150 | "Cryptographic Operators"
151 | "Denied RODC Password Replication Group"
152 | "Distributed COM Users"
153 | "DnsUpdateProxy"
154 | "DnsAdmins"
155 | "Domain Admins"
156 | "Domain Computers"
157 | "Domain Controllers"
158 | "Domain Guests"
159 | "Domain Users"
160 | "Enterprise Admins"
161 | "Enterprise Key Admins"
162 | "Enterprise Read-only Domain Controllers"
163 | "Event Log Readers"
164 | "Group Policy Creator Owners"
165 | "Guests"
166 | "Hyper-V Administrators"
167 | "IIS_IUSRS"
168 | "Incoming Forest Trust Builders"
169 | "Key Admins"
170 | "Network Configuration Operators"
171 | "Performance Log Users"
172 | "Performance Monitor Users"
173 | "Print Operators"
174 | "Pre-Windows 2000 Compatible Access"
175 | "Protected Users"
176 | "RAS and IAS Servers"
177 | "RDS Endpoint Servers"
178 | "RDS Management Servers"
179 | "RDS Remote Access Servers"
180 | "Read-only Domain Controllers"
181 | "Remote Desktop Users"
182 | "Remote Management Users"
183 | "Replicator"
184 | "Schema Admins"
185 | "Server Operators"
186 | "Storage Replica Administrators"
187 | "System Managed Accounts Group"
188 | "Terminal Server License Servers"
189 | "Users"
190 | "Windows Authorization Access Group"
191 | "WinRMRemoteWMIUsers"
192 | )
193 |
194 | $Table = New-Object 'System.Collections.Generic.List[System.Object]'
195 | $OUTable = New-Object 'System.Collections.Generic.List[System.Object]'
196 | $UserTable = New-Object 'System.Collections.Generic.List[System.Object]'
197 | $GroupTypetable = New-Object 'System.Collections.Generic.List[System.Object]'
198 | $DefaultGrouptable = New-Object 'System.Collections.Generic.List[System.Object]'
199 | $EnabledDisabledUsersTable = New-Object 'System.Collections.Generic.List[System.Object]'
200 | $DomainAdminTable = New-Object 'System.Collections.Generic.List[System.Object]'
201 | $ExpiringAccountsTable = New-Object 'System.Collections.Generic.List[System.Object]'
202 | $CompanyInfoTable = New-Object 'System.Collections.Generic.List[System.Object]'
203 | $securityeventtable = New-Object 'System.Collections.Generic.List[System.Object]'
204 | $DomainTable = New-Object 'System.Collections.Generic.List[System.Object]'
205 | $OUGPOTable = New-Object 'System.Collections.Generic.List[System.Object]'
206 | $GroupMembershipTable = New-Object 'System.Collections.Generic.List[System.Object]'
207 | $PasswordExpirationTable = New-Object 'System.Collections.Generic.List[System.Object]'
208 | $PasswordExpireSoonTable = New-Object 'System.Collections.Generic.List[System.Object]'
209 | $userphaventloggedonrecentlytable = New-Object 'System.Collections.Generic.List[System.Object]'
210 | $EnterpriseAdminTable = New-Object 'System.Collections.Generic.List[System.Object]'
211 | $NewCreatedUsersTable = New-Object 'System.Collections.Generic.List[System.Object]'
212 | $GroupProtectionTable = New-Object 'System.Collections.Generic.List[System.Object]'
213 | $OUProtectionTable = New-Object 'System.Collections.Generic.List[System.Object]'
214 | $GPOTable = New-Object 'System.Collections.Generic.List[System.Object]'
215 | $ADObjectTable = New-Object 'System.Collections.Generic.List[System.Object]'
216 | $ProtectedUsersTable = New-Object 'System.Collections.Generic.List[System.Object]'
217 | $ComputersTable = New-Object 'System.Collections.Generic.List[System.Object]'
218 | $ComputerProtectedTable = New-Object 'System.Collections.Generic.List[System.Object]'
219 | $ComputersEnabledTable = New-Object 'System.Collections.Generic.List[System.Object]'
220 | $DefaultComputersinDefaultOUTable = New-Object 'System.Collections.Generic.List[System.Object]'
221 | $DefaultUsersinDefaultOUTable = New-Object 'System.Collections.Generic.List[System.Object]'
222 | $TOPUserTable = New-Object 'System.Collections.Generic.List[System.Object]'
223 | $TOPGroupsTable = New-Object 'System.Collections.Generic.List[System.Object]'
224 | $TOPComputersTable = New-Object 'System.Collections.Generic.List[System.Object]'
225 | $GraphComputerOS = New-Object 'System.Collections.Generic.List[System.Object]'
226 | $VmwareVmList = New-Object 'System.Collections.Generic.List[System.Object]'
227 | $OutdatedVMwareTools = New-Object 'System.Collections.Generic.List[System.Object]'
228 | $OpenSnapshotTable = New-Object 'System.Collections.Generic.List[System.Object]'
229 | $DatastoreTable = New-Object 'System.Collections.Generic.List[System.Object]'
230 | $PortGroupTable = New-Object 'System.Collections.Generic.List[System.Object]'
231 | $VcenterAlarmTable = New-Object 'System.Collections.Generic.List[System.Object]'
232 | $EsxiHostTable = New-Object 'System.Collections.Generic.List[System.Object]'
233 |
234 |
235 | #Get all users right away. Instead of doing several lookups, we will use this object to look up all the information needed.
236 | $AllUsers = Get-ADUser -Filter * -Properties *
237 |
238 | $GPOs = Get-GPO -All | Select-Object DisplayName, GPOStatus, ModificationTime, @{ Label = "ComputerVersion"; Expression = { $_.computer.dsversion } }, @{ Label = "UserVersion"; Expression = { $_.user.dsversion } }
239 |
240 | <###########################
241 | Dashboard
242 | ############################>
243 |
244 | Write-Host "Working on Dashboard Report..." -ForegroundColor Green
245 |
246 | $dte = (Get-Date).AddDays(- $ADModNumber)
247 |
248 | $ADObjs = Get-ADObject -Filter { whenchanged -gt $dte -and ObjectClass -ne "domainDNS" -and ObjectClass -ne "rIDManager" -and ObjectClass -ne "rIDSet" } -Properties *
249 |
250 | foreach ($ADObj in $ADObjs)
251 | {
252 |
253 | if ($ADObj.ObjectClass -eq "GroupPolicyContainer")
254 | {
255 |
256 | $Name = $ADObj.DisplayName
257 | }
258 |
259 | else
260 | {
261 |
262 | $Name = $ADObj.Name
263 | }
264 |
265 | $obj = [PSCustomObject]@{
266 |
267 | 'Name' = $Name
268 | 'Object Type' = $ADObj.ObjectClass
269 | 'When Changed' = $ADObj.WhenChanged
270 | }
271 |
272 | $ADObjectTable.Add($obj)
273 | }
274 | if (($ADObjectTable).Count -eq 0)
275 | {
276 |
277 | $Obj = [PSCustomObject]@{
278 |
279 | Information = 'Information: No AD Objects have been modified recently'
280 | }
281 |
282 | $ADObjectTable.Add($obj)
283 | }
284 |
285 |
286 | $ADRecycleBinStatus = (Get-ADOptionalFeature -Filter 'name -like "Recycle Bin Feature"').EnabledScopes
287 |
288 | if ($ADRecycleBinStatus.Count -lt 1)
289 | {
290 |
291 | $ADRecycleBin = "Disabled"
292 | }
293 |
294 | else
295 | {
296 |
297 | $ADRecycleBin = "Enabled"
298 | }
299 |
300 | #Company Information
301 | $ADInfo = Get-ADDomain
302 | $ForestObj = Get-ADForest
303 | $DomainControllerobj = Get-ADDomain
304 | $Forest = $ADInfo.Forest
305 | $InfrastructureMaster = $DomainControllerobj.InfrastructureMaster
306 | $RIDMaster = $DomainControllerobj.RIDMaster
307 | $PDCEmulator = $DomainControllerobj.PDCEmulator
308 | $DomainNamingMaster = $ForestObj.DomainNamingMaster
309 | $SchemaMaster = $ForestObj.SchemaMaster
310 |
311 | $obj = [PSCustomObject]@{
312 |
313 | 'Domain' = $Forest
314 | 'AD Recycle Bin' = $ADRecycleBin
315 | 'Infrastructure Master' = $InfrastructureMaster
316 | 'RID Master' = $RIDMaster
317 | 'PDC Emulator' = $PDCEmulator
318 | 'Domain Naming Master' = $DomainNamingMaster
319 | 'Schema Master' = $SchemaMaster
320 | }
321 |
322 | $CompanyInfoTable.Add($obj)
323 |
324 | if (($CompanyInfoTable).Count -eq 0)
325 | {
326 |
327 | $Obj = [PSCustomObject]@{
328 |
329 | Information = 'Information: Could not get items for table'
330 | }
331 | $CompanyInfoTable.Add($obj)
332 | }
333 |
334 | #Get newly created users
335 | $When = ((Get-Date).AddDays(- $UserCreatedDays)).Date
336 | $NewUsers = $AllUsers | Where-Object { $_.whenCreated -ge $When }
337 |
338 | foreach ($Newuser in $Newusers)
339 | {
340 |
341 | $obj = [PSCustomObject]@{
342 |
343 | 'Name' = $Newuser.Name
344 | 'Enabled' = $Newuser.Enabled
345 | 'Creation Date' = $Newuser.whenCreated
346 | }
347 |
348 | $NewCreatedUsersTable.Add($obj)
349 | }
350 | if (($NewCreatedUsersTable).Count -eq 0)
351 | {
352 |
353 | $Obj = [PSCustomObject]@{
354 |
355 | Information = 'Information: No new users have been recently created'
356 | }
357 | $NewCreatedUsersTable.Add($obj)
358 | }
359 |
360 |
361 |
362 | #Get Domain Admins
363 | $DomainAdminMembers = Get-ADGroupMember "Domain Admins"
364 |
365 | foreach ($DomainAdminMember in $DomainAdminMembers)
366 | {
367 |
368 | $Name = $DomainAdminMember.Name
369 | $Type = $DomainAdminMember.ObjectClass
370 | $Enabled = ($AllUsers | Where-Object { $_.Name -eq $Name }).Enabled
371 |
372 | $obj = [PSCustomObject]@{
373 |
374 | 'Name' = $Name
375 | 'Enabled' = $Enabled
376 | 'Type' = $Type
377 | }
378 |
379 | $DomainAdminTable.Add($obj)
380 | }
381 |
382 | if (($DomainAdminTable).Count -eq 0)
383 | {
384 |
385 | $Obj = [PSCustomObject]@{
386 |
387 | Information = 'Information: No Domain Admin Members were found'
388 | }
389 | $DomainAdminTable.Add($obj)
390 | }
391 |
392 |
393 | #Get Enterprise Admins
394 | $EnterpriseAdminsMembers = Get-ADGroupMember "Enterprise Admins" -Server $SchemaMaster
395 |
396 | foreach ($EnterpriseAdminsMember in $EnterpriseAdminsMembers)
397 | {
398 |
399 | $Name = $EnterpriseAdminsMember.Name
400 | $Type = $EnterpriseAdminsMember.ObjectClass
401 | $Enabled = ($AllUsers | Where-Object { $_.Name -eq $Name }).Enabled
402 |
403 | $obj = [PSCustomObject]@{
404 |
405 | 'Name' = $Name
406 | 'Enabled' = $Enabled
407 | 'Type' = $Type
408 | }
409 |
410 | $EnterpriseAdminTable.Add($obj)
411 | }
412 |
413 | if (($EnterpriseAdminTable).Count -eq 0)
414 | {
415 |
416 | $Obj = [PSCustomObject]@{
417 |
418 | Information = 'Information: Enterprise Admin members were found'
419 | }
420 | $EnterpriseAdminTable.Add($obj)
421 | }
422 |
423 | $DefaultComputersOU = (Get-ADDomain).computerscontainer
424 | $DefaultComputers = Get-ADComputer -Filter * -Properties * -SearchBase "$DefaultComputersOU"
425 |
426 | foreach ($DefaultComputer in $DefaultComputers)
427 | {
428 |
429 | $obj = [PSCustomObject]@{
430 |
431 | 'Name' = $DefaultComputer.Name
432 | 'Enabled' = $DefaultComputer.Enabled
433 | 'Operating System' = $DefaultComputer.OperatingSystem
434 | 'Modified Date' = $DefaultComputer.Modified
435 | 'Password Last Set' = $DefaultComputer.PasswordLastSet
436 | 'Protect from Deletion' = $DefaultComputer.ProtectedFromAccidentalDeletion
437 | }
438 |
439 | $DefaultComputersinDefaultOUTable.Add($obj)
440 | }
441 |
442 | if (($DefaultComputersinDefaultOUTable).Count -eq 0)
443 | {
444 |
445 | $Obj = [PSCustomObject]@{
446 |
447 | Information = 'Information: No computers were found in the Default OU'
448 | }
449 | $DefaultComputersinDefaultOUTable.Add($obj)
450 | }
451 |
452 | $DefaultUsersOU = (Get-ADDomain).UsersContainer
453 | $DefaultUsers = $Allusers | Where-Object { $_.DistinguishedName -like "*$($DefaultUsersOU)" } | Select-Object Name, UserPrincipalName, Enabled, ProtectedFromAccidentalDeletion, EmailAddress, @{ Name = 'lastlogon'; Expression = { LastLogonConvert $_.lastlogon } }, DistinguishedName
454 |
455 | foreach ($DefaultUser in $DefaultUsers)
456 | {
457 |
458 | $obj = [PSCustomObject]@{
459 |
460 | 'Name' = $DefaultUser.Name
461 | 'UserPrincipalName' = $DefaultUser.UserPrincipalName
462 | 'Enabled' = $DefaultUser.Enabled
463 | 'Protected from Deletion' = $DefaultUser.ProtectedFromAccidentalDeletion
464 | 'Last Logon' = $DefaultUser.LastLogon
465 | 'Email Address' = $DefaultUser.EmailAddress
466 | }
467 |
468 | $DefaultUsersinDefaultOUTable.Add($obj)
469 | }
470 | if (($DefaultUsersinDefaultOUTable).Count -eq 0)
471 | {
472 |
473 | $Obj = [PSCustomObject]@{
474 |
475 | Information = 'Information: No Users were found in the default OU'
476 | }
477 | $DefaultUsersinDefaultOUTable.Add($obj)
478 | }
479 |
480 |
481 | #Expiring Accounts
482 | $LooseUsers = Search-ADAccount -AccountExpiring -UsersOnly
483 |
484 | foreach ($LooseUser in $LooseUsers)
485 | {
486 |
487 | $NameLoose = $LooseUser.Name
488 | $UPNLoose = $LooseUser.UserPrincipalName
489 | $ExpirationDate = $LooseUser.AccountExpirationDate
490 | $enabled = $LooseUser.Enabled
491 |
492 | $obj = [PSCustomObject]@{
493 |
494 | 'Name' = $NameLoose
495 | 'UserPrincipalName' = $UPNLoose
496 | 'Expiration Date' = $ExpirationDate
497 | 'Enabled' = $enabled
498 | }
499 |
500 | $ExpiringAccountsTable.Add($obj)
501 | }
502 |
503 | if (($ExpiringAccountsTable).Count -eq 0)
504 | {
505 |
506 | $Obj = [PSCustomObject]@{
507 |
508 | Information = 'Information: No Users were found to expire soon'
509 | }
510 | $ExpiringAccountsTable.Add($obj)
511 | }
512 |
513 | #Security Logs
514 | $SecurityLogs = Get-EventLog -Newest 7 -LogName "Security" | Where-Object { $_.Message -like "*An account*" }
515 |
516 | foreach ($SecurityLog in $SecurityLogs)
517 | {
518 |
519 | $TimeGenerated = $SecurityLog.TimeGenerated
520 | $EntryType = $SecurityLog.EntryType
521 | $Recipient = $SecurityLog.Message
522 |
523 | $obj = [PSCustomObject]@{
524 |
525 | 'Time' = $TimeGenerated
526 | 'Type' = $EntryType
527 | 'Message' = $Recipient
528 | }
529 |
530 | $SecurityEventTable.Add($obj)
531 | }
532 |
533 | if (($SecurityEventTable).Count -eq 0)
534 | {
535 |
536 | $Obj = [PSCustomObject]@{
537 |
538 | Information = 'Information: No logon security events were found'
539 | }
540 | $SecurityEventTable.Add($obj)
541 | }
542 |
543 | #Tenant Domain
544 | $Domains = Get-ADForest | Select-Object -ExpandProperty upnsuffixes | ForEach-Object{
545 |
546 | $obj = [PSCustomObject]@{
547 |
548 | 'UPN Suffixes' = $_
549 | Valid = "True"
550 | }
551 |
552 | $DomainTable.Add($obj)
553 | }
554 | if (($DomainTable).Count -eq 0)
555 | {
556 |
557 | $Obj = [PSCustomObject]@{
558 |
559 | Information = 'Information: No UPN Suffixes were found'
560 | }
561 | $DomainTable.Add($obj)
562 | }
563 |
564 | Write-Host "Done!" -ForegroundColor White
565 |
566 | <###########################
567 |
568 | Groups
569 |
570 | ############################>
571 |
572 | Write-Host "Working on Groups Report..." -ForegroundColor Green
573 |
574 | #Get groups and sort in alphabetical order
575 | $Groups = Get-ADGroup -Filter * -Properties *
576 | $SecurityCount = 0
577 | $MailSecurityCount = 0
578 | $CustomGroup = 0
579 | $DefaultGroup = 0
580 | $Groupswithmemebrship = 0
581 | $Groupswithnomembership = 0
582 | $GroupsProtected = 0
583 | $GroupsNotProtected = 0
584 |
585 | foreach ($Group in $Groups)
586 | {
587 |
588 | $DefaultADGroup = 'False'
589 | $Type = New-Object 'System.Collections.Generic.List[System.Object]'
590 | $Gemail = (Get-ADGroup $Group -Properties mail).mail
591 |
592 | if (($group.GroupCategory -eq "Security") -and ($Gemail -ne $Null))
593 | {
594 |
595 | $MailSecurityCount++
596 | }
597 |
598 | if (($group.GroupCategory -eq "Security") -and (($Gemail) -eq $Null))
599 | {
600 |
601 | $SecurityCount++
602 | }
603 |
604 | if ($Group.ProtectedFromAccidentalDeletion -eq $True)
605 | {
606 |
607 | $GroupsProtected++
608 | }
609 |
610 | else
611 | {
612 |
613 | $GroupsNotProtected++
614 | }
615 |
616 | if ($DefaultSGs -contains $Group.Name)
617 | {
618 |
619 | $DefaultADGroup = "True"
620 | $DefaultGroup++
621 | }
622 |
623 | else
624 | {
625 |
626 | $CustomGroup++
627 | }
628 |
629 | if ($group.GroupCategory -eq "Distribution")
630 | {
631 |
632 | $Type = "Distribution Group"
633 | }
634 |
635 | if (($group.GroupCategory -eq "Security") -and (($Gemail) -eq $Null))
636 | {
637 |
638 | $Type = "Security Group"
639 | }
640 |
641 | if (($group.GroupCategory -eq "Security") -and (($Gemail) -ne $Null))
642 | {
643 |
644 | $Type = "Mail-Enabled Security Group"
645 | }
646 |
647 | if ($Group.Name -ne "Domain Users")
648 | {
649 |
650 | $Users = (Get-ADGroupMember -Identity $Group | Sort-Object DisplayName | Select-Object -ExpandProperty Name) -join ", "
651 |
652 | if (!($Users))
653 | {
654 |
655 | $Groupswithnomembership++
656 | }
657 |
658 | else
659 | {
660 |
661 | $Groupswithmemebrship++
662 |
663 | }
664 | }
665 |
666 | else
667 | {
668 |
669 | $Users = "Skipped Domain Users Membership"
670 | }
671 |
672 | $OwnerDN = Get-ADGroup -Filter { name -eq $Group.Name } -Properties managedBy | Select-Object -ExpandProperty ManagedBy
673 | Try
674 | {
675 | $Manager = Get-ADUser -Filter { distinguishedname -like $OwnerDN } | Select-Object -ExpandProperty Name
676 | }
677 | Catch
678 | {
679 | write-host -ForegroundColor Yellow "Cannot resolve the manager, " $Manager " on the group " $group.name
680 | }
681 |
682 | #$Manager = $AllUsers | Where-Object { $_.distinguishedname -eq $OwnerDN } | Select-Object -ExpandProperty Name
683 |
684 | $obj = [PSCustomObject]@{
685 |
686 | 'Name' = $Group.name
687 | 'Type' = $Type
688 | 'Members' = $users
689 | 'Managed By' = $Manager
690 | 'E-mail Address' = $GEmail
691 | 'Protected from Deletion' = $Group.ProtectedFromAccidentalDeletion
692 | 'Default AD Group' = $DefaultADGroup
693 | }
694 |
695 | $table.Add($obj)
696 | }
697 |
698 | if (($table).Count -eq 0)
699 | {
700 |
701 | $Obj = [PSCustomObject]@{
702 |
703 | Information = 'Information: No Groups were found'
704 | }
705 | $table.Add($obj)
706 | }
707 | #TOP groups table
708 | $obj1 = [PSCustomObject]@{
709 |
710 | 'Total Groups' = $Groups.Count
711 | 'Mail-Enabled Security Groups' = $MailSecurityCount
712 | 'Security Groups' = $SecurityCount
713 | 'Distribution Groups' = $DistroCount
714 | }
715 |
716 | $TOPGroupsTable.Add($obj1)
717 |
718 | $obj1 = [PSCustomObject]@{
719 |
720 | 'Name' = 'Mail-Enabled Security Groups'
721 | 'Count' = $MailSecurityCount
722 | }
723 |
724 | $GroupTypetable.Add($obj1)
725 |
726 | $obj1 = [PSCustomObject]@{
727 |
728 | 'Name' = 'Security Groups'
729 | 'Count' = $SecurityCount
730 | }
731 |
732 | $GroupTypetable.Add($obj1)
733 | $DistroCount = ($Groups | Where-Object { $_.GroupCategory -eq "Distribution" }).Count
734 |
735 | $obj1 = [PSCustomObject]@{
736 |
737 | 'Name' = 'Distribution Groups'
738 | 'Count' = $DistroCount
739 | }
740 |
741 | $GroupTypetable.Add($obj1)
742 |
743 | #Default Group Pie Chart
744 | $obj1 = [PSCustomObject]@{
745 |
746 | 'Name' = 'Default Groups'
747 | 'Count' = $DefaultGroup
748 | }
749 |
750 | $DefaultGrouptable.Add($obj1)
751 |
752 | $obj1 = [PSCustomObject]@{
753 |
754 | 'Name' = 'Custom Groups'
755 | 'Count' = $CustomGroup
756 | }
757 |
758 | $DefaultGrouptable.Add($obj1)
759 |
760 | #Group Protection Pie Chart
761 | $obj1 = [PSCustomObject]@{
762 |
763 | 'Name' = 'Protected'
764 | 'Count' = $GroupsProtected
765 | }
766 |
767 | $GroupProtectionTable.Add($obj1)
768 |
769 | $obj1 = [PSCustomObject]@{
770 |
771 | 'Name' = 'Not Protected'
772 | 'Count' = $GroupsNotProtected
773 | }
774 |
775 | $GroupProtectionTable.Add($obj1)
776 |
777 | #Groups with membership vs no membership pie chart
778 | $objmem = [PSCustomObject]@{
779 |
780 | 'Name' = 'With Members'
781 | 'Count' = $Groupswithmemebrship
782 | }
783 |
784 | $GroupMembershipTable.Add($objmem)
785 |
786 | $objmem = [PSCustomObject]@{
787 |
788 | 'Name' = 'No Members'
789 | 'Count' = $Groupswithnomembership
790 | }
791 |
792 | $GroupMembershipTable.Add($objmem)
793 |
794 | Write-Host "Done!" -ForegroundColor White
795 |
796 | <###########################
797 |
798 | Organizational Units
799 |
800 | ############################>
801 |
802 | Write-Host "Working on Organizational Units Report..." -ForegroundColor Green
803 |
804 | #Get all OUs'
805 | $OUs = Get-ADOrganizationalUnit -Filter * -Properties *
806 | $OUwithLinked = 0
807 | $OUwithnoLink = 0
808 | $OUProtected = 0
809 | $OUNotProtected = 0
810 |
811 | foreach ($OU in $OUs)
812 | {
813 |
814 | $LinkedGPOs = New-Object 'System.Collections.Generic.List[System.Object]'
815 |
816 | if (($OU.linkedgrouppolicyobjects).length -lt 1)
817 | {
818 |
819 | $LinkedGPOs = "None"
820 | $OUwithnoLink++
821 | }
822 |
823 | else
824 | {
825 |
826 | $OUwithLinked++
827 | $GPOslinks = $OU.linkedgrouppolicyobjects
828 |
829 | foreach ($GPOlink in $GPOslinks)
830 | {
831 |
832 | $Split1 = $GPOlink -split "{" | Select-Object -Last 1
833 | $Split2 = $Split1 -split "}" | Select-Object -First 1
834 | $LinkedGPOs.Add((Get-GPO -Guid $Split2 -ErrorAction SilentlyContinue).DisplayName)
835 | }
836 | }
837 |
838 | if ($OU.ProtectedFromAccidentalDeletion -eq $True)
839 | {
840 |
841 | $OUProtected++
842 | }
843 |
844 | else
845 | {
846 |
847 | $OUNotProtected++
848 | }
849 |
850 | $LinkedGPOs = $LinkedGPOs -join ", "
851 | $obj = [PSCustomObject]@{
852 |
853 | 'Name' = $OU.Name
854 | 'Linked GPOs' = $LinkedGPOs
855 | 'Modified Date' = $OU.WhenChanged
856 | 'Protected from Deletion' = $OU.ProtectedFromAccidentalDeletion
857 | }
858 |
859 | $OUTable.Add($obj)
860 | }
861 |
862 | if (($OUTable).Count -eq 0)
863 | {
864 |
865 | $Obj = [PSCustomObject]@{
866 |
867 | Information = 'Information: No OUs were found'
868 | }
869 | $OUTable.Add($obj)
870 | }
871 |
872 | #OUs with no GPO Linked
873 | $obj1 = [PSCustomObject]@{
874 |
875 | 'Name' = "OUs with no GPO's linked"
876 | 'Count' = $OUwithnoLink
877 | }
878 |
879 | $OUGPOTable.Add($obj1)
880 |
881 | $obj2 = [PSCustomObject]@{
882 |
883 | 'Name' = "OUs with GPO's linked"
884 | 'Count' = $OUwithLinked
885 | }
886 |
887 | $OUGPOTable.Add($obj2)
888 |
889 | #OUs Protected Pie Chart
890 | $obj1 = [PSCustomObject]@{
891 |
892 | 'Name' = "Protected"
893 | 'Count' = $OUProtected
894 | }
895 |
896 | $OUProtectionTable.Add($obj1)
897 |
898 | $obj2 = [PSCustomObject]@{
899 |
900 | 'Name' = "Not Protected"
901 | 'Count' = $OUNotProtected
902 | }
903 |
904 | $OUProtectionTable.Add($obj2)
905 |
906 | Write-Host "Done!" -ForegroundColor White
907 |
908 | <###########################
909 |
910 | USERS
911 |
912 | ############################>
913 |
914 | Write-Host "Working on Users Report..." -ForegroundColor Green
915 |
916 | $UserEnabled = 0
917 | $UserDisabled = 0
918 | $UserPasswordExpires = 0
919 | $UserPasswordNeverExpires = 0
920 | $ProtectedUsers = 0
921 | $NonProtectedUsers = 0
922 |
923 | $UsersWIthPasswordsExpiringInUnderAWeek = 0
924 | $UsersNotLoggedInOver30Days = 0
925 | $AccountsExpiringSoon = 0
926 |
927 |
928 | #Get users that haven't logged on in X amount of days, var is set at start of script
929 | $userphaventloggedonrecentlytable = New-Object 'System.Collections.Generic.List[System.Object]'
930 | foreach ($User in $AllUsers)
931 | {
932 |
933 | $AttVar = $User | Select-Object Enabled, PasswordExpired, PasswordLastSet, PasswordNeverExpires, PasswordNotRequired, Name, SamAccountName, EmailAddress, AccountExpirationDate, @{ Name = 'lastlogon'; Expression = { LastLogonConvert $_.lastlogon } }, DistinguishedName
934 | $maxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge.Days
935 |
936 | if ((($AttVar.PasswordNeverExpires) -eq $False) -and (($AttVar.Enabled) -ne $false))
937 | {
938 |
939 | #Get Password last set date
940 | $passwordSetDate = ($User | ForEach-Object { $_.PasswordLastSet })
941 |
942 | if ($null -eq $passwordSetDate)
943 | {
944 |
945 | $daystoexpire = "User has never logged on"
946 | }
947 |
948 | else
949 | {
950 |
951 | #Check for Fine Grained Passwords
952 | $PasswordPol = (Get-ADUserResultantPasswordPolicy $user)
953 |
954 | if (($PasswordPol) -ne $null)
955 | {
956 |
957 | $maxPasswordAge = ($PasswordPol).MaxPasswordAge
958 | }
959 |
960 | $expireson = $passwordsetdate.AddDays($maxPasswordAge)
961 | $today = (Get-Date)
962 |
963 | #Gets the count on how many days until the password expires and stores it in the $daystoexpire var
964 | $daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days
965 | }
966 | }
967 |
968 | else
969 | {
970 |
971 | $daystoexpire = "N/A"
972 | }
973 |
974 | if (($User.Enabled -eq $True) -and ($AttVar.LastLogon -lt ((Get-Date).AddDays(- $Days))) -and ($User.LastLogon -ne $NULL))
975 | {
976 |
977 | $obj = [PSCustomObject]@{
978 |
979 | 'Name' = $User.Name
980 | 'UserPrincipalName' = $User.UserPrincipalName
981 | 'Enabled' = $AttVar.Enabled
982 | 'Protected from Deletion' = $User.ProtectedFromAccidentalDeletion
983 | 'Last Logon' = $AttVar.lastlogon
984 | 'Password Never Expires' = $AttVar.PasswordNeverExpires
985 | 'Days Until Password Expires' = $daystoexpire
986 | }
987 |
988 | $userphaventloggedonrecentlytable.Add($obj)
989 | }
990 |
991 | #Items for protected vs non protected users
992 | if ($User.ProtectedFromAccidentalDeletion -eq $False)
993 | {
994 |
995 | $NonProtectedUsers++
996 | }
997 |
998 | else
999 | {
1000 |
1001 | $ProtectedUsers++
1002 | }
1003 |
1004 | #Items for the enabled vs disabled users pie chart
1005 | if (($AttVar.PasswordNeverExpires) -ne $false)
1006 | {
1007 |
1008 | $UserPasswordNeverExpires++
1009 | }
1010 |
1011 | else
1012 | {
1013 |
1014 | $UserPasswordExpires++
1015 | }
1016 |
1017 | #Items for password expiration pie chart
1018 | if (($AttVar.Enabled) -ne $false)
1019 | {
1020 |
1021 | $UserEnabled++
1022 | }
1023 |
1024 | else
1025 | {
1026 |
1027 | $UserDisabled++
1028 | }
1029 |
1030 | $Name = $User.Name
1031 | $UPN = $User.UserPrincipalName
1032 | $Enabled = $AttVar.Enabled
1033 | $EmailAddress = $AttVar.EmailAddress
1034 | $AccountExpiration = $AttVar.AccountExpirationDate
1035 | $PasswordExpired = $AttVar.PasswordExpired
1036 | $PasswordLastSet = $AttVar.PasswordLastSet
1037 | $PasswordNeverExpires = $AttVar.PasswordNeverExpires
1038 | $daysUntilPWExpire = $daystoexpire
1039 |
1040 | $obj = [PSCustomObject]@{
1041 |
1042 | 'Name' = $Name
1043 | 'UserPrincipalName' = $UPN
1044 | 'Enabled' = $Enabled
1045 | 'Protected from Deletion' = $User.ProtectedFromAccidentalDeletion
1046 | 'Last Logon' = $LastLogon
1047 | 'Email Address' = $EmailAddress
1048 | 'Account Expiration' = $AccountExpiration
1049 | 'Change Password Next Logon' = $PasswordExpired
1050 | 'Password Last Set' = $PasswordLastSet
1051 | 'Password Never Expires' = $PasswordNeverExpires
1052 | 'Days Until Password Expires' = $daystoexpire
1053 | }
1054 |
1055 | $usertable.Add($obj)
1056 |
1057 | if ($daystoexpire -lt $DaysUntilPWExpireINT)
1058 | {
1059 |
1060 | $obj = [PSCustomObject]@{
1061 |
1062 | 'Name' = $Name
1063 | 'Days Until Password Expires' = $daystoexpire
1064 | }
1065 |
1066 | $PasswordExpireSoonTable.Add($obj)
1067 | }
1068 | }
1069 | if (($userphaventloggedonrecentlytable).Count -eq 0)
1070 | {
1071 | $userphaventloggedonrecentlytable = [PSCustomObject]@{
1072 |
1073 | Information = "Information: No Users were found to have not logged on in $Days days or more"
1074 | }
1075 | }
1076 | if (($PasswordExpireSoonTable).Count -eq 0)
1077 | {
1078 |
1079 | $Obj = [PSCustomObject]@{
1080 |
1081 | Information = 'Information: No users were found to have passwords expiring soon'
1082 | }
1083 | $PasswordExpireSoonTable.Add($obj)
1084 | }
1085 |
1086 |
1087 | if (($usertable).Count -eq 0)
1088 | {
1089 |
1090 | $Obj = [PSCustomObject]@{
1091 |
1092 | Information = 'Information: No users were found'
1093 | }
1094 | $usertable.Add($obj)
1095 | }
1096 |
1097 | #Data for users enabled vs disabled pie graph
1098 | $objULic = [PSCustomObject]@{
1099 |
1100 | 'Name' = 'Enabled'
1101 | 'Count' = $UserEnabled
1102 | }
1103 |
1104 | $EnabledDisabledUsersTable.Add($objULic)
1105 |
1106 | $objULic = [PSCustomObject]@{
1107 |
1108 | 'Name' = 'Disabled'
1109 | 'Count' = $UserDisabled
1110 | }
1111 |
1112 | $EnabledDisabledUsersTable.Add($objULic)
1113 |
1114 | #Data for users password expires pie graph
1115 | $objULic = [PSCustomObject]@{
1116 |
1117 | 'Name' = 'Password Expires'
1118 | 'Count' = $UserPasswordExpires
1119 | }
1120 |
1121 | $PasswordExpirationTable.Add($objULic)
1122 |
1123 | $objULic = [PSCustomObject]@{
1124 |
1125 | 'Name' = 'Password Never Expires'
1126 | 'Count' = $UserPasswordNeverExpires
1127 | }
1128 |
1129 | $PasswordExpirationTable.Add($objULic)
1130 |
1131 | #Data for protected users pie graph
1132 | $objULic = [PSCustomObject]@{
1133 |
1134 | 'Name' = 'Protected'
1135 | 'Count' = $ProtectedUsers
1136 | }
1137 |
1138 | $ProtectedUsersTable.Add($objULic)
1139 |
1140 | $objULic = [PSCustomObject]@{
1141 |
1142 | 'Name' = 'Not Protected'
1143 | 'Count' = $NonProtectedUsers
1144 | }
1145 |
1146 | $ProtectedUsersTable.Add($objULic)
1147 | if ($null -ne (($userphaventloggedonrecentlytable).Information))
1148 | {
1149 | $UHLONXD = "0"
1150 |
1151 | }
1152 | Else
1153 | {
1154 | $UHLONXD = $userphaventloggedonrecentlytable.Count
1155 |
1156 | }
1157 | #TOP User table
1158 | If ($null -eq (($ExpiringAccountsTable).Information))
1159 | {
1160 |
1161 | $objULic = [PSCustomObject]@{
1162 | 'Total Users' = $AllUsers.Count
1163 | "Users with Passwords Expiring in less than $DaysUntilPWExpireINT days" = $PasswordExpireSoonTable.Count
1164 | 'Expiring Accounts' = $ExpiringAccountsTable.Count
1165 | "Users Haven't Logged on in $Days Days or more" = $UHLONXD
1166 | }
1167 |
1168 | $TOPUserTable.Add($objULic)
1169 |
1170 |
1171 | }
1172 | Else
1173 | {
1174 |
1175 | $objULic = [PSCustomObject]@{
1176 | 'Total Users' = $AllUsers.Count
1177 | "Users with Passwords Expiring in less than $DaysUntilPWExpireINT days" = $PasswordExpireSoonTable.Count
1178 | 'Expiring Accounts' = "0"
1179 | "Users Haven't Logged on in $Days Days or more" = $UHLONXD
1180 | }
1181 | $TOPUserTable.Add($objULic)
1182 | }
1183 |
1184 | Write-Host "Done!" -ForegroundColor White
1185 | <###########################
1186 |
1187 | Group Policy
1188 |
1189 | ############################>
1190 | Write-Host "Working on Group Policy Report..." -ForegroundColor Green
1191 |
1192 | $GPOTable = New-Object 'System.Collections.Generic.List[System.Object]'
1193 |
1194 | foreach ($GPO in $GPOs)
1195 | {
1196 |
1197 | $obj = [PSCustomObject]@{
1198 |
1199 | 'Name' = $GPO.DisplayName
1200 | 'Status' = $GPO.GpoStatus
1201 | 'Modified Date' = $GPO.ModificationTime
1202 | 'User Version' = $GPO.UserVersion
1203 | 'Computer Version' = $GPO.ComputerVersion
1204 | }
1205 |
1206 | $GPOTable.Add($obj)
1207 | }
1208 | if (($GPOTable).Count -eq 0)
1209 | {
1210 |
1211 | $Obj = [PSCustomObject]@{
1212 |
1213 | Information = 'Information: No Group Policy Obejects were found'
1214 | }
1215 | $GPOTable.Add($obj)
1216 | }
1217 | Write-Host "Done!" -ForegroundColor White
1218 | <###########################
1219 |
1220 | Computers
1221 |
1222 | ############################>
1223 | Write-Host "Working on Computers Report..." -ForegroundColor Green
1224 |
1225 | $Computers = Get-ADComputer -Filter * -Properties *
1226 | $ComputersProtected = 0
1227 | $ComputersNotProtected = 0
1228 | $ComputerEnabled = 0
1229 | $ComputerDisabled = 0
1230 | #Only search for versions of windows that exist in the Environment
1231 | $WindowsRegex = "(Windows (Server )?(\d+|XP)?( R2)?).*"
1232 | $OsVersions = $Computers | Select-Object OperatingSystem -unique | ForEach-Object {
1233 | if ($_.OperatingSystem -match $WindowsRegex ){
1234 | return $matches[1]
1235 | } elseif ($_.OperatingSystem -ne $null) {
1236 | return $_.OperatingSystem
1237 | }
1238 | } | Select-Object -unique | Sort-Object
1239 |
1240 | $OsObj = [PSCustomObject]@{}
1241 |
1242 | $OsVersions | ForEach-Object {
1243 |
1244 | $OsObj | Add-Member -Name $_ -Value 0 -Type NoteProperty
1245 |
1246 | }
1247 |
1248 | foreach ($Computer in $Computers)
1249 | {
1250 |
1251 | if ($Computer.ProtectedFromAccidentalDeletion -eq $True)
1252 | {
1253 |
1254 | $ComputersProtected++
1255 | }
1256 |
1257 | else
1258 | {
1259 |
1260 | $ComputersNotProtected++
1261 | }
1262 |
1263 | if ($Computer.Enabled -eq $True)
1264 | {
1265 |
1266 | $ComputerEnabled++
1267 | }
1268 |
1269 | else
1270 | {
1271 |
1272 | $ComputerDisabled++
1273 | }
1274 |
1275 | $obj = [PSCustomObject]@{
1276 |
1277 | 'Name' = $Computer.Name
1278 | 'Enabled' = $Computer.Enabled
1279 | 'Operating System' = $Computer.OperatingSystem
1280 | 'Modified Date' = $Computer.Modified
1281 | 'Password Last Set' = $Computer.PasswordLastSet
1282 | 'Protect from Deletion' = $Computer.ProtectedFromAccidentalDeletion
1283 | }
1284 |
1285 | $ComputersTable.Add($obj)
1286 |
1287 | if ($Computer.OperatingSystem -match $WindowsRegex)
1288 | {
1289 | $OsObj."$($matches[1])"++
1290 | }
1291 |
1292 | }
1293 |
1294 | if (($ComputersTable).Count -eq 0)
1295 | {
1296 |
1297 | $Obj = [PSCustomObject]@{
1298 |
1299 | Information = 'Information: No computers were found'
1300 | }
1301 | $ComputersTable.Add($obj)
1302 | }
1303 |
1304 | #Pie chart breaking down OS for computer obj
1305 | $OsObj.PSObject.Properties | ForEach-Object {
1306 | $GraphComputerOS.Add([PSCustomObject]@{'Name' = $_.Name;"Count" =$_.Value})
1307 | }
1308 |
1309 | #Data for TOP Computers data table
1310 | $OsObj | Add-Member -Name 'Total Computers' -Value $Computers.Count -Type NoteProperty
1311 |
1312 | $TOPComputersTable.Add($OsObj)
1313 |
1314 |
1315 | #Data for protected Computers pie graph
1316 | $objULic = [PSCustomObject]@{
1317 |
1318 | 'Name' = 'Protected'
1319 | 'Count' = $ComputerProtected
1320 | }
1321 |
1322 | $ComputerProtectedTable.Add($objULic)
1323 |
1324 | $objULic = [PSCustomObject]@{
1325 |
1326 | 'Name' = 'Not Protected'
1327 | 'Count' = $ComputersNotProtected
1328 | }
1329 |
1330 | $ComputerProtectedTable.Add($objULic)
1331 |
1332 | #Data for enabled/vs Computers pie graph
1333 | $objULic = [PSCustomObject]@{
1334 |
1335 | 'Name' = 'Enabled'
1336 | 'Count' = $ComputerEnabled
1337 | }
1338 |
1339 | $ComputersEnabledTable.Add($objULic)
1340 |
1341 | $objULic = [PSCustomObject]@{
1342 |
1343 | 'Name' = 'Disabled'
1344 | 'Count' = $ComputerDisabled
1345 | }
1346 |
1347 | $ComputersEnabledTable.Add($objULic)
1348 |
1349 | Write-Host "Done!" -ForegroundColor White
1350 |
1351 | Write-Host "Working on VMware Report..." -ForegroundColor Green
1352 |
1353 | $VCenterServer = $NULL
1354 | if ($VCenterServer -eq $NULL)
1355 | { $VCenterServer = Read-Host -Prompt 'No hard-coded vCenter server name in script, prompting interactively for vCenter Server Name' }
1356 |
1357 | Connect-ViServer $VCenterServer
1358 | $MasterVMList = Get-VM
1359 |
1360 | $AllVirtualMachines = $MasterVMList | select Name,Guest,NumCPU,MemoryGB,ProvisionedSpaceGB,VMHost
1361 | $AllVirtualMachines | % {
1362 |
1363 | $obj = [PSCustomObject]@{
1364 | 'Name' = $_.Name
1365 | 'Guest' = $_.Guest
1366 | 'NumCPU' = $_.NumCPU
1367 | 'MemoryGB' = $_.MemoryGB
1368 | 'ProvisionedSpaceGB' = $_.ProvisionedSpaceGB
1369 | 'VMHost' = $_.VMHost
1370 | }
1371 | $VmwareVmList.Add($obj)}
1372 |
1373 | $OutofDate = $MasterVMList | where {$_.PowerState -ne "PoweredOff" -and $_.ExtensionData.Guest.ToolsStatus -ne "toolsOk"}
1374 | $ResultantSet = @($OutofDate | select Name,Guest,@{Name="ToolsVersion";Expression={$_.ExtensionData.Guest.Toolsversion}})
1375 | $ResultantSet | % {
1376 |
1377 | $obj = [PSCustomObject]@{
1378 | 'Name' = $_.Name
1379 | 'Guest' = $_.Guest
1380 | 'ToolsVersion' = $_.ToolsVersion
1381 | }
1382 |
1383 | $OutdatedVMwareTools.Add($obj);
1384 | }
1385 |
1386 | If (($OutdatedVMwareTools).count -eq 0)
1387 | {
1388 | $OutdatedVMwareTools = [PSCustomObject]@{
1389 | 'Information' = 'All virtual machines have up-to-date VMWare Tools installations'
1390 | }
1391 | }
1392 |
1393 | $Snapshots = $MasterVMList | Get-Snapshot | select Guest,NumCPU,MemoryGB,ProvisionedSpaceGB
1394 |
1395 | $Snapshots | % {
1396 |
1397 | $obj = [PSCustomObject]@{
1398 | 'Guest' = $_.Guest
1399 | 'NumcPU' = $_.NumcPU
1400 | 'MemoryGB' = $_.MemoryGB
1401 | 'ProvisionedSpaceGB'= $_.ProvisionedSpaceGB
1402 | }
1403 |
1404 | $OpenSnapshotTable.Add($obj);
1405 | }
1406 |
1407 | If (($OpenSnapshotTable).count -eq 0)
1408 | {
1409 | $OpenSnapshotTable = [PSCustomObject]@{
1410 | 'Information' = 'There are no open VMWare Snapshots'
1411 | }
1412 | }
1413 |
1414 | $AllDatastores = Get-Datastore | select Name, FreeSpaceGB, CapacityGB
1415 |
1416 | $AllDatastores | % {
1417 |
1418 | $obj = [PSCustomObject]@{
1419 | 'Name' = $_.Name
1420 | 'FreeSpaceGB' = $_.FreeSpaceGB
1421 | 'CapacityGB' = $_.CapacityGB
1422 | }
1423 |
1424 | $DatastoreTable.Add($obj);
1425 | }
1426 |
1427 | If (($DatastoreTable).count -eq 0)
1428 | {
1429 | $DatastoreTable = [PSCustomObject]@{
1430 | 'Information' = 'No datastores were found in the virtual infrastructure'
1431 | }
1432 | }
1433 |
1434 | $AllPortGroups = Get-VirtualPortGroup | select Name, VLanID, VirtualSwitch
1435 |
1436 | $AllPortGroups | % {
1437 |
1438 | $obj = [PSCustomObject]@{
1439 | 'Name' = $_.Name
1440 | 'VLanID' = $_.VLanID
1441 | 'VirtualSwitch' = $_.VirtualSwitch
1442 | }
1443 |
1444 | $PortGroupTable.Add($obj);
1445 | }
1446 |
1447 | If (($PortGroupTable).count -eq 0)
1448 | {
1449 | $PortGroupTable = [PSCustomObject]@{
1450 | 'Information' = 'No port groups were found in the virtual infrastructure'
1451 | }
1452 | }
1453 |
1454 | $AllVcenterAlarms = Get-VIEvent | select Username, FullFormattedMessage, CreatedTime
1455 |
1456 | $AllVcenterAlarms | % {
1457 |
1458 | $obj = [PSCustomObject]@{
1459 | 'Username' = $_.Username
1460 | 'FullFormattedMessage' = $_.FullFormattedMessage
1461 | 'CreatedTime' = $_.CreatedTime
1462 |
1463 | }
1464 |
1465 | $VcenterAlarmTable.Add($obj);
1466 | }
1467 |
1468 | If (($VcenterAlarmTable).count -eq 0)
1469 | {
1470 | $VcenterAlarmTable = [PSCustomObject]@{
1471 | 'Information' = 'No recent vCenter alarms found.'
1472 | }
1473 | }
1474 |
1475 | Write-Host "Done!" -ForegroundColor White
1476 |
1477 | $tabarray = @('Dashboard', 'Groups', 'Organizational Units', 'Users', 'Group Policy', 'Computers', 'VM Infrastructure')
1478 |
1479 | Write-Host "Compiling Report..." -ForegroundColor Green
1480 |
1481 | ##--OU Protection PIE CHART--##
1482 | #Basic Properties
1483 | $PO12 = Get-HTMLPieChartObject
1484 | $PO12.Title = "Organizational Units Protected from Deletion"
1485 | $PO12.Size.Height = 250
1486 | $PO12.Size.width = 250
1487 | $PO12.ChartStyle.ChartType = 'doughnut'
1488 |
1489 | #These file exist in the module directoy, There are 4 schemes by default
1490 | $PO12.ChartStyle.ColorSchemeName = "ColorScheme3"
1491 |
1492 | #There are 8 generated schemes, randomly generated at runtime
1493 | $PO12.ChartStyle.ColorSchemeName = "Generated3"
1494 |
1495 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1496 | $PO12.ChartStyle.ColorSchemeName = 'Random'
1497 |
1498 | #Data defintion you can reference any column from name and value from the dataset.
1499 | #Name and Count are the default to work with the Group function.
1500 | $PO12.DataDefinition.DataNameColumnName = 'Name'
1501 | $PO12.DataDefinition.DataValueColumnName = 'Count'
1502 |
1503 | ##--Computer OS Breakdown PIE CHART--##
1504 | $PieObjectComputerObjOS = Get-HTMLPieChartObject
1505 | $PieObjectComputerObjOS.Title = "Computer Operating Systems"
1506 |
1507 | #These file exist in the module directoy, There are 4 schemes by default
1508 | $PieObjectComputerObjOS.ChartStyle.ColorSchemeName = "ColorScheme3"
1509 |
1510 | #There are 8 generated schemes, randomly generated at runtime
1511 | $PieObjectComputerObjOS.ChartStyle.ColorSchemeName = "Generated3"
1512 |
1513 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1514 | $PieObjectComputerObjOS.ChartStyle.ColorSchemeName = 'Random'
1515 |
1516 | ##--Computers Protection PIE CHART--##
1517 | #Basic Properties
1518 | $PieObjectComputersProtected = Get-HTMLPieChartObject
1519 | $PieObjectComputersProtected.Title = "Computers Protected from Deletion"
1520 | $PieObjectComputersProtected.Size.Height = 250
1521 | $PieObjectComputersProtected.Size.width = 250
1522 | $PieObjectComputersProtected.ChartStyle.ChartType = 'doughnut'
1523 |
1524 | #These file exist in the module directoy, There are 4 schemes by default
1525 | $PieObjectComputersProtected.ChartStyle.ColorSchemeName = "ColorScheme3"
1526 |
1527 | #There are 8 generated schemes, randomly generated at runtime
1528 | $PieObjectComputersProtected.ChartStyle.ColorSchemeName = "Generated3"
1529 |
1530 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1531 | $PieObjectComputersProtected.ChartStyle.ColorSchemeName = 'Random'
1532 |
1533 | #Data defintion you can reference any column from name and value from the dataset.
1534 | #Name and Count are the default to work with the Group function.
1535 | $PieObjectComputersProtected.DataDefinition.DataNameColumnName = 'Name'
1536 | $PieObjectComputersProtected.DataDefinition.DataValueColumnName = 'Count'
1537 |
1538 | ##--Computers Enabled PIE CHART--##
1539 | #Basic Properties
1540 | $PieObjectComputersEnabled = Get-HTMLPieChartObject
1541 | $PieObjectComputersEnabled.Title = "Computers Enabled vs Disabled"
1542 | $PieObjectComputersEnabled.Size.Height = 250
1543 | $PieObjectComputersEnabled.Size.width = 250
1544 | $PieObjectComputersEnabled.ChartStyle.ChartType = 'doughnut'
1545 |
1546 | #These file exist in the module directoy, There are 4 schemes by default
1547 | $PieObjectComputersEnabled.ChartStyle.ColorSchemeName = "ColorScheme3"
1548 |
1549 | #There are 8 generated schemes, randomly generated at runtime
1550 | $PieObjectComputersEnabled.ChartStyle.ColorSchemeName = "Generated3"
1551 |
1552 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1553 | $PieObjectComputersEnabled.ChartStyle.ColorSchemeName = 'Random'
1554 |
1555 | #Data defintion you can reference any column from name and value from the dataset.
1556 | #Name and Count are the default to work with the Group function.
1557 | $PieObjectComputersEnabled.DataDefinition.DataNameColumnName = 'Name'
1558 | $PieObjectComputersEnabled.DataDefinition.DataValueColumnName = 'Count'
1559 |
1560 | ##--USERS Protection PIE CHART--##
1561 | #Basic Properties
1562 | $PieObjectProtectedUsers = Get-HTMLPieChartObject
1563 | $PieObjectProtectedUsers.Title = "Users Protected from Deletion"
1564 | $PieObjectProtectedUsers.Size.Height = 250
1565 | $PieObjectProtectedUsers.Size.width = 250
1566 | $PieObjectProtectedUsers.ChartStyle.ChartType = 'doughnut'
1567 |
1568 | #These file exist in the module directoy, There are 4 schemes by default
1569 | $PieObjectProtectedUsers.ChartStyle.ColorSchemeName = "ColorScheme3"
1570 |
1571 | #There are 8 generated schemes, randomly generated at runtime
1572 | $PieObjectProtectedUsers.ChartStyle.ColorSchemeName = "Generated3"
1573 |
1574 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1575 | $PieObjectProtectedUsers.ChartStyle.ColorSchemeName = 'Random'
1576 |
1577 | #Data defintion you can reference any column from name and value from the dataset.
1578 | #Name and Count are the default to work with the Group function.
1579 | $PieObjectProtectedUsers.DataDefinition.DataNameColumnName = 'Name'
1580 | $PieObjectProtectedUsers.DataDefinition.DataValueColumnName = 'Count'
1581 |
1582 | #Basic Properties
1583 | $PieObjectOUGPOLinks = Get-HTMLPieChartObject
1584 | $PieObjectOUGPOLinks.Title = "OU GPO Links"
1585 | $PieObjectOUGPOLinks.Size.Height = 250
1586 | $PieObjectOUGPOLinks.Size.width = 250
1587 | $PieObjectOUGPOLinks.ChartStyle.ChartType = 'doughnut'
1588 |
1589 | #These file exist in the module directoy, There are 4 schemes by default
1590 | $PieObjectOUGPOLinks.ChartStyle.ColorSchemeName = "ColorScheme4"
1591 |
1592 | #There are 8 generated schemes, randomly generated at runtime
1593 | $PieObjectOUGPOLinks.ChartStyle.ColorSchemeName = "Generated5"
1594 |
1595 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1596 | $PieObjectOUGPOLinks.ChartStyle.ColorSchemeName = 'Random'
1597 |
1598 | #Data defintion you can reference any column from name and value from the dataset.
1599 | #Name and Count are the default to work with the Group function.
1600 | $PieObjectOUGPOLinks.DataDefinition.DataNameColumnName = 'Name'
1601 | $PieObjectOUGPOLinks.DataDefinition.DataValueColumnName = 'Count'
1602 |
1603 | #Basic Properties
1604 | $PieObject4 = Get-HTMLPieChartObject
1605 | $PieObject4.Title = "Office 365 Unassigned Licenses"
1606 | $PieObject4.Size.Height = 250
1607 | $PieObject4.Size.width = 250
1608 | $PieObject4.ChartStyle.ChartType = 'doughnut'
1609 |
1610 | #These file exist in the module directoy, There are 4 schemes by default
1611 | $PieObject4.ChartStyle.ColorSchemeName = "ColorScheme4"
1612 |
1613 | #There are 8 generated schemes, randomly generated at runtime
1614 | $PieObject4.ChartStyle.ColorSchemeName = "Generated4"
1615 |
1616 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1617 | $PieObject4.ChartStyle.ColorSchemeName = 'Random'
1618 |
1619 | #Data defintion you can reference any column from name and value from the dataset.
1620 | #Name and Count are the default to work with the Group function.
1621 | $PieObject4.DataDefinition.DataNameColumnName = 'Name'
1622 | $PieObject4.DataDefinition.DataValueColumnName = 'Unassigned Licenses'
1623 |
1624 | #Basic Properties
1625 | $PieObjectGroupType = Get-HTMLPieChartObject
1626 | $PieObjectGroupType.Title = "Group Types"
1627 | $PieObjectGroupType.Size.Height = 250
1628 | $PieObjectGroupType.Size.width = 250
1629 | $PieObjectGroupType.ChartStyle.ChartType = 'doughnut'
1630 |
1631 | #Pie Chart Groups with members vs no members
1632 | $PieObjectGroupMembersType = Get-HTMLPieChartObject
1633 | $PieObjectGroupMembersType.Title = "Group Membership"
1634 | $PieObjectGroupMembersType.Size.Height = 250
1635 | $PieObjectGroupMembersType.Size.width = 250
1636 | $PieObjectGroupMembersType.ChartStyle.ChartType = 'doughnut'
1637 | $PieObjectGroupMembersType.ChartStyle.ColorSchemeName = "ColorScheme4"
1638 | $PieObjectGroupMembersType.ChartStyle.ColorSchemeName = "Generated8"
1639 | $PieObjectGroupMembersType.ChartStyle.ColorSchemeName = 'Random'
1640 | $PieObjectGroupMembersType.DataDefinition.DataNameColumnName = 'Name'
1641 | $PieObjectGroupMembersType.DataDefinition.DataValueColumnName = 'Count'
1642 |
1643 | #Basic Properties
1644 | $PieObjectGroupType2 = Get-HTMLPieChartObject
1645 | $PieObjectGroupType2.Title = "Custom vs Default Groups"
1646 | $PieObjectGroupType2.Size.Height = 250
1647 | $PieObjectGroupType2.Size.width = 250
1648 | $PieObjectGroupType2.ChartStyle.ChartType = 'doughnut'
1649 |
1650 | #These file exist in the module directoy, There are 4 schemes by default
1651 | $PieObjectGroupType.ChartStyle.ColorSchemeName = "ColorScheme4"
1652 |
1653 | #There are 8 generated schemes, randomly generated at runtime
1654 | $PieObjectGroupType.ChartStyle.ColorSchemeName = "Generated8"
1655 |
1656 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1657 | $PieObjectGroupType.ChartStyle.ColorSchemeName = 'Random'
1658 |
1659 | #Data defintion you can reference any column from name and value from the dataset.
1660 | #Name and Count are the default to work with the Group function.
1661 | $PieObjectGroupType.DataDefinition.DataNameColumnName = 'Name'
1662 | $PieObjectGroupType.DataDefinition.DataValueColumnName = 'Count'
1663 |
1664 | ##--Enabled users vs Disabled Users PIE CHART--##
1665 | #Basic Properties
1666 | $EnabledDisabledUsersPieObject = Get-HTMLPieChartObject
1667 | $EnabledDisabledUsersPieObject.Title = "Enabled vs Disabled Users"
1668 | $EnabledDisabledUsersPieObject.Size.Height = 250
1669 | $EnabledDisabledUsersPieObject.Size.width = 250
1670 | $EnabledDisabledUsersPieObject.ChartStyle.ChartType = 'doughnut'
1671 |
1672 | #These file exist in the module directoy, There are 4 schemes by default
1673 | $EnabledDisabledUsersPieObject.ChartStyle.ColorSchemeName = "ColorScheme3"
1674 |
1675 | #There are 8 generated schemes, randomly generated at runtime
1676 | $EnabledDisabledUsersPieObject.ChartStyle.ColorSchemeName = "Generated3"
1677 |
1678 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1679 | $EnabledDisabledUsersPieObject.ChartStyle.ColorSchemeName = 'Random'
1680 |
1681 | #Data defintion you can reference any column from name and value from the dataset.
1682 | #Name and Count are the default to work with the Group function.
1683 | $EnabledDisabledUsersPieObject.DataDefinition.DataNameColumnName = 'Name'
1684 | $EnabledDisabledUsersPieObject.DataDefinition.DataValueColumnName = 'Count'
1685 |
1686 | ##--PasswordNeverExpires PIE CHART--##
1687 | #Basic Properties
1688 | $PWExpiresUsersTable = Get-HTMLPieChartObject
1689 | $PWExpiresUsersTable.Title = "Password Expiration"
1690 | $PWExpiresUsersTable.Size.Height = 250
1691 | $PWExpiresUsersTable.Size.Width = 250
1692 | $PWExpiresUsersTable.ChartStyle.ChartType = 'doughnut'
1693 |
1694 | #These file exist in the module directoy, There are 4 schemes by default
1695 | $PWExpiresUsersTable.ChartStyle.ColorSchemeName = "ColorScheme3"
1696 |
1697 | #There are 8 generated schemes, randomly generated at runtime
1698 | $PWExpiresUsersTable.ChartStyle.ColorSchemeName = "Generated3"
1699 |
1700 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1701 | $PWExpiresUsersTable.ChartStyle.ColorSchemeName = 'Random'
1702 |
1703 | #Data defintion you can reference any column from name and value from the dataset.
1704 | #Name and Count are the default to work with the Group function.
1705 | $PWExpiresUsersTable.DataDefinition.DataNameColumnName = 'Name'
1706 | $PWExpiresUsersTable.DataDefinition.DataValueColumnName = 'Count'
1707 |
1708 | ##--Group Protection PIE CHART--##
1709 | #Basic Properties
1710 | $PieObjectGroupProtection = Get-HTMLPieChartObject
1711 | $PieObjectGroupProtection.Title = "Groups Protected from Deletion"
1712 | $PieObjectGroupProtection.Size.Height = 250
1713 | $PieObjectGroupProtection.Size.width = 250
1714 | $PieObjectGroupProtection.ChartStyle.ChartType = 'doughnut'
1715 |
1716 | #These file exist in the module directoy, There are 4 schemes by default
1717 | $PieObjectGroupProtection.ChartStyle.ColorSchemeName = "ColorScheme3"
1718 |
1719 | #There are 8 generated schemes, randomly generated at runtime
1720 | $PieObjectGroupProtection.ChartStyle.ColorSchemeName = "Generated3"
1721 |
1722 | #you can also ask for a random scheme. Which also happens ifyou have too many records for the scheme
1723 | $PieObjectGroupProtection.ChartStyle.ColorSchemeName = 'Random'
1724 |
1725 | #Data defintion you can reference any column from name and value from the dataset.
1726 | #Name and Count are the default to work with the Group function.
1727 | $PieObjectGroupProtection.DataDefinition.DataNameColumnName = 'Name'
1728 | $PieObjectGroupProtection.DataDefinition.DataValueColumnName = 'Count'
1729 |
1730 | #Dashboard Report
1731 | $FinalReport = New-Object 'System.Collections.Generic.List[System.Object]'
1732 | $FinalReport.Add($(Get-HTMLOpenPage -TitleText $ReportTitle -LeftLogoString $CompanyLogo -RightLogoString $RightLogo))
1733 | $FinalReport.Add($(Get-HTMLTabHeader -TabNames $tabarray))
1734 | $FinalReport.Add($(Get-HTMLTabContentopen -TabName $tabarray[0] -TabHeading ("Report: " + (Get-Date -Format MM-dd-yyyy))))
1735 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Company Information"))
1736 | $FinalReport.Add($(Get-HTMLContentTable $CompanyInfoTable))
1737 | $FinalReport.Add($(Get-HTMLContentClose))
1738 |
1739 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Groups"))
1740 | $FinalReport.Add($(Get-HTMLColumn1of2))
1741 | $FinalReport.Add($(Get-HTMLContentOpen -BackgroundShade 1 -HeaderText 'Domain Administrators'))
1742 | $FinalReport.Add($(Get-HTMLContentDataTable $DomainAdminTable -HideFooter))
1743 | $FinalReport.Add($(Get-HTMLContentClose))
1744 | $FinalReport.Add($(Get-HTMLColumnClose))
1745 | $FinalReport.Add($(Get-HTMLColumn2of2))
1746 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText 'Enterprise Administrators'))
1747 | $FinalReport.Add($(Get-HTMLContentDataTable $EnterpriseAdminTable -HideFooter))
1748 | $FinalReport.Add($(Get-HTMLContentClose))
1749 | $FinalReport.Add($(Get-HTMLColumnClose))
1750 | $FinalReport.Add($(Get-HTMLContentClose))
1751 |
1752 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Objects in Default OUs"))
1753 | $FinalReport.Add($(Get-HTMLColumn1of2))
1754 | $FinalReport.Add($(Get-HTMLContentOpen -BackgroundShade 1 -HeaderText 'Computers'))
1755 | $FinalReport.Add($(Get-HTMLContentDataTable $DefaultComputersinDefaultOUTable -HideFooter))
1756 | $FinalReport.Add($(Get-HTMLContentClose))
1757 | $FinalReport.Add($(Get-HTMLColumnClose))
1758 | $FinalReport.Add($(Get-HTMLColumn2of2))
1759 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText 'Users'))
1760 | $FinalReport.Add($(Get-HTMLContentDataTable $DefaultUsersinDefaultOUTable -HideFooter))
1761 | $FinalReport.Add($(Get-HTMLContentClose))
1762 | $FinalReport.Add($(Get-HTMLColumnClose))
1763 | $FinalReport.Add($(Get-HTMLContentClose))
1764 |
1765 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "AD Objects Modified in Last $ADModNumber Days"))
1766 | $FinalReport.Add($(Get-HTMLContentDataTable $ADObjectTable))
1767 | $FinalReport.Add($(Get-HTMLContentClose))
1768 |
1769 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Expiring Items"))
1770 | $FinalReport.Add($(Get-HTMLColumn1of2))
1771 | $FinalReport.Add($(Get-HTMLContentOpen -BackgroundShade 1 -HeaderText "Users with Passwords Expiring in less than $DaysUntilPWExpireINT days"))
1772 | $FinalReport.Add($(Get-HTMLContentDataTable $PasswordExpireSoonTable -HideFooter))
1773 | $FinalReport.Add($(Get-HTMLContentClose))
1774 | $FinalReport.Add($(Get-HTMLColumnClose))
1775 | $FinalReport.Add($(Get-HTMLColumn2of2))
1776 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText 'Accounts Expiring Soon'))
1777 | $FinalReport.Add($(Get-HTMLContentDataTable $ExpiringAccountsTable -HideFooter))
1778 | $FinalReport.Add($(Get-HTMLContentClose))
1779 | $FinalReport.Add($(Get-HTMLColumnClose))
1780 | $FinalReport.Add($(Get-HTMLContentClose))
1781 |
1782 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Accounts"))
1783 | $FinalReport.Add($(Get-HTMLColumn1of2))
1784 | $FinalReport.Add($(Get-HTMLContentOpen -BackgroundShade 1 -HeaderText "Users Haven't Logged on in $Days Days or more"))
1785 | $FinalReport.Add($(Get-HTMLContentDataTable $userphaventloggedonrecentlytable -HideFooter))
1786 | $FinalReport.Add($(Get-HTMLContentClose))
1787 | $FinalReport.Add($(Get-HTMLColumnClose))
1788 | $FinalReport.Add($(Get-HTMLColumn2of2))
1789 | $FinalReport.Add($(Get-HTMLContentOpen -BackgroundShade 1 -HeaderText "Accounts Created in $UserCreatedDays Days or Less"))
1790 | $FinalReport.Add($(Get-HTMLContentDataTable $NewCreatedUsersTable -HideFooter))
1791 | $FinalReport.Add($(Get-HTMLContentClose))
1792 | $FinalReport.Add($(Get-HTMLColumnClose))
1793 | $FinalReport.Add($(Get-HTMLContentClose))
1794 |
1795 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Security Logs"))
1796 | $FinalReport.Add($(Get-HTMLContentDataTable $securityeventtable -HideFooter))
1797 | $FinalReport.Add($(Get-HTMLContentClose))
1798 |
1799 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "UPN Suffixes"))
1800 | $FinalReport.Add($(Get-HTMLContentTable $DomainTable))
1801 | $FinalReport.Add($(Get-HTMLContentClose))
1802 | $FinalReport.Add($(Get-HTMLTabContentClose))
1803 |
1804 | #Groups Report
1805 | $FinalReport.Add($(Get-HTMLTabContentopen -TabName $tabarray[1] -TabHeading ("Report: " + (Get-Date -Format MM-dd-yyyy))))
1806 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Groups Overivew"))
1807 | $FinalReport.Add($(Get-HTMLContentTable $TOPGroupsTable -HideFooter))
1808 | $FinalReport.Add($(Get-HTMLContentClose))
1809 |
1810 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Active Directory Groups"))
1811 | $FinalReport.Add($(Get-HTMLContentDataTable $Table -HideFooter))
1812 | $FinalReport.Add($(Get-HTMLContentClose))
1813 | $FinalReport.Add($(Get-HTMLColumn1of2))
1814 |
1815 | $FinalReport.Add($(Get-HTMLContentOpen -BackgroundShade 1 -HeaderText 'Domain Administrators'))
1816 | $FinalReport.Add($(Get-HTMLContentDataTable $DomainAdminTable -HideFooter))
1817 | $FinalReport.Add($(Get-HTMLContentClose))
1818 | $FinalReport.Add($(Get-HTMLColumnClose))
1819 | $FinalReport.Add($(Get-HTMLColumn2of2))
1820 |
1821 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText 'Enterprise Administrators'))
1822 | $FinalReport.Add($(Get-HTMLContentDataTable $EnterpriseAdminTable -HideFooter))
1823 | $FinalReport.Add($(Get-HTMLContentClose))
1824 | $FinalReport.Add($(Get-HTMLColumnClose))
1825 |
1826 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Active Directory Groups Chart"))
1827 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 1 -ColumnCount 4))
1828 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PieObjectGroupType -DataSet $GroupTypetable))
1829 | $FinalReport.Add($(Get-HTMLColumnClose))
1830 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 2 -ColumnCount 4))
1831 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PieObjectGroupType2 -DataSet $DefaultGrouptable))
1832 | $FinalReport.Add($(Get-HTMLColumnClose))
1833 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 3 -ColumnCount 4))
1834 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PieObjectGroupMembersType -DataSet $GroupMembershipTable))
1835 | $FinalReport.Add($(Get-HTMLColumnClose))
1836 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 4 -ColumnCount 4))
1837 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PieObjectGroupProtection -DataSet $GroupProtectionTable))
1838 | $FinalReport.Add($(Get-HTMLColumnClose))
1839 | $FinalReport.Add($(Get-HTMLContentClose))
1840 | $FinalReport.Add($(Get-HTMLTabContentClose))
1841 |
1842 | #Organizational Unit Report
1843 | $FinalReport.Add($(Get-HTMLTabContentopen -TabName $tabarray[2] -TabHeading ("Report: " + (Get-Date -Format MM-dd-yyyy))))
1844 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Organizational Units"))
1845 | $FinalReport.Add($(Get-HTMLContentDataTable $OUTable -HideFooter))
1846 | $FinalReport.Add($(Get-HTMLContentClose))
1847 |
1848 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Organizational Units Charts"))
1849 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 1 -ColumnCount 2))
1850 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PieObjectOUGPOLinks -DataSet $OUGPOTable))
1851 | $FinalReport.Add($(Get-HTMLColumnClose))
1852 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 2 -ColumnCount 2))
1853 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PO12 -DataSet $OUProtectionTable))
1854 | $FinalReport.Add($(Get-HTMLColumnClose))
1855 | $FinalReport.Add($(Get-HTMLContentclose))
1856 | $FinalReport.Add($(Get-HTMLTabContentClose))
1857 |
1858 | #Users Report
1859 | $FinalReport.Add($(Get-HTMLTabContentopen -TabName $tabarray[3] -TabHeading ("Report: " + (Get-Date -Format MM-dd-yyyy))))
1860 |
1861 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Users Overivew"))
1862 | $FinalReport.Add($(Get-HTMLContentTable $TOPUserTable -HideFooter))
1863 | $FinalReport.Add($(Get-HTMLContentClose))
1864 |
1865 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Active Directory Users"))
1866 | $FinalReport.Add($(Get-HTMLContentDataTable $UserTable -HideFooter))
1867 | $FinalReport.Add($(Get-HTMLContentClose))
1868 |
1869 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Expiring Items"))
1870 | $FinalReport.Add($(Get-HTMLColumn1of2))
1871 | $FinalReport.Add($(Get-HTMLContentOpen -BackgroundShade 1 -HeaderText "Users with Passwords Expiring in less than $DaysUntilPWExpireINT days"))
1872 | $FinalReport.Add($(Get-HTMLContentDataTable $PasswordExpireSoonTable -HideFooter))
1873 | $FinalReport.Add($(Get-HTMLContentClose))
1874 | $FinalReport.Add($(Get-HTMLColumnClose))
1875 | $FinalReport.Add($(Get-HTMLColumn2of2))
1876 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText 'Accounts Expiring Soon'))
1877 | $FinalReport.Add($(Get-HTMLContentDataTable $ExpiringAccountsTable -HideFooter))
1878 | $FinalReport.Add($(Get-HTMLContentClose))
1879 | $FinalReport.Add($(Get-HTMLColumnClose))
1880 | $FinalReport.Add($(Get-HTMLContentClose))
1881 |
1882 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Accounts"))
1883 | $FinalReport.Add($(Get-HTMLColumn1of2))
1884 | $FinalReport.Add($(Get-HTMLContentOpen -BackgroundShade 1 -HeaderText "Users Haven't Logged on in $Days Days or more"))
1885 | $FinalReport.Add($(Get-HTMLContentDataTable $userphaventloggedonrecentlytable -HideFooter))
1886 | $FinalReport.Add($(Get-HTMLContentClose))
1887 | $FinalReport.Add($(Get-HTMLColumnClose))
1888 | $FinalReport.Add($(Get-HTMLColumn2of2))
1889 |
1890 | $FinalReport.Add($(Get-HTMLContentOpen -BackgroundShade 1 -HeaderText "Accounts Created in $UserCreatedDays Days or Less"))
1891 | $FinalReport.Add($(Get-HTMLContentDataTable $NewCreatedUsersTable -HideFooter))
1892 | $FinalReport.Add($(Get-HTMLContentClose))
1893 | $FinalReport.Add($(Get-HTMLColumnClose))
1894 | $FinalReport.Add($(Get-HTMLContentClose))
1895 |
1896 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Users Charts"))
1897 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 1 -ColumnCount 3))
1898 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $EnabledDisabledUsersPieObject -DataSet $EnabledDisabledUsersTable))
1899 | $FinalReport.Add($(Get-HTMLColumnClose))
1900 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 2 -ColumnCount 3))
1901 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PWExpiresUsersTable -DataSet $PasswordExpirationTable))
1902 | $FinalReport.Add($(Get-HTMLColumnClose))
1903 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 3 -ColumnCount 3))
1904 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PieObjectProtectedUsers -DataSet $ProtectedUsersTable))
1905 | $FinalReport.Add($(Get-HTMLColumnClose))
1906 | $FinalReport.Add($(Get-HTMLContentClose))
1907 | $FinalReport.Add($(Get-HTMLTabContentClose))
1908 |
1909 | #GPO Report
1910 | $FinalReport.Add($(Get-HTMLTabContentopen -TabName $tabarray[4] -TabHeading ("Report: " + (Get-Date -Format MM-dd-yyyy))))
1911 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Group Policies"))
1912 | $FinalReport.Add($(Get-HTMLContentDataTable $GPOTable -HideFooter))
1913 | $FinalReport.Add($(Get-HTMLContentClose))
1914 | $FinalReport.Add($(Get-HTMLTabContentClose))
1915 |
1916 | #Computers Report
1917 | $FinalReport.Add($(Get-HTMLTabContentopen -TabName $tabarray[5] -TabHeading ("Report: " + (Get-Date -Format MM-dd-yyyy))))
1918 |
1919 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Computers Overivew"))
1920 | $FinalReport.Add($(Get-HTMLContentTable $TOPComputersTable -HideFooter))
1921 | $FinalReport.Add($(Get-HTMLContentClose))
1922 |
1923 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Computers"))
1924 | $FinalReport.Add($(Get-HTMLContentDataTable $ComputersTable -HideFooter))
1925 | $FinalReport.Add($(Get-HTMLContentClose))
1926 |
1927 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Computers Charts"))
1928 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 1 -ColumnCount 2))
1929 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PieObjectComputersProtected -DataSet $ComputerProtectedTable))
1930 | $FinalReport.Add($(Get-HTMLColumnClose))
1931 | $FinalReport.Add($(Get-HTMLColumnOpen -ColumnNumber 2 -ColumnCount 2))
1932 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PieObjectComputersEnabled -DataSet $ComputersEnabledTable))
1933 | $FinalReport.Add($(Get-HTMLColumnClose))
1934 | $FinalReport.Add($(Get-HTMLContentclose))
1935 |
1936 | $FinalReport.Add($(Get-HTMLContentOpen -HeaderText "Computers Operating System Breakdown"))
1937 | $FinalReport.Add($(Get-HTMLPieChart -ChartObject $PieObjectComputerObjOS -DataSet $GraphComputerOS))
1938 | $FinalReport.Add($(Get-HTMLContentclose))
1939 |
1940 | $FinalReport.Add($(Get-HTMLTabContentClose))
1941 |
1942 | $FinalReport += get-htmltabcontentopen -TabName $tabarray[6] -TabHeading ("Report: " + (Get-Date -Format MM-dd-yyyy))
1943 |
1944 | $FinalReport += Get-HtmlContentOpen -HeaderText "Virtual Machines"
1945 | $FinalReport += get-htmlColumn1of2
1946 | $FinalReport += Get-HtmlContentOpen -BackgroundShade 1 -HeaderText 'All Virtual Machines'
1947 | $FinalReport += get-htmlcontentdatatable $VmwareVmList -HideFooter
1948 | $FinalReport += Get-HtmlContentClose
1949 | $FinalReport += get-htmlColumnClose
1950 |
1951 | $FinalReport += get-htmlColumn2of2
1952 | $FinalReport += Get-HtmlContentOpen -HeaderText 'Outdated VMWare Tools'
1953 | $FinalReport += get-htmlcontentdatatable $OutdatedVMwareTools -HideFooter
1954 | $FinalReport += Get-HtmlContentClose
1955 | $FinalReport += Get-HtmlContentOpen -HeaderText 'Open VMWare Snapshots'
1956 | $FinalReport += get-htmlcontentdatatable $OpenSnapshotTable -HideFooter
1957 | $FinalReport += Get-HtmlContentClose
1958 | $FinalReport += Get-HtmlContentOpen -HeaderText 'ESXi Hosts'
1959 | $FinalReport += get-htmlcontentdatatable $EsxiHostTable -HideFooter
1960 | $FinalReport += Get-HtmlContentClose
1961 | $FinalReport += get-htmlColumnClose
1962 |
1963 | $FinalReport += Get-HTMLContentOpen -HeaderText "Networking and Storage"
1964 |
1965 | $FinalReport += Get-HTMLColumnOpen -ColumnNumber 1 -ColumnCount 2
1966 | $FinalReport += Get-HtmlContentOpen -HeaderText 'Port Groups and VLANs'
1967 | $FinalReport += get-htmlcontentdatatable $PortGroupTable -HideFooter
1968 | $FinalReport += Get-HtmlContentClose
1969 | $FinalReport += get-htmlColumnClose
1970 |
1971 |
1972 | $FinalReport += Get-HTMLColumnOpen -ColumnNumber 2 -ColumnCount 2
1973 | $FinalReport += Get-HtmlContentOpen -HeaderText 'Datastores'
1974 | $FinalReport += get-htmlcontentdatatable $DatastoreTable -HideFooter
1975 | $FinalReport += Get-HtmlContentClose
1976 | $FinalReport += Get-HtmlContentClose
1977 | $FinalReport += get-htmlColumnClose
1978 |
1979 | $FinalReport += Get-HtmlContentClose
1980 |
1981 | $FinalReport += Get-HTMLContentOpen -HeaderText "vCenter Alarms"
1982 | $FinalReport += Get-HtmlContentOpen -HeaderText 'Recent VCenter Alarms'
1983 | $FinalReport += get-htmlcontentdatatable $VcenterAlarmTable -HideFooter
1984 | $FinalReport += Get-HtmlContentClose
1985 | $FinalReport += Get-HtmlContentClose
1986 |
1987 | $FinalReport += get-htmltabcontentclose
1988 |
1989 | $FinalReport.Add($(Get-HTMLClosePage))
1990 |
1991 | $Day = (Get-Date).Day
1992 | $Month = (Get-Date).Month
1993 | $Year = (Get-Date).Year
1994 | $ReportName = ("$Day - $Month - $Year - AD Report")
1995 |
1996 | Save-HTMLReport -ReportContent $FinalReport -ShowReport -ReportName $ReportName -ReportPath $ReportSavePath
1997 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Additional VMWare Reporting for PSHTML-AD-Report
2 |
3 | This fork of the PSHTML-AD-Report project adds functionality to the existing report tool so that various metrics can be collected from VMWare infrastructures.
4 |
5 | The resulting report will contain the Active Directory reporting provided by the base project [bwya77/PSHTML-AD-REPORT](https://github.com/bwya77/PSHTML-AD-Report), with a new tab in the report that provides reporting on various VMWare metrics obtained from vCenter.
6 |
7 | This script is designed to run from a secure jump station or other secure origin that has read access to both vCenter and Active Directory.
8 |
9 | The additional tab introduced will contain the following VMWare metrics:
10 |
11 | * List of all VMs
12 | * List of open snapshosts
13 | * List of VMs with outdated VMware tools
14 | * List of all datastores (current capacity, max capacity)
15 | * List of all port groups
16 | * List of all ESXi hosts
17 |
--------------------------------------------------------------------------------