PSWinDocumentation.AD.psm1
function Clear-DataInformation { [CmdletBinding()] param([System.Collections.IDictionary] $Data, [Array] $TypesRequired, [switch] $DontRemoveSupportData, [switch] $DontRemoveEmpty) foreach ($Domain in $Data.FoundDomains.Keys) { $RemoveDomainKeys = foreach ($Key in $Data.FoundDomains.$Domain.Keys) { if ($null -eq $Data.FoundDomains.$Domain.$Key) { if (-not $DontRemoveEmpty) { $Key } continue } if ($Key -notin $TypesRequired -and $DontRemoveSupportData -eq $false) { $Key } } foreach ($Key in $RemoveDomainKeys) { $Data.FoundDomains.$Domain.Remove($Key) } } $RemoveDomains = foreach ($Domain in $Data.FoundDomains.Keys) { if ($Data.FoundDomains.$Domain.Count -eq 0) { $Domain } } foreach ($Domain in $RemoveDomains) { $Data.FoundDomains.Remove($Domain) } if ($Data.FoundDomains.Count -eq 0) { $Data.Remove('FoundDomains') } $RemoveKeys = foreach ($Key in $Data.Keys) { if ($Key -eq 'FoundDomains') { continue } if ($null -eq $Data.$Key) { if (-not $DontRemoveEmpty) { $Key } continue } if ($Key -notin $TypesRequired -and $DontRemoveSupportData -eq $false) { $Key } } foreach ($Key in $RemoveKeys) { $Data.Remove($Key) } } function ConvertFrom-DistinguishedName { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER DistinguishedName Parameter description .PARAMETER ToOrganizationalUnit Parameter description .PARAMETER ToDC Parameter description .PARAMETER ToDomainCN Parameter description .EXAMPLE $DistinguishedName = 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' ConvertFrom-DistinguishedName -DistinguishedName $DistinguishedName -ToOrganizationalUnit Output: OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz .EXAMPLE $DistinguishedName = 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' ConvertFrom-DistinguishedName -DistinguishedName $DistinguishedName Output: Przemyslaw Klys .NOTES General notes #> [CmdletBinding()] param([alias('Identity', 'DN')][Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName, Position = 0)][string[]] $DistinguishedName, [switch] $ToOrganizationalUnit, [switch] $ToDC, [switch] $ToDomainCN) process { foreach ($Distinguished in $DistinguishedName) { if ($ToDomainCN) { $DN = $Distinguished -replace '.*?((DC=[^=]+,)+DC=[^=]+)$', '$1' $CN = $DN -replace ',DC=', '.' -replace "DC=" $CN } elseif ($ToOrganizationalUnit) { [Regex]::Match($Distinguished, '(?=OU=)(.*\n?)(?<=.)').Value } elseif ($ToDC) { $Distinguished -replace '.*?((DC=[^=]+,)+DC=[^=]+)$', '$1' } else { $Regex = '^CN=(?<cn>.+?)(?<!\\),(?<ou>(?:(?:OU|CN).+?(?<!\\),)+(?<dc>DC.+?))$' $Output = foreach ($_ in $Distinguished) { $_ -match $Regex $Matches } $Output.cn } } } } function Convert-TimeToDays { [CmdletBinding()] param ($StartTime, $EndTime, [string] $Ignore = '*1601*') if ($null -ne $StartTime -and $null -ne $EndTime) { try { if ($StartTime -notlike $Ignore -and $EndTime -notlike $Ignore) { $Days = (New-TimeSpan -Start $StartTime -End $EndTime).Days } } catch {} } elseif ($null -ne $EndTime) { if ($StartTime -notlike $Ignore -and $EndTime -notlike $Ignore) { $Days = (New-TimeSpan -Start (Get-Date) -End ($EndTime)).Days } } elseif ($null -ne $StartTime) { if ($StartTime -notlike $Ignore -and $EndTime -notlike $Ignore) { $Days = (New-TimeSpan -Start $StartTime -End (Get-Date)).Days } } return $Days } function Convert-ToDateTime { [CmdletBinding()] param ([string] $Timestring, [string] $Ignore = '*1601*') Try { $DateTime = ([datetime]::FromFileTime($Timestring)) } catch { $DateTime = $null } if ($null -eq $DateTime -or $DateTime -like $Ignore) { return $null } else { return $DateTime } } function ConvertTo-OperatingSystem { <# .SYNOPSIS Allows easy conversion of OperatingSystem, Operating System Version to proper Windows 10 naming based on WMI or AD .DESCRIPTION Allows easy conversion of OperatingSystem, Operating System Version to proper Windows 10 naming based on WMI or AD .PARAMETER OperatingSystem Operating System as returned by Active Directory .PARAMETER OperatingSystemVersion Operating System Version as returned by Active Directory .EXAMPLE $Computers = Get-ADComputer -Filter * -Properties OperatingSystem, OperatingSystemVersion | ForEach-Object { $OPS = ConvertTo-OperatingSystem -OperatingSystem $_.OperatingSystem -OperatingSystemVersion $_.OperatingSystemVersion Add-Member -MemberType NoteProperty -Name 'OperatingSystemTranslated' -Value $OPS -InputObject $_ -Force $_ } $Computers | Select-Object DNS*, Name, SamAccountName, Enabled, OperatingSystem*, DistinguishedName | Format-Table .NOTES General notes #> [CmdletBinding()] param([string] $OperatingSystem, [string] $OperatingSystemVersion) if ($OperatingSystem -like '*Windows 10*') { $Systems = @{'10.0 (19041)' = 'Windows 10 2004' '10.0 (18363)' = "Windows 10 1909" '10.0 (18362)' = "Windows 10 1903" '10.0 (17763)' = "Windows 10 1809" '10.0 (17134)' = "Windows 10 1803" '10.0 (16299)' = "Windows 10 1709" '10.0 (15063)' = "Windows 10 1703" '10.0 (14393)' = "Windows 10 1607" '10.0 (10586)' = "Windows 10 1511" '10.0 (10240)' = "Windows 10 1507" '10.0 (18898)' = 'Windows 10 Insider Preview' '10.0.19041' = 'Windows 10 2004' '10.0.18363' = "Windows 10 1909" '10.0.18362' = "Windows 10 1903" '10.0.17763' = "Windows 10 1809" '10.0.17134' = "Windows 10 1803" '10.0.16299' = "Windows 10 1709" '10.0.15063' = "Windows 10 1703" '10.0.14393' = "Windows 10 1607" '10.0.10586' = "Windows 10 1511" '10.0.10240' = "Windows 10 1507" '10.0.18898' = 'Windows 10 Insider Preview' } $System = $Systems[$OperatingSystemVersion] if (-not $System) { $System = $OperatingSystem } } elseif ($OperatingSystem -like '*Windows Server*') { $Systems = @{'5.2 (3790)' = 'Windows Server 2003' '6.1 (7601)' = 'Windows Server 2008 R2' '10.0 (18362)' = "Windows Server, version 1903 (Semi-Annual Channel) 1903" '10.0 (17763)' = "Windows Server 2019 (Long-Term Servicing Channel) 1809" '10.0 (17134)' = "Windows Server, version 1803 (Semi-Annual Channel) 1803" '10.0 (14393)' = "Windows Server 2016 (Long-Term Servicing Channel) 1607" '10.0.18362' = "Windows Server, version 1903 (Semi-Annual Channel) 1903" '10.0.17763' = "Windows Server 2019 (Long-Term Servicing Channel) 1809" '10.0.17134' = "Windows Server, version 1803 (Semi-Annual Channel) 1803" '10.0.14393' = "Windows Server 2016 (Long-Term Servicing Channel) 1607" } $System = $Systems[$OperatingSystemVersion] if (-not $System) { $System = $OperatingSystem } } else { $System = $OperatingSystem } if ($System) { $System } else { 'Unknown' } } function Find-TypesNeeded { [CmdletBinding()] param ([Array] $TypesRequired, [Array] $TypesNeeded) [bool] $Found = $False foreach ($Type in $TypesNeeded) { if ($TypesRequired -contains $Type) { $Found = $true break } } return $Found } function Get-DataInformation { [CmdletBinding()] param([ScriptBlock] $Content, [string] $Text, [Array] $TypesRequired, [Array] $TypesNeeded, [Array] $Commands, [switch] $SkipAvailability) if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded $TypesNeeded) { Write-Verbose -Message $Text $Time = Start-TimeLog if ($Commands.Count -gt 0 -and -not $SkipAvailability) { $Available = Test-AvailabilityCommands -Commands $Commands if ($Available -contains $false) { $EndTime = Stop-TimeLog -Time $Time -Option OneLiner Write-Warning "Get-DataInformation - Commands $($Commands -join ", ") is/are not available. Data gathering skipped." Write-Verbose "$Text - Time: $EndTime" return } } if ($null -ne $Content) { & $Content } $EndTime = Stop-TimeLog -Time $Time -Option OneLiner Write-Verbose "$Text - Time: $EndTime" } } function Get-ObjectCount { [CmdletBinding()] param([parameter(ValueFromPipelineByPropertyName, ValueFromPipeline)][Object]$Object) return $($Object | Measure-Object).Count } function Get-Types { [CmdletBinding()] param ([Object] $Types) $TypesRequired = foreach ($Type in $Types) { $Type.GetEnumValues() } return $TypesRequired } function Get-WinADForestGUIDs { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Domain Parameter description .PARAMETER RootDSE Parameter description .PARAMETER DisplayNameKey Parameter description .EXAMPLE Get-WinADForestGUIDs .EXAMPLE Get-WinADForestGUIDs -DisplayNameKey .NOTES General notes #> [alias('Get-WinADDomainGUIDs')] [cmdletbinding()] param([string] $Domain = $Env:USERDNSDOMAIN, [Microsoft.ActiveDirectory.Management.ADEntity] $RootDSE, [switch] $DisplayNameKey) if ($null -eq $RootDSE) { $RootDSE = Get-ADRootDSE -Server $Domain } $GUID = @{} $GUID.Add('00000000-0000-0000-0000-000000000000', 'All') $Schema = Get-ADObject -SearchBase $RootDSE.schemaNamingContext -LDAPFilter '(schemaIDGUID=*)' -Properties name, schemaIDGUID foreach ($S in $Schema) { if ($DisplayNameKey) { $GUID["$($S.name)"] = $(([System.GUID]$S.schemaIDGUID).Guid) } else { $GUID["$(([System.GUID]$S.schemaIDGUID).Guid)"] = $S.name } } $Extended = Get-ADObject -SearchBase "CN=Extended-Rights,$($RootDSE.configurationNamingContext)" -LDAPFilter '(objectClass=controlAccessRight)' -Properties name, rightsGUID foreach ($S in $Extended) { if ($DisplayNameKey) { $GUID["$($S.name)"] = $(([System.GUID]$S.rightsGUID).Guid) } else { $GUID["$(([System.GUID]$S.rightsGUID).Guid)"] = $S.name } } return $GUID } function Get-WinADForestControllers { [alias('Get-WinADDomainControllers')] <# .SYNOPSIS .DESCRIPTION Long description .PARAMETER TestAvailability Parameter description .EXAMPLE Get-WinADForestControllers -TestAvailability | Format-Table .EXAMPLE Get-WinADDomainControllers .EXAMPLE Get-WinADDomainControllers | Format-Table * Output: Domain HostName Forest IPV4Address IsGlobalCatalog IsReadOnly SchemaMaster DomainNamingMasterMaster PDCEmulator RIDMaster InfrastructureMaster Comment ------ -------- ------ ----------- --------------- ---------- ------------ ------------------------ ----------- --------- -------------------- ------- ad.evotec.xyz AD1.ad.evotec.xyz ad.evotec.xyz 192.168.240.189 True False True True True True True ad.evotec.xyz AD2.ad.evotec.xyz ad.evotec.xyz 192.168.240.192 True False False False False False False ad.evotec.pl ad.evotec.xyz False False False False False Unable to contact the server. This may be becau... .NOTES General notes #> [CmdletBinding()] param([string[]] $Domain, [switch] $TestAvailability, [switch] $SkipEmpty) try { $Forest = Get-ADForest if (-not $Domain) { $Domain = $Forest.Domains } } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning "Get-WinADForestControllers - Couldn't use Get-ADForest feature. Error: $ErrorMessage" return } $Servers = foreach ($D in $Domain) { try { $LocalServer = Get-ADDomainController -Discover -DomainName $D -ErrorAction Stop $DC = Get-ADDomainController -Server $LocalServer.HostName[0] -Filter * -ErrorAction Stop foreach ($S in $DC) { $Server = [ordered] @{Domain = $D HostName = $S.HostName Name = $S.Name Forest = $Forest.RootDomain IPV4Address = $S.IPV4Address IPV6Address = $S.IPV6Address IsGlobalCatalog = $S.IsGlobalCatalog IsReadOnly = $S.IsReadOnly Site = $S.Site SchemaMaster = ($S.OperationMasterRoles -contains 'SchemaMaster') DomainNamingMaster = ($S.OperationMasterRoles -contains 'DomainNamingMaster') PDCEmulator = ($S.OperationMasterRoles -contains 'PDCEmulator') RIDMaster = ($S.OperationMasterRoles -contains 'RIDMaster') InfrastructureMaster = ($S.OperationMasterRoles -contains 'InfrastructureMaster') LdapPort = $S.LdapPort SslPort = $S.SslPort Pingable = $null Comment = '' } if ($TestAvailability) { $Server['Pingable'] = foreach ($_ in $Server.IPV4Address) { Test-Connection -Count 1 -Server $_ -Quiet -ErrorAction SilentlyContinue } } [PSCustomObject] $Server } } catch { [PSCustomObject]@{Domain = $D HostName = '' Name = '' Forest = $Forest.RootDomain IPV4Address = '' IPV6Address = '' IsGlobalCatalog = '' IsReadOnly = '' Site = '' SchemaMaster = $false DomainNamingMasterMaster = $false PDCEmulator = $false RIDMaster = $false InfrastructureMaster = $false LdapPort = '' SslPort = '' Pingable = $null Comment = $_.Exception.Message -replace "`n", " " -replace "`r", " " } } } if ($SkipEmpty) { return $Servers | Where-Object { $_.HostName -ne '' } } return $Servers } function Get-WinADForestDetails { [CmdletBinding()] param([alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [string[]] $ExcludeDomainControllers, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [alias('DomainControllers', 'ComputerName')][string[]] $IncludeDomainControllers, [switch] $SkipRODC, [string] $Filter = '*', [switch] $TestAvailability, [ValidateSet('All', 'Ping', 'WinRM', 'PortOpen', 'Ping+WinRM', 'Ping+PortOpen', 'WinRM+PortOpen')] $Test = 'All', [int[]] $Ports = 135, [int] $PortsTimeout = 100, [int] $PingCount = 1, [switch] $Extended, [System.Collections.IDictionary] $ExtendedForestInformation) if ($Global:ProgressPreference -ne 'SilentlyContinue') { $TemporaryProgress = $Global:ProgressPreference $Global:ProgressPreference = 'SilentlyContinue' } if (-not $ExtendedForestInformation) { $Findings = [ordered] @{} try { if ($Forest) { $ForestInformation = Get-ADForest -ErrorAction Stop -Identity $Forest } else { $ForestInformation = Get-ADForest -ErrorAction Stop } } catch { Write-Warning "Get-WinADForestDetails - Error discovering DC for Forest - $($_.Exception.Message)" return } if (-not $ForestInformation) { return } $Findings['Forest'] = $ForestInformation $Findings['ForestDomainControllers'] = @() $Findings['QueryServers'] = @{} $Findings['DomainDomainControllers'] = @{} [Array] $Findings['Domains'] = foreach ($_ in $ForestInformation.Domains) { if ($IncludeDomains) { if ($_ -in $IncludeDomains) { $_.ToLower() } continue } if ($_ -notin $ExcludeDomains) { $_.ToLower() } } foreach ($Domain in $ForestInformation.Domains) { try { $DC = Get-ADDomainController -DomainName $Domain -Discover -ErrorAction Stop $OrderedDC = [ordered] @{Domain = $DC.Domain Forest = $DC.Forest HostName = [Array] $DC.HostName IPv4Address = $DC.IPv4Address IPv6Address = $DC.IPv6Address Name = $DC.Name Site = $DC.Site } } catch { Write-Warning "Get-WinADForestDetails - Error discovering DC for domain $Domain - $($_.Exception.Message)" continue } if ($Domain -eq $Findings['Forest']['Name']) { $Findings['QueryServers']['Forest'] = $OrderedDC } $Findings['QueryServers']["$Domain"] = $OrderedDC } [Array] $Findings['ForestDomainControllers'] = foreach ($Domain in $Findings.Domains) { $QueryServer = $Findings['QueryServers'][$Domain]['HostName'][0] [Array] $AllDC = try { try { $DomainControllers = Get-ADDomainController -Filter $Filter -Server $QueryServer -ErrorAction Stop } catch { Write-Warning "Get-WinADForestDetails - Error listing DCs for domain $Domain - $($_.Exception.Message)" continue } foreach ($S in $DomainControllers) { if ($IncludeDomainControllers.Count -gt 0) { If (-not $IncludeDomainControllers[0].Contains('.')) { if ($S.Name -notin $IncludeDomainControllers) { continue } } else { if ($S.HostName -notin $IncludeDomainControllers) { continue } } } if ($ExcludeDomainControllers.Count -gt 0) { If (-not $ExcludeDomainControllers[0].Contains('.')) { if ($S.Name -in $ExcludeDomainControllers) { continue } } else { if ($S.HostName -in $ExcludeDomainControllers) { continue } } } $Server = [ordered] @{Domain = $Domain HostName = $S.HostName Name = $S.Name Forest = $ForestInformation.RootDomain Site = $S.Site IPV4Address = $S.IPV4Address IPV6Address = $S.IPV6Address IsGlobalCatalog = $S.IsGlobalCatalog IsReadOnly = $S.IsReadOnly IsSchemaMaster = ($S.OperationMasterRoles -contains 'SchemaMaster') IsDomainNamingMaster = ($S.OperationMasterRoles -contains 'DomainNamingMaster') IsPDC = ($S.OperationMasterRoles -contains 'PDCEmulator') IsRIDMaster = ($S.OperationMasterRoles -contains 'RIDMaster') IsInfrastructureMaster = ($S.OperationMasterRoles -contains 'InfrastructureMaster') OperatingSystem = $S.OperatingSystem OperatingSystemVersion = $S.OperatingSystemVersion OperatingSystemLong = ConvertTo-OperatingSystem -OperatingSystem $S.OperatingSystem -OperatingSystemVersion $S.OperatingSystemVersion LdapPort = $S.LdapPort SslPort = $S.SslPort DistinguishedName = $S.ComputerObjectDN Pingable = $null WinRM = $null PortOpen = $null Comment = '' } if ($TestAvailability) { if ($Test -eq 'All' -or $Test -like 'Ping*') { $Server.Pingable = Test-Connection -ComputerName $Server.IPV4Address -Quiet -Count $PingCount } if ($Test -eq 'All' -or $Test -like '*WinRM*') { $Server.WinRM = (Test-WinRM -ComputerName $Server.HostName).Status } if ($Test -eq 'All' -or '*PortOpen*') { $Server.PortOpen = (Test-ComputerPort -Server $Server.HostName -PortTCP $Ports -Timeout $PortsTimeout).Status } } [PSCustomObject] $Server } } catch { [PSCustomObject]@{Domain = $Domain HostName = '' Name = '' Forest = $ForestInformation.RootDomain IPV4Address = '' IPV6Address = '' IsGlobalCatalog = '' IsReadOnly = '' Site = '' SchemaMaster = $false DomainNamingMasterMaster = $false PDCEmulator = $false RIDMaster = $false InfrastructureMaster = $false LdapPort = '' SslPort = '' DistinguishedName = '' Pingable = $null WinRM = $null PortOpen = $null Comment = $_.Exception.Message -replace "`n", " " -replace "`r", " " } } if ($SkipRODC) { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC | Where-Object { $_.IsReadOnly -eq $false } } else { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC } [Array] $Findings['DomainDomainControllers'][$Domain] } if ($Extended) { $Findings['DomainsExtended'] = @{} $Findings['DomainsExtendedNetBIOS'] = @{} foreach ($DomainEx in $Findings['Domains']) { try { $Findings['DomainsExtended'][$DomainEx] = Get-ADDomain -Server $Findings['QueryServers'][$DomainEx].HostName[0] | ForEach-Object { [ordered] @{AllowedDNSSuffixes = $_.AllowedDNSSuffixes | ForEach-Object -Process { $_ } ChildDomains = $_.ChildDomains | ForEach-Object -Process { $_ } ComputersContainer = $_.ComputersContainer DeletedObjectsContainer = $_.DeletedObjectsContainer DistinguishedName = $_.DistinguishedName DNSRoot = $_.DNSRoot DomainControllersContainer = $_.DomainControllersContainer DomainMode = $_.DomainMode DomainSID = $_.DomainSID.Value ForeignSecurityPrincipalsContainer = $_.ForeignSecurityPrincipalsContainer Forest = $_.Forest InfrastructureMaster = $_.InfrastructureMaster LastLogonReplicationInterval = $_.LastLogonReplicationInterval LinkedGroupPolicyObjects = $_.LinkedGroupPolicyObjects | ForEach-Object -Process { $_ } LostAndFoundContainer = $_.LostAndFoundContainer ManagedBy = $_.ManagedBy Name = $_.Name NetBIOSName = $_.NetBIOSName ObjectClass = $_.ObjectClass ObjectGUID = $_.ObjectGUID ParentDomain = $_.ParentDomain PDCEmulator = $_.PDCEmulator PublicKeyRequiredPasswordRolling = $_.PublicKeyRequiredPasswordRolling | ForEach-Object -Process { $_ } QuotasContainer = $_.QuotasContainer ReadOnlyReplicaDirectoryServers = $_.ReadOnlyReplicaDirectoryServers | ForEach-Object -Process { $_ } ReplicaDirectoryServers = $_.ReplicaDirectoryServers | ForEach-Object -Process { $_ } RIDMaster = $_.RIDMaster SubordinateReferences = $_.SubordinateReferences | ForEach-Object -Process { $_ } SystemsContainer = $_.SystemsContainer UsersContainer = $_.UsersContainer } } $NetBios = $Findings['DomainsExtended'][$DomainEx]['NetBIOSName'] $Findings['DomainsExtendedNetBIOS'][$NetBios] = $Findings['DomainsExtended'][$DomainEx] } catch { Write-Warning "Get-WinADForestDetails - Error gathering Domain Information for domain $DomainEx - $($_.Exception.Message)" continue } } } if ($TemporaryProgress) { $Global:ProgressPreference = $TemporaryProgress } $Findings } else { $Findings = Copy-DictionaryManual -Dictionary $ExtendedForestInformation [Array] $Findings['Domains'] = foreach ($_ in $Findings.Domains) { if ($IncludeDomains) { if ($_ -in $IncludeDomains) { $_.ToLower() } continue } if ($_ -notin $ExcludeDomains) { $_.ToLower() } } foreach ($_ in [string[]] $Findings.DomainDomainControllers.Keys) { if ($_ -notin $Findings.Domains) { $Findings.DomainDomainControllers.Remove($_) } } foreach ($_ in [string[]] $Findings.DomainsExtended.Keys) { if ($_ -notin $Findings.Domains) { $Findings.DomainsExtended.Remove($_) $NetBiosName = $Findings.DomainsExtended.$_.'NetBIOSName' if ($NetBiosName) { $Findings.DomainsExtendedNetBIOS.Remove($NetBiosName) } } } [Array] $Findings['ForestDomainControllers'] = foreach ($Domain in $Findings.Domains) { [Array] $AllDC = foreach ($S in $Findings.DomainDomainControllers["$Domain"]) { if ($IncludeDomainControllers.Count -gt 0) { If (-not $IncludeDomainControllers[0].Contains('.')) { if ($S.Name -notin $IncludeDomainControllers) { continue } } else { if ($S.HostName -notin $IncludeDomainControllers) { continue } } } if ($ExcludeDomainControllers.Count -gt 0) { If (-not $ExcludeDomainControllers[0].Contains('.')) { if ($S.Name -in $ExcludeDomainControllers) { continue } } else { if ($S.HostName -in $ExcludeDomainControllers) { continue } } } $S } if ($SkipRODC) { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC | Where-Object { $_.IsReadOnly -eq $false } } else { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC } [Array] $Findings['DomainDomainControllers'][$Domain] } $Findings } } function Start-TimeLog { [CmdletBinding()] param() [System.Diagnostics.Stopwatch]::StartNew() } function Stop-TimeLog { [CmdletBinding()] param ([Parameter(ValueFromPipeline = $true)][System.Diagnostics.Stopwatch] $Time, [ValidateSet('OneLiner', 'Array')][string] $Option = 'OneLiner', [switch] $Continue) Begin {} Process { if ($Option -eq 'Array') { $TimeToExecute = "$($Time.Elapsed.Days) days", "$($Time.Elapsed.Hours) hours", "$($Time.Elapsed.Minutes) minutes", "$($Time.Elapsed.Seconds) seconds", "$($Time.Elapsed.Milliseconds) milliseconds" } else { $TimeToExecute = "$($Time.Elapsed.Days) days, $($Time.Elapsed.Hours) hours, $($Time.Elapsed.Minutes) minutes, $($Time.Elapsed.Seconds) seconds, $($Time.Elapsed.Milliseconds) milliseconds" } } End { if (-not $Continue) { $Time.Stop() } return $TimeToExecute } } function Copy-DictionaryManual { [CmdletBinding()] param([System.Collections.IDictionary] $Dictionary) $clone = @{} foreach ($Key in $Dictionary.Keys) { $value = $Dictionary.$Key $clonedValue = switch ($Dictionary.$Key) { { $null -eq $_ } { $null continue } { $_ -is [System.Collections.IDictionary] } { Copy-DictionaryManual -Dictionary $_ continue } { $type = $_.GetType() $type.IsPrimitive -or $type.IsValueType -or $_ -is [string] } { $_ continue } default { $_ | Select-Object -Property * } } if ($value -is [System.Collections.IList]) { $clone[$Key] = @($clonedValue) } else { $clone[$Key] = $clonedValue } } $clone } function Test-AvailabilityCommands { [cmdletBinding()] param ([string[]] $Commands) $CommandsStatus = foreach ($Command in $Commands) { $Exists = Get-Command -Name $Command -ErrorAction SilentlyContinue if ($Exists) { Write-Verbose "Test-AvailabilityCommands - Command $Command is available." } else { Write-Verbose "Test-AvailabilityCommands - Command $Command is not available." } $Exists } return $CommandsStatus } function Test-ComputerPort { [CmdletBinding()] param ([alias('Server')][string[]] $ComputerName, [int[]] $PortTCP, [int[]] $PortUDP, [int]$Timeout = 5000) begin { if ($Global:ProgressPreference -ne 'SilentlyContinue') { $TemporaryProgress = $Global:ProgressPreference $Global:ProgressPreference = 'SilentlyContinue' } } process { foreach ($Computer in $ComputerName) { foreach ($P in $PortTCP) { $Output = [ordered] @{'ComputerName' = $Computer 'Port' = $P 'Protocol' = 'TCP' 'Status' = $null 'Summary' = $null 'Response' = $null } $TcpClient = Test-NetConnection -ComputerName $Computer -Port $P -InformationLevel Detailed -WarningAction SilentlyContinue if ($TcpClient.TcpTestSucceeded) { $Output['Status'] = $TcpClient.TcpTestSucceeded $Output['Summary'] = "TCP $P Successful" } else { $Output['Status'] = $false $Output['Summary'] = "TCP $P Failed" $Output['Response'] = $Warnings } [PSCustomObject]$Output } foreach ($P in $PortUDP) { $Output = [ordered] @{'ComputerName' = $Computer 'Port' = $P 'Protocol' = 'UDP' 'Status' = $null 'Summary' = $null } $UdpClient = [System.Net.Sockets.UdpClient]::new($Computer, $P) $UdpClient.Client.ReceiveTimeout = $Timeout $Encoding = [System.Text.ASCIIEncoding]::new() $byte = $Encoding.GetBytes("Evotec") [void]$UdpClient.Send($byte, $byte.length) $RemoteEndpoint = [System.Net.IPEndPoint]::new([System.Net.IPAddress]::Any, 0) try { $Bytes = $UdpClient.Receive([ref]$RemoteEndpoint) [string]$Data = $Encoding.GetString($Bytes) If ($Data) { $Output['Status'] = $true $Output['Summary'] = "UDP $P Successful" $Output['Response'] = $Data } } catch { $Output['Status'] = $false $Output['Summary'] = "UDP $P Failed" $Output['Response'] = $_.Exception.Message } $UdpClient.Close() $UdpClient.Dispose() [PSCustomObject]$Output } } } end { if ($TemporaryProgress) { $Global:ProgressPreference = $TemporaryProgress } } } function Test-WinRM { [CmdletBinding()] param ([alias('Server')][string[]] $ComputerName) $Output = foreach ($Computer in $ComputerName) { $Test = [PSCustomObject] @{Output = $null Status = $null ComputerName = $Computer } try { $Test.Output = Test-WSMan -ComputerName $Computer -ErrorAction Stop $Test.Status = $true } catch { $Test.Status = $false } $Test } $Output } Add-Type -TypeDefinition @" using System; namespace PSWinDocumentation { [Flags] public enum ActiveDirectory { // Forest Information - Section Main ForestInformation, ForestFSMO, ForestRoles, ForestGlobalCatalogs, ForestOptionalFeatures, ForestUPNSuffixes, ForestSPNSuffixes, ForestSites, ForestSites1, ForestSites2, ForestSubnets, ForestSubnets1, ForestSubnets2, ForestSiteLinks, ForestDomainControllers, ForestRootDSE, ForestSchemaPropertiesUsers, ForestSchemaPropertiesComputers, ForestReplication, // Domain Information - Section Main DomainRootDSE, DomainRIDs, DomainAuthenticationPolicies, // Not yet tested DomainAuthenticationPolicySilos, // Not yet tested DomainCentralAccessPolicies, // Not yet tested DomainCentralAccessRules, // Not yet tested DomainClaimTransformPolicies, // Not yet tested DomainClaimTypes, // Not yet tested DomainFineGrainedPolicies, DomainFineGrainedPoliciesUsers, DomainFineGrainedPoliciesUsersExtended, DomainGUIDS, DomainDNSSRV, DomainDNSA, DomainInformation, DomainControllers, DomainFSMO, DomainDefaultPasswordPolicy, DomainGroupPolicies, DomainGroupPoliciesDetails, DomainGroupPoliciesACL, DomainGroupPoliciesACLConsistency, DomainGroupPoliciesSysVol, DomainGroupPoliciesOwners, DomainGroupPoliciesWMI, DomainGroupPoliciesLinksSummary, DomainOrganizationalUnits, DomainOrganizationalUnitsBasicACL, DomainOrganizationalUnitsExtendedACL, DomainContainers, DomainTrustsClean, DomainTrusts, DomainWellKnownFolders, DomainBitlocker, DomainLAPS, // Domain Information - Group Data DomainGroupsFullList, // Contains all data DomainGroups, DomainGroupsMembers, DomainGroupsMembersRecursive, DomainGroupsSpecial, DomainGroupsSpecialMembers, DomainGroupsSpecialMembersRecursive, DomainGroupsPriviliged, DomainGroupsPriviligedMembers, DomainGroupsPriviligedMembersRecursive, // Domain Information - User Data DomainUsersFullList, // Contains all data DomainUsers, DomainUsersCount, DomainUsersAll, DomainUsersSystemAccounts, DomainUsersNeverExpiring, DomainUsersNeverExpiringInclDisabled, DomainUsersExpiredInclDisabled, DomainUsersExpiredExclDisabled, DomainAdministrators, DomainAdministratorsRecursive, DomainEnterpriseAdministrators, DomainEnterpriseAdministratorsRecursive, // Domain Information - Computer Data DomainComputersFullList, // Contains all data DomainComputersAll, DomainComputersAllBuildCount, DomainComputersAllCount, DomainComputers, DomainComputersCount, DomainServers, DomainServersCount, DomainComputersUnknown, DomainComputersUnknownCount, // This requires DSInstall PowerShell Module DomainPasswordDataUsers, // Gathers users data and their passwords DomainPasswordDataPasswords, // Compares Users Password with File DomainPasswordDataPasswordsHashes, // Compares Users Password with File HASH DomainPasswordClearTextPassword, // include both enabled / disabled accounts DomainPasswordClearTextPasswordEnabled, // include only enabled DomainPasswordClearTextPasswordDisabled, // include only disabled DomainPasswordLMHash, DomainPasswordEmptyPassword, DomainPasswordWeakPassword, DomainPasswordWeakPasswordEnabled, DomainPasswordWeakPasswordDisabled, DomainPasswordWeakPasswordList, // Password List from file.. DomainPasswordDefaultComputerPassword, DomainPasswordPasswordNotRequired, DomainPasswordPasswordNeverExpires, DomainPasswordSmartCardUsersWithPassword, DomainPasswordAESKeysMissing, DomainPasswordPreAuthNotRequired, DomainPasswordDESEncryptionOnly, DomainPasswordDelegatableAdmins, DomainPasswordDuplicatePasswordGroups, DomainPasswordHashesWeakPassword, DomainPasswordHashesWeakPasswordEnabled, DomainPasswordHashesWeakPasswordDisabled, DomainPasswordStats } } "@ function Get-ADObjectFromDNHash { [CmdletBinding()] param ( [string[]] $DistinguishedName, [hashtable] $ADCatalog, [string] $Type = '', [string] $Splitter # ', ' # Alternative for example [System.Environment]::NewLine ) if ($null -eq $DistinguishedName) { return } $FoundObjects = foreach ($DN in $DistinguishedName) { if ($Type -eq '') { $ADCatalog.$DN } else { $ADCatalog.$DN.$Type } } if ($Splitter) { return ($FoundObjects | Sort-Object) -join $Splitter } else { return $FoundObjects | Sort-Object } } function Get-WinADDomain { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN ) try { Get-ADDomain -Server $Domain -ErrorAction Stop } catch { $null } } function Get-WinADDomainAdministrators { [CmdletBinding()] param( [Array] $DomainGroupsMembers, $DomainInformation ) # $DomainGroupsMembers | Where-Object { $_.'Group SID' -eq $('{0}-512' -f $DomainInformation.DomainSID.Value) } | Select-Object * -Exclude Group*, 'High Privileged Group' $Members = foreach ($_ in $DomainGroupsMembers) { if ($_.'Group SID' -eq $('{0}-512' -f $DomainInformation.DomainSID.Value)) { $_ } } $Members | Select-Object * -Exclude Group*, 'High Privileged Group' } function Get-WinADDomainAdministratorsRecursive { [CmdletBinding()] param( [Array] $DomainGroupsMembersRecursive, $DomainInformation ) # $DomainGroupsMembersRecursive | Where-Object { $_.'Group SID' -eq $('{0}-512' -f $DomainInformation.DomainSID.Value) } | Select-Object * -Exclude Group*, 'High Privileged Group' $Members = foreach ($_ in $DomainGroupsMembersRecursive) { if ($_.'Group SID' -eq $('{0}-512' -f $DomainInformation.DomainSID.Value)) { $_ } } $Members | Select-Object * -Exclude Group*, 'High Privileged Group' } function Get-WinADDomainAllUsersCount { [CmdletBinding()] param( [Array] $DomainUsers, [Array] $DomainUsersAll, [Array] $DomainUsersExpiredExclDisabled, [Array] $DomainUsersExpiredInclDisabled, [Array] $DomainUsersNeverExpiring, [Array] $DomainUsersNeverExpiringInclDisabled, [Array] $DomainUsersSystemAccounts ) <# $DomainUsersCount = [ordered] @{ 'Users Count Incl. System' = Get-ObjectCount -Object $DomainUsers 'Users Count' = Get-ObjectCount -Object $DomainUsersAll 'Users Expired' = Get-ObjectCount -Object $DomainUsersExpiredExclDisabled 'Users Expired Incl. Disabled' = Get-ObjectCount -Object $DomainUsersExpiredInclDisabled 'Users Never Expiring' = Get-ObjectCount -Object $DomainUsersNeverExpiring 'Users Never Expiring Incl. Disabled' = Get-ObjectCount -Object $DomainUsersNeverExpiringInclDisabled 'Users System Accounts' = Get-ObjectCount -Object $DomainUsersSystemAccounts } #> $DomainUsersCount = [ordered] @{ 'Users Count Incl. System' = $DomainUsers.Count 'Users Count' = $DomainUsersAll.Count 'Users Expired' = $DomainUsersExpiredExclDisabled.Count 'Users Expired Incl. Disabled' = $DomainUsersExpiredInclDisabled.Count 'Users Never Expiring' = $DomainUsersNeverExpiring.Count 'Users Never Expiring Incl. Disabled' = $DomainUsersNeverExpiringInclDisabled.Count 'Users System Accounts' = $DomainUsersSystemAccounts.Count } return $DomainUsersCount } function Get-WinADDomainBitlocker { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN, [Array] $Computers ) $Properties = @( 'Name', 'OperatingSystem', 'DistinguishedName' ) if ($null -eq $Computers) { $Computers = Get-ADComputer -Filter * -Properties $Properties -Server $Domain } foreach ($Computer in $Computers) { try { $Bitlockers = Get-ADObject -Filter 'objectClass -eq "msFVE-RecoveryInformation"' -SearchBase $Computer.DistinguishedName -Properties 'WhenCreated', 'msFVE-RecoveryPassword' #| Sort-Object whenCreated -Descending #| Select-Object whenCreated, msFVE-RecoveryPassword } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " if ($ErrorMessage -like "*The supplied distinguishedName must belong to one of the following partition(s)*") { Write-Warning "Getting domain information - $Domain - Couldn't get Bitlocker information. Most likely not enabled." } else { Write-Warning "Getting domain information - $Domain - Couldn't get Bitlocker information. Error: $ErrorMessage" } return } foreach ($Bitlocker in $Bitlockers) { [PSCustomObject] @{ 'Name' = $Computer.Name 'Operating System' = $Computer.'OperatingSystem' 'Bitlocker Recovery Password' = $Bitlocker.'msFVE-RecoveryPassword' 'Bitlocker When' = $Bitlocker.WhenCreated 'DistinguishedName' = $Computer.'DistinguishedName' } } } } function Get-WinADDomainComputers { [CmdletBinding()] param( [Array] $DomainComputersAll ) #$DomainComputersAll | & { process { if ($_.OperatingSystem -notlike 'Windows Server*' -and $null -ne $_.OperatingSystem) { $_ } } } # | Where-Object { $_.OperatingSystem -notlike 'Windows Server*' -and $_.OperatingSystem -ne $null } foreach ($_ in $DomainComputersAll) { if ($_.OperatingSystem -notlike 'Windows Server*' -and $null -ne $_.OperatingSystem) { $_ } } } function Get-WinADDomainComputersAll { [CmdletBinding()] param( [Array] $DomainComputersFullList, [string] $Splitter, [System.Collections.IDictionary] $DomainObjects, [System.Collections.IDictionary] $DomainObjectsNetbios, [Object] $Domaininformation ) [DateTime] $CurrentDate = Get-Date foreach ($_ in $DomainComputersFullList) { $Manager = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $_.ManagedBy $Computer = [PSCustomObject] @{ SamAccountName = $_.SamAccountName Enabled = $_.Enabled OperatingSystem = $_.OperatingSystem PasswordLastSet = $_.PasswordLastSet 'PasswordLastChanged(Days)' = if ($null -ne $_.PasswordLastSet) { "$(-$($_.PasswordLastSet - $CurrentDate).Days)" } else { } IPv4Address = $_.IPv4Address IPv6Address = $_.IPv6Address Name = $_.Name DNSHostName = $_.DNSHostName 'Manager' = $Manager.Name 'ManagerEmail' = if ($Splitter -ne '') { $Manager.EmailAddress -join $Splitter } else { $Manager.EmailAddress } OperatingSystemVersion = $_.OperatingSystemVersion OperatingSystemHotfix = $_.OperatingSystemHotfix OperatingSystemServicePack = $_.OperatingSystemServicePack OperatingSystemBuild = ConvertTo-OperatingSystem -OperatingSystem $_.OperatingSystem -OperatingSystemVersion $_.OperatingSystemVersion PasswordNeverExpires = $_.PasswordNeverExpires PasswordNotRequired = $_.PasswordNotRequired UserPrincipalName = $_.UserPrincipalName LastLogonDate = $_.LastLogonDate 'LastLogonDate(Days)' = if ($null -ne $_.LastLogonDate) { "$(-$($_.LastLogonDate - $CurrentDate).Days)" } else { } LockedOut = $_.LockedOut LogonCount = $_.LogonCount CanonicalName = $_.CanonicalName SID = $_.SID Created = $_.Created Modified = $_.Modified Deleted = $_.Deleted "Protected" = $_.ProtectedFromAccidentalDeletion "PrimaryGroup" = (Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $_.PrimaryGroup -Type 'SamAccountName') "MemberOf" = (Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $_.MemberOf -Type 'SamAccountName' -Splitter $Splitter) } $Name = -join ($Domaininformation.NetBIOSName, "\", $Computer.SamAccountName) $DomainObjectsNetbios[$Name] = $Computer $Computer } } function Get-WinADDomainComputersAllBuildSummary { [CmdletBinding()] param( [Array] $DomainComputers, [switch] $Formatted ) if ($Formatted) { $DomainComputers | Group-Object -Property OperatingSystemBuild | Sort-Object -Property Name | ` Select-Object @{ L = 'System Name'; Expression = { if ($_.Name -ne '') { $_.Name } else { 'N/A' } } } , @{ L = 'System Count'; Expression = { $_.Count } } } else { $DomainComputers | Group-Object -Property OperatingSystemBuild | Sort-Object -Property Name } } function Get-WinADDomainComputersAllCount { [CmdletBinding()] param( [Array] $DomainComputersAll ) $DomainComputersAll | ` Group-Object -Property OperatingSystem | ` Select-Object @{ L = 'System Name'; Expression = { if ($_.Name -ne '') { $_.Name } else { 'Unknown' } } } , @{ L = 'System Count'; Expression = { $_.Count } } } function Get-WinADDomainComputersCount { [CmdletBinding()] param( [Array] $DomainComputers ) $DomainComputers | Group-Object -Property OperatingSystem | Select-Object @{ L = 'System Name'; Expression = { if ($_.Name -ne '') { $_.Name } else { 'N/A' } } } , @{ L = 'System Count'; Expression = { $_.Count } } } function Get-WinADDomainComputersFullList { [cmdletbinding()] param( [string] $Domain = $Env:USERDNSDOMAIN, [Array] $ForestSchemaComputers, [System.Collections.IDictionary] $DomainObjects, [int] $ResultPageSize = 500000 ) if ($Extended) { [string] $Properties = '*' } else { [string[]] $Properties = @( 'SamAccountName', 'Enabled', 'OperatingSystem', 'PasswordLastSet', 'IPv4Address', 'IPv6Address', 'Name', 'DNSHostName', 'ManagedBy', 'OperatingSystemVersion', 'OperatingSystemHotfix', 'OperatingSystemServicePack' , 'PasswordNeverExpires', 'PasswordNotRequired', 'UserPrincipalName', 'LastLogonDate', 'LockedOut', 'LogonCount', 'CanonicalName', 'SID', 'Created', 'Modified', 'Deleted', 'MemberOf', 'PrimaryGroup', 'ProtectedFromAccidentalDeletion' if ($ForestSchemaComputers.Name -contains 'ms-Mcs-AdmPwd') { 'ms-Mcs-AdmPwd' 'ms-Mcs-AdmPwdExpirationTime' } ) } $Computers = Get-ADComputer -Server $Domain -Filter * -ResultPageSize $ResultPageSize -Properties $Properties -ErrorAction SilentlyContinue #| Select-Object -Property $Properties -ExcludeProperty $ExcludeProperty if ($null -ne $DomainObjects) { foreach ($_ in $Computers) { $DomainObjects[$_.DistinguishedName] = $_ } } $Computers } function Get-WinADDomainComputersUnknown { [CmdletBinding()] param( [Array] $DomainComputersAll ) #$DomainComputersAll | & { process { if ( $null -eq $_.OperatingSystem ) { $_ } } } # | Where-Object { $_.OperatingSystem -eq $null } foreach ($_ in $DomainComputersAll) { if ( $null -eq $_.OperatingSystem ) { $_ } } } function Get-WinADDomainComputersUnknownCount { [CmdletBinding()] param( [Array] $DomainComputersUnknown ) $DomainComputersUnknown | Group-Object -Property OperatingSystem | Select-Object @{ L = 'System Name'; Expression = { if ($_.Name -ne '') { $_.Name } else { 'Unknown' } } } , @{ L = 'System Count'; Expression = { $_.Count } } } function Get-WinADDomainControllersInternal { [CmdletBinding()] param( [string] $Domain ) $DomainControllersClean = Get-ADDomainController -Server $Domain -Filter * foreach ($DC in $DomainControllersClean) { [PsCustomObject] @{ 'Name' = $DC.Name 'Host Name' = $DC.HostName 'Operating System' = $DC.OperatingSystem 'Site' = $DC.Site 'Ipv4' = $DC.Ipv4Address 'Ipv6' = $DC.Ipv6Address 'Global Catalog?' = $DC.IsGlobalCatalog 'Read Only?' = $DC.IsReadOnly 'Ldap Port' = $DC.LdapPort 'SSL Port' = $DC.SSLPort } } } function Get-WinADDomainDefaultPasswordPolicy { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN ) $Policy = Get-ADDefaultDomainPasswordPolicy -Server $Domain [ordered] @{ 'Complexity Enabled' = $Policy.ComplexityEnabled 'Lockout Duration' = ($Policy.LockoutDuration).TotalMinutes 'Lockout Observation Window' = ($Policy.LockoutObservationWindow).TotalMinutes 'Lockout Threshold' = $Policy.LockoutThreshold 'Max Password Age' = $($Policy.MaxPasswordAge).TotalDays 'Min Password Length' = $Policy.MinPasswordLength 'Min Password Age' = $($Policy.MinPasswordAge).TotalDays 'Password History Count' = $Policy.PasswordHistoryCount 'Reversible Encryption Enabled' = $Policy.ReversibleEncryptionEnabled 'Distinguished Name' = $Policy.DistinguishedName } } function Get-WinADDomainDNSData { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN ) $DnsRecords = "_kerberos._tcp.$Domain", "_ldap._tcp.$Domain" $DNSData = foreach ($DnsRecord in $DnsRecords) { $Value = Resolve-DnsName -Name $DnsRecord -Type SRV -Verbose:$false -ErrorAction SilentlyContinue #| Select-Object * if ($null -eq $Value) { Write-Warning 'Getting domain information - DomainDNSSRV / DomainDNSA - Failed!' } $Value } $ReturnData = @{} $ReturnData.Srv = foreach ($V in $DNSData) { if ($V.QueryType -eq 'SRV') { $V | Select-Object Target, NameTarget, Priority, Weight, Port, Name } } $ReturnData.A = foreach ($V in $DNSData) { if ($V.QueryType -ne 'SRV') { $V | Select-Object Address, IPAddress, IP4Address, Name, Type, DataLength, TTL } } return $ReturnData } function Get-WinADDomainEnterpriseAdministrators { [CmdletBinding()] param( [Array] $DomainGroupsMembers, $DomainInformation ) #$DomainGroupsMembers | Where-Object { $_.'Group SID' -eq $('{0}-519' -f $DomainInformation.DomainSID.Value) } | Select-Object * -Exclude Group*, 'High Privileged Group' $Members = foreach ($_ in $DomainGroupsMembers) { if ($_.'Group SID' -eq $('{0}-519' -f $DomainInformation.DomainSID.Value)) { $_ } } $Members | Select-Object * -Exclude Group*, 'High Privileged Group' } function Get-WinADDomainEnterpriseAdministratorsRecursive { [CmdletBinding()] param( [Array] $DomainGroupsMembersRecursive, $DomainInformation ) # $DomainGroupsMembersRecursive | Where-Object { $_.'Group SID' -eq $('{0}-519' -f $DomainInformation.DomainSID.Value) } | Select-Object * -Exclude Group*, 'High Privileged Group' $Members = foreach ($_ in $DomainGroupsMembersRecursive) { if ($_.'Group SID' -eq $('{0}-519' -f $DomainInformation.DomainSID.Value)) { $_ } } $Members | Select-Object * -Exclude Group*, 'High Privileged Group' } function Get-WinADDomainFineGrainedPolicies { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN ) $FineGrainedPoliciesData = Get-ADFineGrainedPasswordPolicy -Filter * -Server $Domain $FineGrainedPolicies = foreach ($Policy in $FineGrainedPoliciesData) { [PsCustomObject] @{ 'Name' = $Policy.Name 'Complexity Enabled' = $Policy.ComplexityEnabled 'Lockout Duration' = $Policy.LockoutDuration 'Lockout Observation Window' = $Policy.LockoutObservationWindow 'Lockout Threshold' = $Policy.LockoutThreshold 'Max Password Age' = $Policy.MaxPasswordAge 'Min Password Length' = $Policy.MinPasswordLength 'Min Password Age' = $Policy.MinPasswordAge 'Password History Count' = $Policy.PasswordHistoryCount 'Reversible Encryption Enabled' = $Policy.ReversibleEncryptionEnabled 'Precedence' = $Policy.Precedence 'Applies To' = $Policy.AppliesTo # get all groups / usrs and convert to data TODO 'Distinguished Name' = $Policy.DistinguishedName } } return $FineGrainedPolicies } function Get-WinADDomainFineGrainedPoliciesUsers { [CmdletBinding()] param( [Array] $DomainFineGrainedPolicies, #[Array] $DomainUsersFullList, #[Array] $DomainGroupsFullList, [hashtable] $DomainObjects ) $PolicyUsers = foreach ($Policy in $DomainFineGrainedPolicies) { $AllObjects = foreach ($U in $Policy.'Applies To') { Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $U #Get-ADObjectFromDistingusishedName -ADCatalog $DomainUsersFullList -DistinguishedName $U } #$Groups = foreach ($U in $Policy.'Applies To') { # Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $U #Get-ADObjectFromDistingusishedName -ADCatalog $DomainGroupsFullList -DistinguishedName $U #} foreach ($_ in $AllObjects) { [PsCustomObject] @{ 'Policy Name' = $Policy.Name Name = $_.Name SamAccountName = $_.SamAccountName Type = $_.ObjectClass SID = $_.SID } } <# foreach ($Group in $Groups) { [PsCustomObject] @{ 'Policy Name' = $Policy.Name Name = $Group.Name SamAccountName = $Group.SamAccountName Type = $Group.ObjectClass SID = $Group.SID } } #> } #Get-AdFineGrainedPassowrdPolicySubject #Get-AdresultantPasswordPolicy -Identity <user> return $PolicyUsers } function Get-WinADDomainFineGrainedPoliciesUsersExtended { [CmdletBinding()] param( [Array] $DomainFineGrainedPolicies, # [Array] $DomainUsersFullList, # [Array] $DomainGroupsFullList, [string] $Domain = ($Env:USERDNSDOMAIN).ToLower(), [hashtable] $DomainObjects ) $CurrentDate = Get-Date $PolicyUsers = @( foreach ($Policy in $DomainFineGrainedPolicies) { $Objects = foreach ($U in $Policy.'Applies To') { #Get-ADObjectFromDistingusishedName -ADCatalog $DomainUsersFullList -DistinguishedName $U Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $U } $Users = foreach ($_ in $Objects) { if ($_.ObjectClass -eq 'user') { $_ } } $Groups = foreach ($_ in $Objects) { if ($_.ObjectClass -eq 'group') { $_ } } foreach ($User in $Users) { $Manager = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $User.Manager [PsCustomObject] @{ 'Policy Name' = $Policy.Name Name = $User.Name SamAccountName = $User.SamAccountName Type = $User.ObjectClass SID = $User.SID 'High Privileged Group' = 'N/A' 'Display Name' = $User.DisplayName 'Member Name' = $Member.Name 'User Principal Name' = $User.UserPrincipalName 'Sam Account Name' = $User.SamAccountName 'Email Address' = $User.EmailAddress 'PasswordExpired' = $User.PasswordExpired 'PasswordLastSet' = $User.PasswordLastSet 'PasswordNotRequired' = $User.PasswordNotRequired 'PasswordNeverExpires' = $User.PasswordNeverExpires 'Enabled' = $User.Enabled 'MemberSID' = $Member.SID.Value #'Manager' = (Get-ADObjectFromDistingusishedName -ADCatalog $DomainUsersFullList -DistinguishedName $User.Manager).Name #'ManagerEmail' = (Get-ADObjectFromDistingusishedName -ADCatalog $DomainUsersFullList -DistinguishedName $User.Manager).EmailAddress 'Manager' = $Manager.Name 'ManagerEmail' = if ($Splitter -ne '') { $Manager.EmailAddress -join $Splitter } else { $Manager.EmailAddress } 'DateExpiry' = Convert-ToDateTime -Timestring $($Object."msDS-UserPasswordExpiryTimeComputed") # -Verbose "DaysToExpire" = (Convert-TimeToDays -StartTime ($CurrentDate) -EndTime (Convert-ToDateTime -Timestring $($User."msDS-UserPasswordExpiryTimeComputed"))) "AccountExpirationDate" = $User.AccountExpirationDate "AccountLockoutTime" = $User.AccountLockoutTime "AllowReversiblePasswordEncryption" = $User.AllowReversiblePasswordEncryption "BadLogonCount" = $User.BadLogonCount "CannotChangePassword" = $User.CannotChangePassword "CanonicalName" = $User.CanonicalName 'Given Name' = $User.GivenName 'Surname' = $User.Surname "Description" = $User.Description "DistinguishedName" = $User.DistinguishedName "EmployeeID" = $User.EmployeeID "EmployeeNumber" = $User.EmployeeNumber "LastBadPasswordAttempt" = $User.LastBadPasswordAttempt "LastLogonDate" = $User.LastLogonDate "Created" = $User.Created "Modified" = $User.Modified "Protected" = $User.ProtectedFromAccidentalDeletion "Domain" = $Domain } } #$Groups = foreach ($U in $Policy.'Applies To') { # Get-ADObjectFromDistingusishedName -ADCatalog $DomainGroupsFullList -DistinguishedName $U # Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $U #} foreach ($Group in $Groups) { $GroupMembership = Get-ADGroupMember -Server $Domain -Identity $Group.SID -Recursive foreach ($Member in $GroupMembership) { # $Object = (Get-ADObjectFromDistingusishedName -ADCatalog $DomainUsersFullList -DistinguishedName $Member.DistinguishedName) $Object = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $Member.DistinguishedName $Manager = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $Object.Manager [PsCustomObject] @{ 'Policy Name' = $Policy.Name Name = $Group.Name SamAccountName = $Group.SamAccountName Type = $Group.ObjectClass SID = $Group.SID 'High Privileged Group' = if ($Group.adminCount -eq 1) { $True } else { $False } 'Display Name' = $Object.DisplayName 'Member Name' = $Member.Name 'User Principal Name' = $Object.UserPrincipalName 'Sam Account Name' = $Object.SamAccountName 'Email Address' = $Object.EmailAddress 'PasswordExpired' = $Object.PasswordExpired 'PasswordLastSet' = $Object.PasswordLastSet 'PasswordNotRequired' = $Object.PasswordNotRequired 'PasswordNeverExpires' = $Object.PasswordNeverExpires 'Enabled' = $Object.Enabled 'MemberSID' = $Member.SID.Value # 'Manager' = (Get-ADObjectFromDistingusishedName -ADCatalog $DomainUsersFullList -DistinguishedName $Object.Manager).Name # 'ManagerEmail' = (Get-ADObjectFromDistingusishedName -ADCatalog $DomainUsersFullList -DistinguishedName $Object.Manager).EmailAddress 'Manager' = $Manager.Name 'ManagerEmail' = if ($Splitter -ne '') { $Manager.EmailAddress -join $Splitter } else { $Manager.EmailAddress } 'DateExpiry' = Convert-ToDateTime -Timestring $($Object."msDS-UserPasswordExpiryTimeComputed") # -Verbose "DaysToExpire" = (Convert-TimeToDays -StartTime ($CurrentDate) -EndTime (Convert-ToDateTime -Timestring $($Object."msDS-UserPasswordExpiryTimeComputed"))) "AccountExpirationDate" = $Object.AccountExpirationDate "AccountLockoutTime" = $Object.AccountLockoutTime "AllowReversiblePasswordEncryption" = $Object.AllowReversiblePasswordEncryption "BadLogonCount" = $Object.BadLogonCount "CannotChangePassword" = $Object.CannotChangePassword "CanonicalName" = $Object.CanonicalName 'Given Name' = $Object.GivenName 'Surname' = $Object.Surname "Description" = $Object.Description "DistinguishedName" = $Object.DistinguishedName "EmployeeID" = $Object.EmployeeID "EmployeeNumber" = $Object.EmployeeNumber "LastBadPasswordAttempt" = $Object.LastBadPasswordAttempt "LastLogonDate" = $Object.LastLogonDate "Created" = $Object.Created "Modified" = $Object.Modified "Protected" = $Object.ProtectedFromAccidentalDeletion "Domain" = $Domain } } } } ) return $PolicyUsers } function Get-WinADDomainFSMO { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN, [Microsoft.ActiveDirectory.Management.ADDomain] $DomainInformation ) # required for multiple use cases FSMO/DomainTrusts [ordered] @{ 'PDC Emulator' = $DomainInformation.PDCEmulator 'RID Master' = $DomainInformation.RIDMaster 'Infrastructure Master' = $DomainInformation.InfrastructureMaster } } function Get-WinADDomainGroupPolicies { [CmdletBinding()] param( [Array] $GroupPolicies, [string] $Domain = $Env:USERDNSDOMAIN ) if ($null -eq $GroupPolicies) { $GroupPolicies = Get-GPO -Domain $Domain -All } foreach ($gpo in $GroupPolicies) { [PsCustomObject] @{ 'Display Name' = $gpo.DisplayName 'Gpo Status' = $gpo.GPOStatus 'Creation Time' = $gpo.CreationTime 'Modification Time' = $gpo.ModificationTime 'Description' = $gpo.Description 'Wmi Filter' = $gpo.WmiFilter } } } function Get-WinADDomainGroupPoliciesACL { [CmdletBinding()] param( [Array] $GroupPolicies, [string] $Domain = $Env:USERDNSDOMAIN ) if ($null -eq $GroupPolicies) { $GroupPolicies = Get-GPO -Domain $Domain -All } $Output = ForEach ($GPO in $GroupPolicies) { [xml]$XmlGPReport = $GPO.generatereport('xml') $ACLs = $XmlGPReport.GPO.SecurityDescriptor.Permissions.TrusteePermissions foreach ($ACL in $ACLS) { [PsCustomObject] @{ 'GPO Name' = $GPO.DisplayName 'User' = $ACL.trustee.name.'#Text' 'Permission Type' = $ACL.type.PermissionType 'Inherited' = $ACL.Inherited 'Permissions' = $ACL.Standard.GPOGroupedAccessEnum } } } return $Output } function Get-WinADDomainGroupPoliciesDetails { [CmdletBinding()] param( [Array] $GroupPolicies, [string] $Domain = $Env:USERDNSDOMAIN, [string] $Splitter ) if ($null -eq $GroupPolicies) { $GroupPolicies = Get-GPO -Domain $Domain -All } ForEach ($GPO in $GroupPolicies) { [xml]$XmlGPReport = $GPO.generatereport('xml') #GPO version if ($XmlGPReport.GPO.Computer.VersionDirectory -eq 0 -and $XmlGPReport.GPO.Computer.VersionSysvol -eq 0) { $ComputerSettings = "NeverModified" } else { $ComputerSettings = "Modified" } if ($XmlGPReport.GPO.User.VersionDirectory -eq 0 -and $XmlGPReport.GPO.User.VersionSysvol -eq 0) { $UserSettings = "NeverModified" } else { $UserSettings = "Modified" } #GPO content if ($null -eq $XmlGPReport.GPO.User.ExtensionData) { $UserSettingsConfigured = $false } else { $UserSettingsConfigured = $true } if ($null -eq $XmlGPReport.GPO.Computer.ExtensionData) { $ComputerSettingsConfigured = $false } else { $ComputerSettingsConfigured = $true } #Output [PsCustomObject] @{ 'Name' = $XmlGPReport.GPO.Name 'Links' = $XmlGPReport.GPO.LinksTo | Select-Object -ExpandProperty SOMPath 'Has Computer Settings' = $ComputerSettingsConfigured 'Has User Settings' = $UserSettingsConfigured 'User Enabled' = $XmlGPReport.GPO.User.Enabled 'Computer Enabled' = $XmlGPReport.GPO.Computer.Enabled 'Computer Settings' = $ComputerSettings 'User Settings' = $UserSettings 'Gpo Status' = $GPO.GpoStatus 'Creation Time' = $GPO.CreationTime 'Modification Time' = $GPO.ModificationTime 'WMI Filter' = $GPO.WmiFilter.name 'WMI Filter Description' = $GPO.WmiFilter.Description 'Path' = $GPO.Path 'GUID' = $GPO.Id 'SDDL' = if ($Splitter -ne '') { $XmlGPReport.GPO.SecurityDescriptor.SDDL.'#text' -join $Splitter } else { $XmlGPReport.GPO.SecurityDescriptor.SDDL.'#text' } #'ACLs' = $XmlGPReport.GPO.SecurityDescriptor.Permissions.TrusteePermissions | ForEach-Object -Process { # New-Object -TypeName PSObject -Property @{ # 'User' = $_.trustee.name.'#Text' # 'Permission Type' = $_.type.PermissionType # 'Inherited' = $_.Inherited # 'Permissions' = $_.Standard.GPOGroupedAccessEnum # } #} } } } function Get-WinADDomainGroupsFullList { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN, [HashTable] $DomainObjects, [int] $ResultPageSize = 500000 ) if ($Extended) { [string] $Properties = '*' } else { [string[]] $Properties = @( 'adminCount' 'CanonicalName' 'CN' 'Created' 'createTimeStamp' 'Deleted' 'Description' 'DisplayName' 'DistinguishedName' #'dSCorePropagationData' 'GroupCategory' 'GroupScope' 'groupType' 'HomePage' 'instanceType' 'isCriticalSystemObject' 'isDeleted' 'LastKnownParent' 'ManagedBy' 'member' 'MemberOf' 'Members' 'Modified' 'modifyTimeStamp' 'Name' #'nTSecurityDescriptor' 'ObjectCategory' 'ObjectClass' 'ObjectGUID' 'objectSid' 'ProtectedFromAccidentalDeletion' 'SamAccountName' 'sAMAccountType' 'sDRightsEffective' 'SID' 'SIDHistory' 'systemFlags' 'uSNChanged' 'uSNCreated' 'whenChanged' 'whenCreated' ) } $Groups = Get-ADGroup -Server $Domain -Filter * -ResultPageSize $ResultPageSize -Properties $Properties foreach ($_ in $Groups) { # $DomainObjects.$($_.DistinguishedName) = $_ $DomainObjects.Add($_.DistinguishedName, $_) } $Groups } <# $Groups = Get-ADGroup -Filter * $GroupsWithMembers = foreach ($_ in $Groups) { $Members = Get-ADGroupMember -Identity $_ -Recursive foreach ($Member in $Members) { [PSCustomobject] @{ 'Group Name' = $_.Name 'Member Name' = $Member.Name 'Member SamAccountName' = $Member.SamAccountName 'Member UserPrincipalName' = $Member.UserPrincipalName } } } $GroupsWithMembers | Format-Table -AutoSize #> function Get-DomainGroupsPriviliged { [cmdletbinding()] param( [Microsoft.ActiveDirectory.Management.ADDomain] $DomainInformation, [Array] $DomainGroups ) $PrivilegedGroupsSID = @( "S-1-5-32-544" "S-1-5-32-548" "S-1-5-32-549" "S-1-5-32-550" "S-1-5-32-551" "S-1-5-32-552" "S-1-5-32-556" "S-1-5-32-557" "S-1-5-32-573" "S-1-5-32-578" "S-1-5-32-580" "$($DomainInformation.DomainSID.Value)-512" "$($DomainInformation.DomainSID.Value)-518" "$($DomainInformation.DomainSID.Value)-519" "$($DomainInformation.DomainSID.Value)-520" ) # $DomainGroups | Where-Object { $PrivilegedGroupsSID -contains $_.'Group SID' } foreach ($_ in $DomainGroups) { if ($PrivilegedGroupsSID -contains $_.'Group SID' ) { $_ } } } function Get-WinADDomainGroupsPriviligedMembers { [CmdletBinding()] param( [Array] $DomainGroupsMembers, [Array] $DomainGroupsPriviliged ) # Needs review #$DomainGroupsMembers | Where-Object { $DomainGroupsPriviliged.'Group SID' -contains ($_.'Group SID') } | Select-Object * #-Exclude Group*, 'High Privileged Group' foreach ($_ in $DomainGroupsMembers) { if ($DomainGroupsPriviliged.'Group SID' -contains ($_.'Group SID')) { $_ } } } function Get-WinADDomainGroupsPriviligedMembersRecursive { [CmdletBinding()] param( [Array] $DomainGroupsMembersRecursive, [Array] $DomainGroupsPriviliged ) # Needs review #$DomainGroupsMembersRecursive | Where-Object { $DomainGroupsPriviliged.'Group SID' -contains ($_.'Group SID') } | Select-Object * #-Exclude Group*, 'High Privileged Group' foreach ($_ in $DomainGroupsMembersRecursive) { if ($DomainGroupsPriviliged.'Group SID' -contains ($_.'Group SID')) { $_ } } } function Get-WinADDomainGroupsSpecial { [CmdletBinding()] param( [Array] $DomainGroups ) #$DomainGroups | Where-Object { ($_.'Group SID').Length -eq 12 } foreach ($_ in $DomainGroups) { if (($_.'Group SID').Length -eq 12) { $_ } } } function Get-WinADDomainGroupsSpecialMembers { [CmdletBinding()] param( [Array] $DomainGroupsMembers ) # $DomainGroupsMembers | Where-Object { ($_.'Group SID').Length -eq 12 } | Select-Object * #-Exclude Group*, 'High Privileged Group' foreach ($_ in $DomainGroupsMembers) { if (($_.'Group SID').Length -eq 12) { $_ } } } function Get-WinADDomainGroupsSpecialMembersRecursive { [CmdletBinding()] param( [Array] $DomainGroupsMembersRecursive ) #$DomainGroupsMembersRecursive | Where-Object { ($_.'Group SID').Length -eq 12 } | Select-Object * #-Exclude Group*, 'High Privileged Group' foreach ($_ in $DomainGroupsMembersRecursive) { if (($_.'Group SID').Length -eq 12) { $_ } } } function Get-WinADDomainLAPS { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN, [Array] $Computers, [string] $Splitter ) $Properties = @( 'Name', 'OperatingSystem', 'DistinguishedName', 'ms-Mcs-AdmPwd', 'ms-Mcs-AdmPwdExpirationTime' ) [DateTime] $CurrentDate = Get-Date if ($null -eq $Computers -or $Computers.Count -eq 0) { $Computers = Get-ADComputer -Filter * -Properties $Properties } foreach ($Computer in $Computers) { [PSCustomObject] @{ 'Name' = $Computer.Name 'Operating System' = $Computer.'OperatingSystem' 'LapsPassword' = if ($Splitter -ne '') { $Computer.'ms-Mcs-AdmPwd' -join $Splitter } else { $Computer.'ms-Mcs-AdmPwd' } # For some reason it's an array Laps Password : {} 'LapsExpire(days)' = Convert-TimeToDays -StartTime ($CurrentDate) -EndTime (Convert-ToDateTime -Timestring ($Computer.'ms-Mcs-AdmPwdExpirationTime')) 'LapsExpirationTime' = Convert-ToDateTime -Timestring ($Computer.'ms-Mcs-AdmPwdExpirationTime') 'DistinguishedName' = $Computer.'DistinguishedName' } } } function Get-WinADDomainOrganizationalUnits { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN, [Array] $OrgnaizationalUnits, [hashtable] $DomainObjects ) if ($null -eq $OrgnaizationalUnits) { $OrgnaizationalUnits = $(Get-ADOrganizationalUnit -Server $Domain -Properties * -Filter * ) } $Output = foreach ($_ in $OrgnaizationalUnits) { $Manager = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $_.ManagedBy [PSCustomObject] @{ 'Canonical Name' = $_.CanonicalName 'Managed' = $Manager.Name 'Manager Email' = $Manager.EmailAddress 'Protected' = $_.ProtectedFromAccidentalDeletion Description = $_.Description Created = $_.Created Modified = $_.Modified Deleted = $_.Deleted 'PostalCode' = $_.PostalCode City = $_.City Country = $_.Country State = $_.State 'StreetAddress' = $_.StreetAddress DistinguishedName = $_.DistinguishedName ObjectGUID = $_.ObjectGUID } } $Output | Sort-Object 'Canonical Name' } function Get-WinADDomainOrganizationalUnitsACL { [cmdletbinding()] param( [Array] $DomainOrganizationalUnitsClean, [string] $Domain = $Env:USERDNSDOMAIN, [string] $NetBiosName, [string] $RootDomainNamingContext ) # Write-Verbose -Message "Getting domain information - $Domain DomainOrganizationalUnitsBasicACL" #$Time = Start-TimeLog $OUs = @( #@{ Name = 'Root'; Value = $RootDomainNamingContext } foreach ($OU in $DomainOrganizationalUnitsClean) { @{ Name = 'Organizational Unit'; Value = $OU.DistinguishedName } } ) $null = New-PSDrive -Name $NetBiosName -Root '' -PSProvider ActiveDirectory -Server $Domain @( foreach ($OU in $OUs) { $ACL = Get-Acl -Path "$NetBiosName`:\$($OU.Value)" [PsCustomObject] @{ 'Distinguished Name' = $OU.Value 'Type' = $OU.Name 'Owner' = $ACL.Owner 'Group' = $ACL.Group 'Are AccessRules Protected' = $ACL.AreAccessRulesProtected 'Are AuditRules Protected' = $ACL.AreAuditRulesProtected 'Are AccessRules Canonical' = $ACL.AreAccessRulesCanonical 'Are AuditRules Canonical' = $ACL.AreAuditRulesCanonical #'Sddl' = $ACL.Sddl } <# Get-Acl -Path "$NetBiosName`:\$($OU.Value)" | Select-Object ` @{name = 'Distinguished Name'; expression = { $OU.Value } }, @{name = 'Type'; expression = { $OU.Name } }, @{name = 'Owner'; expression = { $_.Owner } }, @{name = 'Group'; expression = { $_.Group } }, @{name = 'Are AccessRules Protected'; expression = { $_.AreAccessRulesProtected } }, @{name = 'Are AuditRules Protected'; expression = { $_.AreAuditRulesProtected } }, @{name = 'Are AccessRules Canonical'; expression = { $_.AreAccessRulesCanonical } }, @{name = 'Are AuditRules Canonical'; expression = { $_.AreAuditRulesCanonical } }, @{name = 'Sddl'; expression = { $_.Sddl } } #> } ) #$EndTime = Stop-TimeLog -Time $Time -Option OneLiner # Write-Verbose -Message "Getting domain information - $Domain DomainOrganizationalUnitsBasicACL Time: $EndTime" } function Get-WinADDomainOrganizationalUnitsACLExtended { [cmdletbinding()] param( [Array] $DomainOrganizationalUnitsClean, [string] $Domain = $Env:USERDNSDOMAIN, [string] $NetBiosName, [string] $RootDomainNamingContext, [hashtable] $GUID ) #Write-Verbose -Message "Getting domain information - $Domain DomainOrganizationalUnitsExtended" #$Time = Start-TimeLog $OUs = @( #@{ Name = 'Root'; Value = $RootDomainNamingContext } foreach ($OU in $DomainOrganizationalUnitsClean) { @{ Name = 'Organizational Unit'; Value = $OU.DistinguishedName } } ) $null = New-PSDrive -Name $NetBiosName -Root '' -PSProvider ActiveDirectory -Server $Domain @( foreach ($OU in $OUs) { $ACLs = Get-Acl -Path "$NetBiosName`:\$($OU.Value)" | Select-Object -ExpandProperty Access foreach ($ACL in $ACLs) { [PSCustomObject] @{ 'Distinguished Name' = $OU.Value 'Type' = $OU.Name 'AccessControlType' = $ACL.AccessControlType 'ObjectType Name' = if ($ACL.objectType.ToString() -eq '00000000-0000-0000-0000-000000000000') { 'All' } Else { $GUID.Item($ACL.objectType) } 'Inherited ObjectType Name' = $GUID.Item($ACL.inheritedObjectType) 'ActiveDirectoryRights' = $ACL.ActiveDirectoryRights 'InheritanceType' = $ACL.InheritanceType 'ObjectType' = $ACL.ObjectType 'InheritedObjectType' = $ACL.InheritedObjectType 'ObjectFlags' = $ACL.ObjectFlags 'IdentityReference' = $ACL.IdentityReference 'IsInherited' = $ACL.IsInherited 'InheritanceFlags' = $ACL.InheritanceFlags 'PropagationFlags' = $ACL.PropagationFlags } } <# Get-Acl -Path "$NetBiosName`:\$($OU.Value)" | ` Select-Object -ExpandProperty Access | ` Select-Object ` @{name = 'Distinguished Name'; expression = { $OU.Value } }, @{name = 'Type'; expression = { $OU.Name } }, @{name = 'AccessControlType'; expression = { $_.AccessControlType } }, @{name = 'ObjectType Name'; expression = { if ($_.objectType.ToString() -eq '00000000-0000-0000-0000-000000000000') { 'All' } Else { $GUID.Item($_.objectType) } } }, @{name = 'Inherited ObjectType Name'; expression = { $GUID.Item($_.inheritedObjectType) } }, @{name = 'ActiveDirectoryRights'; expression = { $_.ActiveDirectoryRights } }, @{name = 'InheritanceType'; expression = { $_.InheritanceType } }, @{name = 'ObjectType'; expression = { $_.ObjectType } }, @{name = 'InheritedObjectType'; expression = { $_.InheritedObjectType } }, @{name = 'ObjectFlags'; expression = { $_.ObjectFlags } }, @{name = 'IdentityReference'; expression = { $_.IdentityReference } }, @{name = 'IsInherited'; expression = { $_.IsInherited } }, @{name = 'InheritanceFlags'; expression = { $_.InheritanceFlags } }, @{name = 'PropagationFlags'; expression = { $_.PropagationFlags } } #> } ) #$EndTime = Stop-TimeLog -Time $Time -Option OneLiner #Write-Verbose -Message "Getting domain information - $Domain DomainOrganizationalUnitsExtended Time: $EndTime" } <# $Data = @{} $Domain = 'ad.evotec.xyz' $Data.DomainRootDSE = $(Get-ADRootDSE -Server $Domain) $Data.DomainInformation = $(Get-ADDomain -Server $Domain) $Data.DomainGUIDS = Invoke-Command -ScriptBlock { $GUID = @{ } Get-ADObject -SearchBase (Get-ADRootDSE).schemaNamingContext -LDAPFilter '(schemaIDGUID=*)' -Properties name, schemaIDGUID | ForEach-Object { if ($GUID.Keys -notcontains $_.schemaIDGUID ) { $GUID.add([System.GUID]$_.schemaIDGUID, $_.name) } } Get-ADObject -SearchBase "CN=Extended-Rights,$((Get-ADRootDSE).configurationNamingContext)" -LDAPFilter '(objectClass=controlAccessRight)' -Properties name, rightsGUID | ForEach-Object { if ($GUID.Keys -notcontains $_.rightsGUID ) { $GUID.add([System.GUID]$_.rightsGUID, $_.name) } } return $GUID } $OU = $(Get-ADOrganizationalUnit -Server $Domain -Properties * -Filter * ) Get-WinADDomainOrganizationalUnitsACLExtended ` -DomainOrganizationalUnitsClean $OU ` -Domain $Domain ` -NetBiosName $Data.DomainInformation.NetBIOSName ` -RootDomainNamingContext $Data.DomainRootDSE.rootDomainNamingContext ` -GUID $Data.DomainGUIDS #> function Get-WinADDomainPassword { [CmdletBinding()] param( [alias('DnsRoot')][string] $Server, [alias('DomainDN')][string] $DistinguishedName ) try { Get-ADReplAccount -All -Server $Server -NamingContext $DistinguishedName } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " if ($ErrorMessage -like '*is not recognized as the name of a cmdlet*') { Write-Warning "Get-ADReplAccount - Please install module DSInternals (Install-Module DSInternals) - Error: $ErrorMessage" } else { Write-Warning "Get-ADReplAccount - Error occured: $ErrorMessage" } } } function Get-WinADDomainPasswordQuality { [CmdletBinding()] param ( [string] $DnsRoot, [string] $DomainDistinguishedName, [Array] $PasswordQualityUsers, [string] $FilePath, [switch] $UseHashes, [switch] $PasswordQuality, [Array] $Properties, [System.Collections.IDictionary] $DomainObjectsNetbios ) if (-not $DomainObjectsNetbios) { Write-Warning "Get-WinADDomainPasswordQuality - DomainobjectsNetbios not passed. Creating new one, but this will skip tests." $DomainObjectsNetbios = [ordered] @{} } if (-not $Properties) { $Properties = @( 'Name', 'UserPrincipalName', 'Enabled', 'Password Last Changed', "DaysToExpire", 'PasswordExpired', 'PasswordNeverExpires', 'PasswordNotRequired', 'DateExpiry', 'PasswordLastSet', 'SamAccountName', 'EmailAddress', 'Display Name', 'Given Name', 'Surname', 'Manager', 'Manager Email', "AccountExpirationDate", "AccountLockoutTime", "AllowReversiblePasswordEncryption", "BadLogonCount", "CannotChangePassword", "CanonicalName", "Description", "DistinguishedName", "EmployeeID", "EmployeeNumber", "LastBadPasswordAttempt", "LastLogonDate", "Created", "Modified", "Protected", "Primary Group", "Member Of", "Domain" ) } if ($FilePath -eq '' -and $PasswordQuality.IsPresent -eq $true) { $FilePath = "$PSScriptRoot\Resources\PasswordList.txt" } if ($FilePath -eq '') { Write-Verbose "Get-WinADDomainPasswordQuality - File path not given, using hashes set to $($UseHashes.IsPresent)" return $null } if (-not (Test-Path -Path $FilePath)) { Write-Verbose "Get-WinADDomainPasswordQuality - File path doesn't exists, using hashes set to $($UseHashes.IsPresent)" return $null } $Data = [ordered] @{ } if ($PasswordQualityUsers) { $Data.PasswordQualityUsers = $PasswordQualityUsers } else { $Data.PasswordQualityUsers = Get-ADReplAccount -All -Server $DnsRoot -NamingContext $DomainDistinguishedName } $Data.PasswordQuality = Invoke-Command -ScriptBlock { if ($UseHashes) { $Results = $Data.PasswordQualityUsers | Test-PasswordQuality -WeakPasswordHashesFile $FilePath -IncludeDisabledAccounts } else { $Results = $Data.PasswordQualityUsers | Test-PasswordQuality -WeakPasswordsFile $FilePath -IncludeDisabledAccounts } return $Results } $Data.DomainPasswordClearTextPassword = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.ClearTextPassword) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordClearTextPasswordEnabled = Invoke-Command -ScriptBlock { return $Data.DomainPasswordClearTextPassword | Where-Object { $_.Enabled -eq $true } } $Data.DomainPasswordClearTextPasswordDisabled = Invoke-Command -ScriptBlock { return $Data.DomainPasswordClearTextPassword | Where-Object { $_.Enabled -eq $false } } $Data.DomainPasswordLMHash = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.LMHash) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordEmptyPassword = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.EmptyPassword) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordWeakPassword = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.WeakPassword) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordWeakPasswordEnabled = Invoke-Command -ScriptBlock { return $Data.DomainPasswordWeakPassword | Where-Object { $_.Enabled -eq $true } } $Data.DomainPasswordWeakPasswordDisabled = Invoke-Command -ScriptBlock { return $Data.DomainPasswordWeakPassword | Where-Object { $_.Enabled -eq $false } } $Data.DomainPasswordWeakPasswordList = Invoke-Command -ScriptBlock { if ($UseHashes) { return '' } else { $Passwords = Get-Content -Path $FilePath return $Passwords -join ', ' } } $Data.DomainPasswordAESKeysMissing = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.AESKeysMissing) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordDefaultComputerPassword = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.DefaultComputerPassword) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordPasswordNotRequired = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.PasswordNotRequired) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordPasswordNeverExpires = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.PasswordNeverExpires) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordPreAuthNotRequired = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.PreAuthNotRequired) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordDESEncryptionOnly = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.DESEncryptionOnly) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordDelegatableAdmins = Invoke-Command -ScriptBlock { foreach ($User in $Data.PasswordQuality.DelegatableAdmins) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordSmartCardUsersWithPassword = & { foreach ($User in $Data.PasswordQuality.SmartCardUsersWithPassword) { if ($DomainObjectsNetbios["$User"]) { $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } $Data.DomainPasswordDuplicatePasswordGroups = Invoke-Command -ScriptBlock { $DuplicateGroups = $Data.PasswordQuality.DuplicatePasswordGroups.ToArray() $Count = 0 foreach ($DuplicateGroup in $DuplicateGroups) { $Count++ $Name = "Duplicate $Count" foreach ($User in $DuplicateGroup) { if ($DomainObjectsNetbios["$User"]) { Add-Member -InputObject $DomainObjectsNetbios["$User"] -MemberType NoteProperty -Name 'Duplicate Group' -Value $Name -Force $DomainObjectsNetbios["$User"] } else { Write-Warning "Get-WinADDomainPasswordQuality - Couldn't find object $User in cache." } } } } return $Data } function Get-WinADDomainPasswordStats { [CmdletBinding()] param( [System.Collections.IDictionary]$PasswordsQuality, [Array] $TypesRequired, $DomainPasswordHashesWeakPassword, $DomainPasswordHashesWeakPasswordEnabled, $DomainPasswordHashesWeakPasswordDisabled ) $Stats = [ordered] @{ } $Stats.'Clear Text Passwords' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordClearTextPassword $Stats.'LM Hashes' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordLMHash $Stats.'Empty Passwords' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordEmptyPassword $Stats.'Weak Passwords' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordWeakPassword $Stats.'Weak Passwords Enabled' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordWeakPasswordEnabled $Stats.'Weak Passwords Disabled' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordWeakPasswordDisabled if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.ActiveDirectory]::DomainPasswordHashesWeakPassword)) { $Stats.'Weak Passwords (HASH)' = Get-ObjectCount -Object $DomainPasswordHashesWeakPassword } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.ActiveDirectory]::DomainPasswordHashesWeakPasswordEnabled)) { $Stats.'Weak Passwords (HASH) Enabled' = Get-ObjectCount -Object $DomainPasswordHashesWeakPasswordEnabled } if (Find-TypesNeeded -TypesRequired $TypesRequired -TypesNeeded @([PSWinDocumentation.ActiveDirectory]::DomainPasswordHashesWeakPasswordDisabled)) { $Stats.'Weak Passwords (HASH) Disabled' = Get-ObjectCount -Object $DomainPasswordHashesWeakPasswordDisabled } $Stats.'Default Computer Passwords' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordDefaultComputerPassword $Stats.'Password Not Required' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordPasswordNotRequired $Stats.'Password Never Expires' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordPasswordNeverExpires $Stats.'AES Keys Missing' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordAESKeysMissing $Stats.'PreAuth Not Required' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordPreAuthNotRequired $Stats.'DES Encryption Only' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordDESEncryptionOnly $Stats.'Delegatable Admins' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordDelegatableAdmins $Stats.'Duplicate Password Users' = Get-ObjectCount -Object $PasswordsQuality.DomainPasswordDuplicatePasswordGroups $Stats.'Duplicate Password Grouped' = Get-ObjectCount ($PasswordsQuality.DomainPasswordDuplicatePasswordGroups.'Duplicate Group' | Sort-Object -Unique) return $Stats } function Get-WinADDomainRIDs { [CmdletBinding()] param( [Microsoft.ActiveDirectory.Management.ADDomain] $DomainInformation, [string] $Domain = $Env:USERDNSDOMAIN ) # Critical for RID Pool Depletion: https://blogs.technet.microsoft.com/askds/2011/09/12/managing-rid-pool-depletion/ #$Time = Start-TimeLog #rite-Verbose "Getting domain information - $Domain DomainRIDs" if ($null -eq $DomainInformation) { $DomainInformation = Get-ADDomain -Server $Domain } $rID = [ordered] @{ } $rID.'rIDs Master' = $DomainInformation.RIDMaster $Property = Get-ADObject "cn=rid manager$,cn=system,$($DomainInformation.DistinguishedName)" -Property RidAvailablePool -Server $rID.'rIDs Master' [int32]$totalSIDS = $($Property.RidAvailablePool) / ([math]::Pow(2, 32)) [int64]$temp64val = $totalSIDS * ([math]::Pow(2, 32)) [int32]$currentRIDPoolCount = $($Property.RidAvailablePool) - $temp64val [int64]$RidsRemaining = $totalSIDS - $currentRIDPoolCount $Rid.'rIDs Available Pool' = $Property.RidAvailablePool $rID.'rIDs Total SIDs' = $totalSIDS $rID.'rIDs Issued' = $CurrentRIDPoolCount $rID.'rIDs Remaining' = $RidsRemaining $rID.'rIDs Percentage' = if ($RidsRemaining -eq 0) { $RidsRemaining.ToString("P") } else { ($currentRIDPoolCount / $RidsRemaining * 100).ToString("P") } #$EndTime = Stop-TimeLog -Time $Time -Option OneLiner #Write-Verbose "Getting domain information - $Domain DomainRIDs Time: $EndTime" return $rID } function Get-WinADDomainServersCount { [CmdletBinding()] param( [Array] $DomainServers ) $DomainServers | Group-Object -Property OperatingSystem | Select-Object @{ L = 'System Name'; Expression = { if ($_.Name -ne '') { $_.Name } else { 'N/A' } } } , @{ L = 'System Count'; Expression = { $_.Count } } } function Get-WinADDomainServers { [CmdletBinding()] param( [Array] $DomainComputersAll ) #$DomainComputersAll | & { process { if ($_.OperatingSystem -like 'Windows Server*') { $_ } } } #| Where-Object { $_.OperatingSystem -like 'Windows Server*' } foreach ($_ in $DomainComputersAll) { if ($_.OperatingSystem -like 'Windows Server*') { $_ } } } function Get-WinADDomainTrusts { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN, [string] $DomainPDC, [Array] $Trusts ) if ($null -eq $Trusts) { $Trusts = Get-ADTrust -Server $Domain -Filter * -Properties * } if ($DomainPDC -eq '') { $DomainPDC = (Get-ADDomain -Server $Domain).PDCEmulator } $PropertiesTrustWMI = @( 'FlatName', 'SID', 'TrustAttributes', 'TrustDirection', 'TrustedDCName', 'TrustedDomain', 'TrustIsOk', 'TrustStatus', 'TrustStatusString', # TrustIsOk/TrustStatus are covered by this 'TrustType' ) <# TrustWMI FlatName : EVOTECPL SID : S-1-5-21-3661168273-3802070955-2987026695 TrustAttributes : 32 TrustDirection : 3 TrustedDCName : \\ADPreview2019.ad.evotec.pl TrustedDomain : ad.evotec.pl TrustIsOk : True TrustStatus : 0 TrustStatusString : OK TrustType : 2 PSComputerName : ad1.ad.evotec.xyz #> $TrustStatatuses = Get-CimInstance -ClassName Microsoft_DomainTrustStatus -Namespace root\MicrosoftActiveDirectory -ComputerName $DomainPDC -ErrorAction SilentlyContinue -Verbose:$false -Property $PropertiesTrustWMI $ReturnData = foreach ($Trust in $Trusts) { $TrustWMI = $TrustStatatuses | & { process { if ($_.TrustedDomain -eq $Trust.Target ) { $_ } } } [PsCustomObject] @{ 'Trust Source' = $Domain 'Trust Target' = $Trust.Target 'Trust Direction' = $Trust.Direction 'Trust Attributes' = if ($Trust.TrustAttributes -is [int]) { Set-TrustAttributes -Value $Trust.TrustAttributes } else { 'Error - needs fixing' } 'Trust Status' = if ($null -ne $TrustWMI) { $TrustWMI.TrustStatusString } else { 'N/A' } 'Forest Transitive' = $Trust.ForestTransitive 'Selective Authentication' = $Trust.SelectiveAuthentication 'SID Filtering Forest Aware' = $Trust.SIDFilteringForestAware 'SID Filtering Quarantined' = $Trust.SIDFilteringQuarantined 'Disallow Transivity' = $Trust.DisallowTransivity 'Intra Forest' = $Trust.IntraForest 'Tree Parent?' = $Trust.IsTreeParent 'Tree Root?' = $Trust.IsTreeRoot 'TGTDelegation' = $Trust.TGTDelegation 'TrustedPolicy' = $Trust.TrustedPolicy 'TrustingPolicy' = $Trust.TrustingPolicy 'TrustType' = $Trust.TrustType 'UplevelOnly' = $Trust.UplevelOnly 'UsesAESKeys' = $Trust.UsesAESKeys 'UsesRC4Encryption' = $Trust.UsesRC4Encryption 'Trust Source DC' = if ($null -ne $TrustWMI) { $TrustWMI.PSComputerName } else { '' } 'Trust Target DC' = if ($null -ne $TrustWMI) { $TrustWMI.TrustedDCName.Replace('\\', '') } else { '' } 'Trust Source DN' = $Trust.Source 'ObjectGUID' = $Trust.ObjectGUID 'Created' = $Trust.Created 'Modified' = $Trust.Modified 'Deleted' = $Trust.Deleted 'SID' = $Trust.securityIdentifier 'TrustOK' = if ($null -ne $TrustWMI) { $TrustWMI.TrustIsOK } else { $false } 'TrustStatus' = if ($null -ne $TrustWMI) { $TrustWMI.TrustStatus } else { -1 } } } #$EndTime = Stop-TimeLog -Time $Time -Option OneLiner #Write-Verbose "Getting domain information - $Domain DomainTrusts Time: $EndTime" return $ReturnData } function Get-WinADDomainTrustsClean { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN ) Get-ADTrust -Server $Domain -Filter * -Properties * -ErrorAction SilentlyContinue } function Get-WinADDomainUsersAll { [CmdletBinding()] param( [Array] $Users, [string] $Domain = $Env:USERDNSDOMAIN, [System.Collections.IDictionary] $DomainObjects, [System.Collections.IDictionary] $DomainObjectsNetbios, [Object] $Domaininformation, [string] $Splitter ) [DateTime] $CurrentDate = Get-Date foreach ($U in $Users) { $Manager = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $U.Manager $User = [PsCustomObject] @{ 'Name' = $U.Name 'UserPrincipalName' = $U.UserPrincipalName 'SamAccountName' = $U.SamAccountName 'DisplayName' = $U.DisplayName 'GivenName' = $U.GivenName 'Surname' = $U.Surname 'EmailAddress' = $U.EmailAddress 'PasswordExpired' = $U.PasswordExpired 'PasswordLastSet' = $U.PasswordLastSet 'PasswordLastChanged(Days)' = if ($null -ne $U.PasswordLastSet) { "$(-$($U.PasswordLastSet - $CurrentDate).Days)" } else { } 'PasswordNotRequired' = $U.PasswordNotRequired 'PasswordNeverExpires' = $U.PasswordNeverExpires 'Enabled' = $U.Enabled 'Manager' = $Manager.Name 'ManagerEmail' = if ($Splitter -ne '') { $Manager.EmailAddress -join $Splitter } else { $Manager.EmailAddress } 'DateExpiry' = Convert-ToDateTime -Timestring $($U."msDS-UserPasswordExpiryTimeComputed") "DaysToExpire" = (Convert-TimeToDays -StartTime $CurrentDate -EndTime (Convert-ToDateTime -Timestring $($U."msDS-UserPasswordExpiryTimeComputed"))) "AccountExpirationDate" = $U.AccountExpirationDate "AccountLockoutTime" = $U.AccountLockoutTime "AllowReversiblePasswordEncryption" = $U.AllowReversiblePasswordEncryption "BadLogonCount" = $U.BadLogonCount "CannotChangePassword" = $U.CannotChangePassword "CanonicalName" = $U.CanonicalName "Description" = $U.Description "DistinguishedName" = $U.DistinguishedName "EmployeeID" = $U.EmployeeID "EmployeeNumber" = $U.EmployeeNumber "LastBadPasswordAttempt" = $U.LastBadPasswordAttempt "LastLogonDate" = $U.LastLogonDate "Created" = $U.Created "Modified" = $U.Modified "Protected" = $U.ProtectedFromAccidentalDeletion "Primary Group" = (Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $U.PrimaryGroup -Type 'SamAccountName') "Member Of" = (Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $U.MemberOf -Type 'SamAccountName' -Splitter $Splitter) "Domain" = $Domain } $Name = -join ($Domaininformation.NetBIOSName, "\", $User.SamAccountName) $DomainObjectsNetbios[$Name] = $User $User } } function Get-WinADDomainUsersAllFiltered { [CmdletBinding()] param( [Array] $DomainUsers ) #$DomainUsers | Where-Object { $_.PasswordNotRequired -eq $False } #| Select-Object * #Name, SamAccountName, UserPrincipalName, Enabled foreach ($_ in $DomainUsers) { if ($_.PasswordNotRequired -eq $False) { $_ } } } function Get-WinADDomainUsersExpiredExclDisabled { [CmdletBinding()] param( [Array] $DomainUsers ) #$DomainUsers | Where-Object { $_.PasswordNeverExpires -eq $false -and $_.DaysToExpire -le 0 -and $_.Enabled -eq $true -and $_.PasswordNotRequired -eq $false } #| Select-Object * # Name, SamAccountName, UserPrincipalName, Enabled foreach ($_ in $DomainUsers) { if ($_.PasswordNeverExpires -eq $false -and $_.DaysToExpire -le 0 -and $_.Enabled -eq $true -and $_.PasswordNotRequired -eq $false) { $_ } } } function Get-WinADDomainUsersExpiredInclDisabled { [CmdletBinding()] param( [Array] $DomainUsers ) #$DomainUsers | Where-Object { $_.PasswordNeverExpires -eq $false -and $_.DaysToExpire -le 0 -and $_.PasswordNotRequired -eq $false } foreach ($_ in $DomainUsers) { if ($_.PasswordNeverExpires -eq $false -and $_.DaysToExpire -le 0 -and $_.PasswordNotRequired -eq $false) { $_ } } #| Select-Object * #Name, SamAccountName, UserPrincipalName, Enabled } function Get-WinADDomainUsersFullList { [CmdletBinding()] param( [string] $Domain = $Env:USERDNSDOMAIN, [switch] $Extended, [Array] $ForestSchemaUsers, [System.Collections.IDictionary] $DomainObjects, [int] $ResultPageSize = 500000 ) if ($null -eq $ForestSchemaUsers) { $ForestSchemaUsers = @( $Schema = [directoryservices.activedirectory.activedirectoryschema]::GetCurrentSchema() @( $Schema.FindClass("user").MandatoryProperties #| Select-Object name, commonname, description, syntax #| export-csv user-mandatory-attributes.csv -Delimiter ';' $Schema.FindClass("user").OptionalProperties #| Select-Object name, commonname, description, syntax #| export-csv user-optional-attributes.csv -Delimiter ';' $Schema.FindClass("user").PossibleSuperiors #| Select-Object name, commonname, description, syntax $Schema.FindClass("user").PossibleInferiors #| Select-Object name, commonname, description, syntax $Schema.FindClass("user").AuxiliaryClasses ) # $Schema.FindClass("user").FindAllProperties() | Select-Object name, commonname, description, syntax ) } if ($Extended) { [string] $Properties = '*' } else { $Properties = @( 'Name' 'UserPrincipalName' 'SamAccountName' 'DisplayName' 'GivenName' 'Surname' 'EmailAddress' 'PasswordExpired' 'PasswordLastSet' 'PasswordNotRequired' 'PasswordNeverExpires' 'Enabled' 'Manager' 'msDS-UserPasswordExpiryTimeComputed' 'AccountExpirationDate' 'AccountLockoutTime' 'AllowReversiblePasswordEncryption' 'BadLogonCount' 'CannotChangePassword' 'CanonicalName' 'Description' 'DistinguishedName' 'EmployeeID' 'EmployeeNumber' 'LastBadPasswordAttempt' 'LastLogonDate' 'Created' 'Modified' 'ProtectedFromAccidentalDeletion' 'PrimaryGroup' 'MemberOf' if ($ForestSchemaUsers.Name -contains 'ExtensionAttribute1') { 'ExtensionAttribute1' 'ExtensionAttribute2' 'ExtensionAttribute3' 'ExtensionAttribute4' 'ExtensionAttribute5' 'ExtensionAttribute6' 'ExtensionAttribute7' 'ExtensionAttribute8' 'ExtensionAttribute9' 'ExtensionAttribute10' 'ExtensionAttribute11' 'ExtensionAttribute12' 'ExtensionAttribute13' 'ExtensionAttribute14' 'ExtensionAttribute15' } ) } $Users = Get-ADUser -Server $Domain -ResultPageSize $ResultPageSize -Filter * -Properties $Properties #| Select-Object -Property $Properties -ExcludeProperty $ExcludeProperty if ($null -ne $DomainObjects) { foreach ($_ in $Users) { $DomainObjects[$_.DistinguishedName] = $_ } } $Users } function Get-WinADDomainUsersNeverExpiring { [CmdletBinding()] param( [Array] $DomainUsers ) #$DomainUsers | Where-Object { $_.PasswordNeverExpires -eq $true -and $_.Enabled -eq $true -and $_.PasswordNotRequired -eq $false } foreach ($_ in $DomainUsers) { if ($_.PasswordNeverExpires -eq $true -and $_.Enabled -eq $true -and $_.PasswordNotRequired -eq $false) { $_ } } } function Get-WinADDomainUsersNeverExpiringInclDisabled { [CmdletBinding()] param( [Array] $DomainUsers ) #$DomainUsers | Where-Object { $_.PasswordNeverExpires -eq $true -and $_.Enabled -eq $true -and $_.PasswordNotRequired -eq $false } foreach ($_ in $DomainUsers) { if ($_.PasswordNeverExpires -eq $true -and $_.PasswordNotRequired -eq $false) { $_ } } } function Get-WinADDomainUsersSystemAccounts { [CmdletBinding()] param( [Array] $DomainUsers ) #$DomainUsers | Where-Object { $_.PasswordNotRequired -eq $true } #| Select-Object * #Name, SamAccountName, UserPrincipalName, Enabled foreach ($_ in $DomainUsers) { if ($_.PasswordNotRequired -eq $true) { $_ } } } function Get-WinADForest { [CmdletBinding()] param() # $Time = Start-TimeLog #Write-Verbose 'Getting forest information - Forest' try { Get-ADForest -ErrorAction Stop #| Select-Object -Property * -ExcludeProperty PropertyNames, AddedProperties, RemovedProperties, ModifiedProperties, PropertyCount } catch { $null } #$EndTime = Stop-TimeLog -Time $Time -Option OneLiner #Write-Verbose "Getting forest information - Forest Time: $EndTime" } function Get-WinADForestFSMO { [CmdletBinding()] param( [PSCustomObject] $Forest ) [ordered] @{ 'Domain Naming Master' = $Forest.DomainNamingMaster 'Schema Master' = $Forest.SchemaMaster } } function Get-WinADForestInfo { [CmdletBinding()] param( [PSCustomObject] $Forest, [Microsoft.ActiveDirectory.Management.ADRootDSE] $RootDSE ) #$Time = Start-TimeLog #Write-Verbose 'Getting forest information - Forest Information' [ordered] @{ 'Name' = $Forest.Name 'Root Domain' = $Forest.RootDomain 'Forest Distingushed Name' = $RootDSE.defaultNamingContext 'Forest Functional Level' = $Forest.ForestMode 'Domains Count' = ($Forest.Domains).Count 'Sites Count' = ($Forest.Sites).Count 'Domains' = ($Forest.Domains) -join ", " 'Sites' = ($Forest.Sites) -join ", " } #$EndTime = Stop-TimeLog -Time $Time -Option OneLiner #Write-Verbose "Getting forest information - Forest Information Time: $EndTime" } function Get-WinADForestSiteLinks { [CmdletBinding()] param( ) $ExludedProperties = @( 'PropertyNames', 'AddedProperties', 'RemovedProperties', 'ModifiedProperties', 'PropertyCount' ) $Properties = @( 'Name', 'Cost', 'ReplicationFrequencyInMinutes', 'ReplInterval', 'ReplicationSchedule', 'Created', 'Modified', 'Deleted', 'InterSiteTransportProtocol', 'DistinguishedName', 'ProtectedFromAccidentalDeletion' #siteList,nTSecurityDescriptor ) return Get-ADReplicationSiteLink -Filter * -Properties $Properties | Select-Object -Property $Properties -ExcludeProperty $ExludedProperties } function Get-WinADForestSites { [CmdletBinding()] param( [switch] $Formatted, [string] $Splitter ) <# 'nTSecurityDescriptor' = $_.'nTSecurityDescriptor' LastKnownParent = $_.LastKnownParent instanceType = $_.InstanceType InterSiteTopologyGenerator = $_.InterSiteTopologyGenerator dSCorePropagationData = $_.dSCorePropagationData ReplicationSchedule = $_.ReplicationSchedule.RawSchedule -join ',' msExchServerSiteBL = $_.msExchServerSiteBL -join ',' siteObjectBL = $_.siteObjectBL -join ',' systemFlags = $_.systemFlags ObjectGUID = $_.ObjectGUID ObjectCategory = $_.ObjectCategory ObjectClass = $_.ObjectClass ScheduleHashingEnabled = $_.ScheduleHashingEnabled #> $DomainControllers = Get-WinADForestControllers $Sites = Get-ADReplicationSite -Filter * -Properties * # $Properties | Select-Object -Property $Properties -ExcludeProperty $ExludedProperties foreach ($Site in $Sites) { [Array] $DCs = $DomainControllers | Where-Object { $_.Site -eq $Site.Name } [Array] $Subnets = ConvertFrom-DistinguishedName -DistinguishedName $Site.'Subnets' if ($Formatted) { [PSCustomObject] @{ 'Name' = $Site.Name 'Display Name' = $Site.'DisplayName' 'Description' = $Site.'Description' 'CanonicalName' = $Site.'CanonicalName' 'DistinguishedName' = $Site.'DistinguishedName' 'Location' = $Site.'Location' 'ManagedBy' = $Site.'ManagedBy' 'Protected From Accidental Deletion' = $Site.'ProtectedFromAccidentalDeletion' 'Redundant Server Topology Enabled' = $Site.'RedundantServerTopologyEnabled' 'Automatic Inter-Site Topology Generation Enabled' = $Site.'AutomaticInterSiteTopologyGenerationEnabled' 'Automatic Topology Generation Enabled' = $Site.'AutomaticTopologyGenerationEnabled' 'Subnets' = if ($Splitter) { $Subnets -join $Splitter } else { $Subnets } 'Subnets Count' = $Subnets.Count 'Domain Controllers' = if ($Splitter) { ($DCs).HostName -join $Splitter } else { ($DCs).HostName } 'Domain Controllers Count' = $DCs.Count 'sDRightsEffective' = $_.'sDRightsEffective' 'Topology Cleanup Enabled' = $_.'TopologyCleanupEnabled' 'Topology Detect Stale Enabled' = $_.'TopologyDetectStaleEnabled' 'Topology Minimum Hops Enabled' = $_.'TopologyMinimumHopsEnabled' 'Universal Group Caching Enabled' = $_.'UniversalGroupCachingEnabled' 'Universal Group Caching Refresh Site' = $_.'UniversalGroupCachingRefreshSite' 'Windows Server 2000 Bridgehead Selection Method Enabled' = $_.'WindowsServer2000BridgeheadSelectionMethodEnabled' 'Windows Server 2000 KCC ISTG Selection Behavior Enabled' = $_.'WindowsServer2000KCCISTGSelectionBehaviorEnabled' 'Windows Server 2003 KCC Behavior Enabled' = $_.'WindowsServer2003KCCBehaviorEnabled' 'Windows Server 2003 KCC Ignore Schedule Enabled' = $_.'WindowsServer2003KCCIgnoreScheduleEnabled' 'Windows Server 2003 KCC SiteLink Bridging Enabled' = $_.'WindowsServer2003KCCSiteLinkBridgingEnabled' 'Created' = $Site.Created 'Modified' = $Site.Modified 'Deleted' = $Site.Deleted } } else { [PSCustomObject] @{ 'Name' = $Site.Name 'DisplayName' = $Site.'DisplayName' 'Description' = $Site.'Description' 'CanonicalName' = $Site.'CanonicalName' 'DistinguishedName' = $Site.'DistinguishedName' 'Location' = $Site.'Location' 'ManagedBy' = $Site.'ManagedBy' 'ProtectedFromAccidentalDeletion' = $Site.'ProtectedFromAccidentalDeletion' 'RedundantServerTopologyEnabled' = $Site.'RedundantServerTopologyEnabled' 'AutomaticInterSiteTopologyGenerationEnabled' = $Site.'AutomaticInterSiteTopologyGenerationEnabled' 'AutomaticTopologyGenerationEnabled' = $Site.'AutomaticTopologyGenerationEnabled' 'Subnets' = if ($Splitter) { $Subnets -join $Splitter } else { $Subnets } 'SubnetsCount' = $Subnets.Count 'DomainControllers' = if ($Splitter) { ($DCs).HostName -join $Splitter } else { ($DCs).HostName } 'DomainControllersCount' = $DCs.Count 'sDRightsEffective' = $_.'sDRightsEffective' 'TopologyCleanupEnabled' = $_.'TopologyCleanupEnabled' 'TopologyDetectStaleEnabled' = $_.'TopologyDetectStaleEnabled' 'TopologyMinimumHopsEnabled' = $_.'TopologyMinimumHopsEnabled' 'UniversalGroupCachingEnabled' = $_.'UniversalGroupCachingEnabled' 'UniversalGroupCachingRefreshSite' = $_.'UniversalGroupCachingRefreshSite' 'WindowsServer2000BridgeheadSelectionMethodEnabled' = $_.'WindowsServer2000BridgeheadSelectionMethodEnabled' 'WindowsServer2000KCCISTGSelectionBehaviorEnabled' = $_.'WindowsServer2000KCCISTGSelectionBehaviorEnabled' 'WindowsServer2003KCCBehaviorEnabled' = $_.'WindowsServer2003KCCBehaviorEnabled' 'WindowsServer2003KCCIgnoreScheduleEnabled' = $_.'WindowsServer2003KCCIgnoreScheduleEnabled' 'WindowsServer2003KCCSiteLinkBridgingEnabled' = $_.'WindowsServer2003KCCSiteLinkBridgingEnabled' 'Created' = $Site.Created 'Modified' = $Site.Modified 'Deleted' = $Site.Deleted } } } } function Get-WinADForestSPNSuffixes { [CmdletBinding()] param( [PSCustomObject] $Forest ) @( #[PSCustomObject] @{ #Name = $Forest.RootDomain #Type = 'Primary / Default SPN' #} foreach ($SPN in $Forest.SPNSuffixes) { [PSCustomObject] @{ Name = $SPN #Type = 'Secondary' } } ) } function Get-WinADForestSubnets { [CmdletBinding()] param( ) $ExludedProperties = @( 'PropertyNames', 'AddedProperties', 'RemovedProperties', 'ModifiedProperties', 'PropertyCount' ) $Properties = @( 'Name', 'DisplayName', 'Description', 'Site', 'ProtectedFromAccidentalDeletion', 'Created', 'Modified', 'Deleted' ) return Get-ADReplicationSubnet -Filter * -Properties $Properties | Select-Object -Property $Properties -ExcludeProperty $ExludedProperties } function Get-WinADForestSubnets1 { [CmdletBinding()] param( [Array] $ForestSubnets ) foreach ($Subnets in $ForestSubnets) { [PsCustomObject] @{ 'Name' = $Subnets.Name 'Description' = $Subnets.Description 'Protected' = $Subnets.ProtectedFromAccidentalDeletion 'Modified' = $Subnets.Modified 'Created' = $Subnets.Created 'Deleted' = $Subnets.Deleted } } } function Get-WinADForestSubnets2 { param( [Array] $ForestSubnets ) @( foreach ($Subnets in $ForestSubnets) { [PsCustomObject] @{ 'Name' = $Subnets.Name 'Site' = $Subnets.Site } } ) } function Get-WinADForestUPNSuffixes { param( [PSCustomObject] $Forest ) @( [PSCustomObject] @{ Name = $Forest.RootDomain Type = 'Primary / Default UPN' } foreach ($UPN in $Forest.UPNSuffixes) { [PSCustomObject] @{ Name = $UPN Type = 'Secondary' } } ) } function Get-WinADKerberosUnconstrainedDelegation { param( ) Get-ADObject -Filter { (UserAccountControl -BAND 0x0080000) -OR (UserAccountControl -BAND 0x1000000) -OR (msDS-AllowedToDelegateTo -like '*') } ` -Properties Name, ObjectClass, PrimaryGroupID, UserAccountControl, ServicePrincipalName, msDS-AllowedToDelegateTo } function Get-WinADRootDSE { [CmdletBinding()] param( [string] $Domain = ($Env:USERDNSDOMAIN).ToLower() ) try { if ($Domain -ne '') { Get-ADRootDSE -Properties * -Server $Domain } else { Get-ADRootDSE -Properties * } } catch { Write-Warning "Getting forest/domain information - $Domain RootDSE Error: $($_.Error)" } } function Get-WinGroupMembers { [CmdletBinding()] param( [Array] $Groups, [string] $Domain = $Env:USERDNSDOMAIN, #[System.Object[]] $ADCatalog, #[System.Object[]] $ADCatalogUsers, [ValidateSet("Recursive", "Standard")][String] $Option, [hashtable] $DomainObjects, [string] $Splitter ) [DateTime] $CurrentDate = Get-Date if ($Option -eq 'Recursive') { [Array] $GroupMembersRecursive = foreach ($Group in $Groups) { try { $GroupMembership = Get-ADGroupMember -Server $Domain -Identity $Group.'Group SID' -Recursive -ErrorAction Stop } catch { $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " " Write-Warning "Couldn't get information about group $($Group.Name) with SID $($Group.'Group SID') error: $ErrorMessage" continue } foreach ($Member in $GroupMembership) { # $Object = (Get-ADObjectFromDistingusishedName -ADCatalog $ADCatalog -DistinguishedName $Member.DistinguishedName) $Object = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $Member.DistinguishedName $Manager = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $Object.Manager [PsCustomObject] @{ 'Group Name' = $Group.'Group Name' 'Group SID' = $Group.'Group SID' 'Group Category' = $Group.'Group Category' 'Group Scope' = $Group.'Group Scope' 'High Privileged Group' = if ($Group.adminCount -eq 1) { $True } else { $False } 'Display Name' = $Object.DisplayName 'Name' = $Member.Name 'User Principal Name' = $Object.UserPrincipalName 'Sam Account Name' = $Object.SamAccountName 'Email Address' = $Object.EmailAddress 'PasswordExpired' = $Object.PasswordExpired 'PasswordLastSet' = $Object.PasswordLastSet 'PasswordNotRequired' = $Object.PasswordNotRequired 'PasswordNeverExpires' = $Object.PasswordNeverExpires 'Enabled' = $Object.Enabled 'SID' = $Member.SID.Value #'Manager' = (Get-ADObjectFromDistingusishedName -ADCatalog $ADCatalogUsers -DistinguishedName $Object.Manager).Name #'ManagerEmail' = (Get-ADObjectFromDistingusishedName -ADCatalog $ADCatalogUsers -DistinguishedName $Object.Manager).EmailAddress 'Manager' = $Manager.Name 'ManagerEmail' = if ($Splitter -ne '') { $Manager.EmailAddress -join $Splitter } else { $Manager.EmailAddress } 'DateExpiry' = Convert-ToDateTime -Timestring $($Object."msDS-UserPasswordExpiryTimeComputed") # -Verbose "DaysToExpire" = (Convert-TimeToDays -StartTime $CurrentDate -EndTime (Convert-ToDateTime -Timestring $($Object."msDS-UserPasswordExpiryTimeComputed"))) "AccountExpirationDate" = $Object.AccountExpirationDate "AccountLockoutTime" = $Object.AccountLockoutTime "AllowReversiblePasswordEncryption" = $Object.AllowReversiblePasswordEncryption "BadLogonCount" = $Object.BadLogonCount "CannotChangePassword" = $Object.CannotChangePassword "CanonicalName" = $Object.CanonicalName 'Given Name' = $Object.GivenName 'Surname' = $Object.Surname "Description" = $Object.Description "DistinguishedName" = $Object.DistinguishedName "EmployeeID" = $Object.EmployeeID "EmployeeNumber" = $Object.EmployeeNumber "LastBadPasswordAttempt" = $Object.LastBadPasswordAttempt "LastLogonDate" = $Object.LastLogonDate "Created" = $Object.Created "Modified" = $Object.Modified "Protected" = $Object.ProtectedFromAccidentalDeletion "Domain" = $Domain } # $Member } } if ($GroupMembersRecursive.Count -eq 1) { return , $GroupMembersRecursive } return $GroupMembersRecursive } if ($Option -eq 'Standard') { [Array] $GroupMembersDirect = foreach ($Group in $Groups) { foreach ($Member in $Group.'Group Members DN') { $Object = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $Member $Manager = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $Object.Manager [PsCustomObject] @{ 'Group Name' = $Group.'Group Name' 'Group SID' = $Group.'Group SID' 'Group Category' = $Group.'Group Category' 'Group Scope' = $Group.'Group Scope' 'DisplayName' = $Object.DisplayName 'High Privileged Group' = if ($Group.adminCount -eq 1) { $True } else { $False } 'UserPrincipalName' = $Object.UserPrincipalName 'SamAccountName' = $Object.SamAccountName 'EmailAddress' = $Object.EmailAddress 'PasswordExpired' = $Object.PasswordExpired 'PasswordLastSet' = $Object.PasswordLastSet 'PasswordNotRequired' = $Object.PasswordNotRequired 'PasswordNeverExpires' = $Object.PasswordNeverExpires 'Enabled' = $Object.Enabled # 'Manager' = (Get-ADObjectFromDistingusishedName -ADCatalog $ADCatalogUsers -DistinguishedName $Object.Manager).Name # 'ManagerEmail' = (Get-ADObjectFromDistingusishedName -ADCatalog $ADCatalogUsers -DistinguishedName $Object.Manager).EmailAddress 'Manager' = $Manager.Name 'ManagerEmail' = if ($Splitter -ne '') { $Manager.EmailAddress -join $Splitter } else { $Manager.EmailAddress } 'DateExpiry' = Convert-ToDateTime -Timestring $($Object."msDS-UserPasswordExpiryTimeComputed") #-Verbose "DaysToExpire" = (Convert-TimeToDays -StartTime $CurrentDate -EndTime (Convert-ToDateTime -Timestring $($Object."msDS-UserPasswordExpiryTimeComputed"))) "AccountExpirationDate" = $Object.AccountExpirationDate "AccountLockoutTime" = $Object.AccountLockoutTime "AllowReversiblePasswordEncryption" = $Object.AllowReversiblePasswordEncryption "BadLogonCount" = $Object.BadLogonCount "CannotChangePassword" = $Object.CannotChangePassword "CanonicalName" = $Object.CanonicalName "Description" = $Object.Description "DistinguishedName" = $Object.DistinguishedName "EmployeeID" = $Object.EmployeeID "EmployeeNumber" = $Object.EmployeeNumber "LastBadPasswordAttempt" = $Object.LastBadPasswordAttempt "LastLogonDate" = $Object.LastLogonDate 'Name' = $Object.Name 'SID' = $Object.SID.Value 'GivenName' = $Object.GivenName 'Surname' = $Object.Surname "Created" = $Object.Created "Modified" = $Object.Modified "Protected" = $Object.ProtectedFromAccidentalDeletion "Domain" = $Domain } } } if ($GroupMembersDirect.Count -eq 1) { return , $GroupMembersDirect } return $GroupMembersDirect } } function Get-WinGroups { [CmdletBinding()] param ( [Array] $Groups, # [System.Object[]] $Users, [string] $Domain = $Env:USERDNSDOMAIN, [string] $Splitter, [hashtable] $DomainObjects ) $ReturnGroups = foreach ($Group in $Groups) { #$User = $Users | & { process { if ($_.DistinguishedName -eq $Group.ManagedBy ) { $_ } } } # | Where-Object { $_.DistinguishedName -eq $Group.ManagedBy } #$User = foreach ($_ in $Users) { # if ($_.DistinguishedName -eq $Group.ManagedBy) { $_ } #} $Manager = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $Group.ManagedBy # $GroupMembers = (Get-ADObjectFromDistingusishedName -Splitter $Splitter -ADCatalog $Data.DomainUsersFullList, $Data.DomainComputersFullList, $Data.DomainGroupsFullList -DistinguishedName $Group.Members -Type 'SamAccountName') #$GroupMembers = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $Group.Members -Splitter $Splitter -Type 'SamAccountName' [PsCustomObject] @{ 'Group Name' = [string] $Group.Name #'Group Display Name' = $Group.DisplayName 'Group Category' = [string] $Group.GroupCategory 'Group Scope' = [string] $Group.GroupScope 'Group SID' = [string] $Group.SID.Value 'High Privileged Group' = if ($Group.adminCount -eq 1) { $True } else { $False } 'Member Count' = $Group.Members.Count 'MemberOf Count' = $Group.MemberOf.Count 'Manager' = $Manager.Name 'Manager Email' = if ($Splitter -ne '') { $Manager.EmailAddress -join $Splitter } else { $Manager.EmailAddress } 'Group Members' = Get-ADObjectFromDNHash -ADCatalog $DomainObjects -DistinguishedName $Group.Members -Splitter $Splitter -Type 'SamAccountName' 'Group Members DN' = $Group.Members #if ($Splitter -ne '') { $Group.Members -join $Splitter } else { $Group.Members } "Domain" = $Domain } } return $ReturnGroups } Function Set-TrustAttributes { [cmdletbinding()] Param( [parameter(Mandatory = $false, ValueFromPipeline = $True)][int32]$Value ) [String[]]$TrustAttributes = @( Foreach ($V in $Value) { if ([int32]$V -band 0x00000001) { "Non Transitive" } if ([int32]$V -band 0x00000002) { "UpLevel" } if ([int32]$V -band 0x00000004) { "Quarantaine (SID Filtering enabled)" } #SID Filtering if ([int32]$V -band 0x00000008) { "Forest Transitive" } if ([int32]$V -band 0x00000010) { "Cross Organization (Selective Authentication enabled)" } #Selective Auth if ([int32]$V -band 0x00000020) { "Within Forest" } if ([int32]$V -band 0x00000040) { "Treat as External" } if ([int32]$V -band 0x00000080) { "Uses RC4 Encryption" } } ) return $TrustAttributes } function Get-WinADDomainInformation { [CmdletBinding()] param ( [string] $Domain, [PSWinDocumentation.ActiveDirectory[]] $TypesRequired, [string] $PathToPasswords, [string] $PathToPasswordsHashes, [switch] $Extended, [switch] $Formatted, [Array] $ForestSchemaComputers, [Array] $ForestSchemaUsers, [switch] $PasswordQuality, [alias('Joiner')][string] $Splitter, [switch] $Parallel, [int] $ResultPageSize = 500000 ) # temporary set here, will be moved to variables when all functions will support it $Formatted = $true $PSDefaultParameterValues["Get-DataInformation:Verbose"] = $PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent $Data = [ordered] @{ } if ($Domain -eq '') { Write-Warning 'Get-WinADDomainInformation - $Domain parameter is empty. Try your domain name like ad.evotec.xyz. Skipping for now...' return } if ($null -eq $TypesRequired) { Write-Verbose 'Get-WinADDomainInformation - TypesRequired is null. Getting all.' $TypesRequired = Get-Types -Types ([PSWinDocumentation.ActiveDirectory]) } # Gets all types $TimeToGenerate = Start-TimeLog # this is required to make sure certain properties are used in domain, such as LAPS, EXCHANGE and so on. # this prevents errors of asking for wrong property - normally that would be provided by forest if ($null -eq $ForestSchemaComputers) { $ForestSchemaComputers = Get-DataInformation -Text "Getting domain information - ForestSchemaPropertiesComputers" { Get-WinADForestSchemaProperties -Schema 'Computers' } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSchemaPropertiesComputers [PSWinDocumentation.ActiveDirectory]::DomainComputersFullList [PSWinDocumentation.ActiveDirectory]::DomainComputersAll [PSWinDocumentation.ActiveDirectory]::DomainComputersAllCount [PSWinDocumentation.ActiveDirectory]::DomainServers [PSWinDocumentation.ActiveDirectory]::DomainServersCount [PSWinDocumentation.ActiveDirectory]::DomainComputers [PSWinDocumentation.ActiveDirectory]::DomainComputersCount [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknown [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknownCount [PSWinDocumentation.ActiveDirectory]::DomainBitlocker [PSWinDocumentation.ActiveDirectory]::DomainLAPS ) } if ($null -eq $ForestSchemaUsers) { $ForestSchemaUsers = Get-DataInformation -Text "Getting domain information - ForestSchemaPropertiesUsers" { Get-WinADForestSchemaProperties -Schema 'Users' } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSchemaPropertiesUsers [PSWinDocumentation.ActiveDirectory]::DomainUsersFullList ) } # This is standard cache $Data.DomainObjects = @{ } # this is cache by netbios name such as EVOTEC\SamAccountName $Data.DomainObjectsNetBios = @{} # Domain Root DSE - Complete TypesNeeded $Data.DomainRootDSE = Get-DataInformation -Text "Getting domain information - $Domain DomainRootDSE" { Get-WinADRootDSE -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainRootDSE [PSWinDocumentation.ActiveDirectory]::DomainGUIDS [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsBasicACL [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsExtendedACL ) $Data.DomainInformation = Get-DataInformation -Text "Getting domain information - $Domain DomainInformation" { Get-WinADDomain -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainInformation [PSWinDocumentation.ActiveDirectory]::DomainRIDs [PSWinDocumentation.ActiveDirectory]::DomainFSMO [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsDN [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsBasicACL [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsExtendedACL [PSWinDocumentation.ActiveDirectory]::DomainAdministrators [PSWinDocumentation.ActiveDirectory]::DomainAdministratorsRecursive [PSWinDocumentation.ActiveDirectory]::DomainEnterpriseAdministrators [PSWinDocumentation.ActiveDirectory]::DomainEnterpriseAdministratorsRecursive [PSWinDocumentation.ActiveDirectory].GetEnumValues() | Where-Object { $_ -like 'DomainPassword*' } [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviliged ) # Groups $Data.DomainGroupsFullList = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupsFullList" { Get-WinADDomainGroupsFullList -Domain $Domain -DomainObjects $Data.DomainObjects -ResultPageSize $ResultPageSize } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupsFullList [PSWinDocumentation.ActiveDirectory]::DomainUsers [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPoliciesUsers [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPoliciesUsersExtended [PSWinDocumentation.ActiveDirectory]::DomainGroups [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviliged [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembers [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembersRecursive ) # Users $Data.DomainUsersFullList = Get-DataInformation -Text "Getting domain information - $Domain DomainUsersFullList" { Get-WinADDomainUsersFullList -Domain $Domain -Extended:$Extended -ForestSchemaUsers $ForestSchemaUsers -DomainObjects $Data.DomainObjects -ResultPageSize $ResultPageSize } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsersFullList [PSWinDocumentation.ActiveDirectory]::DomainUsers [PSWinDocumentation.ActiveDirectory]::DomainUsersAll [PSWinDocumentation.ActiveDirectory]::DomainUsersSystemAccounts [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiring [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiringInclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredInclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredExclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersCount [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPoliciesUsers [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPoliciesUsersExtended [PSWinDocumentation.ActiveDirectory]::DomainGroups [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembers [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembersRecursive [PSWinDocumentation.ActiveDirectory].GetEnumValues() | Where-Object { $_ -like 'DomainPassword*' } ) $Data.DomainComputersFullList = Get-DataInformation -Text "Getting domain information - $Domain DomainComputersFullList" { Get-WinADDomainComputersFullList -Domain $Domain -ForestSchemaComputers $ForestSchemaComputers -DomainObjects $Data.DomainObjects -ResultPageSize $ResultPageSize } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainComputersFullList [PSWinDocumentation.ActiveDirectory]::DomainComputersAll [PSWinDocumentation.ActiveDirectory]::DomainComputersAllCount [PSWinDocumentation.ActiveDirectory]::DomainComputersAllBuildCount [PSWinDocumentation.ActiveDirectory]::DomainServers [PSWinDocumentation.ActiveDirectory]::DomainServersCount [PSWinDocumentation.ActiveDirectory]::DomainComputers [PSWinDocumentation.ActiveDirectory]::DomainComputersCount [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknown [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknownCount [PSWinDocumentation.ActiveDirectory]::DomainBitlocker [PSWinDocumentation.ActiveDirectory]::DomainLAPS [PSWinDocumentation.ActiveDirectory]::DomainUsers [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembers [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembersRecursive [PSWinDocumentation.ActiveDirectory].GetEnumValues() | Where-Object { $_ -like 'DomainPassword*' } ) $Data.DomainComputersAll = Get-DataInformation -Text "Getting domain information - $Domain DomainComputersAll" { Get-WinADDomainComputersAll -DomainComputersFullList $Data.DomainComputersFullList -Splitter $Splitter -DomainObjects $Data.DomainObjects -DomainObjectsNetbios $Data.DomainObjectsNetBios -Domaininformation $Data.DomainInformation } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainComputersAll [PSWinDocumentation.ActiveDirectory]::DomainComputersAllCount [PSWinDocumentation.ActiveDirectory]::DomainComputersAllBuildCount [PSWinDocumentation.ActiveDirectory]::DomainServers [PSWinDocumentation.ActiveDirectory]::DomainServersCount [PSWinDocumentation.ActiveDirectory]::DomainComputers [PSWinDocumentation.ActiveDirectory]::DomainComputersCount [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknown [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknownCount [PSWinDocumentation.ActiveDirectory].GetEnumValues() | Where-Object { $_ -like 'DomainPassword*' } ) $Data.DomainComputersAllCount = Get-DataInformation -Text "Getting domain information - $Domain DomainComputersAllCount" { Get-WinADDomainComputersAllCount -DomainComputersAll $Data.DomainComputersAll } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainComputersAllCount ) $Data.DomainComputersAllBuildCount = Get-DataInformation -Text "Getting domain information - $Domain DomainComputersAllBuildCount" { Get-WinADDomainComputersAllBuildSummary -DomainComputers $Data.DomainComputersAll -Formatted:$Formatted } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainComputersAllBuildCount ) $Data.DomainServers = Get-DataInformation -Text "Getting domain information - $Domain DomainServers" { Get-WinADDomainServers -DomainComputersAll $Data.DomainComputersAll } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainServers [PSWinDocumentation.ActiveDirectory]::DomainComputersAll ) $Data.DomainServersCount = Get-DataInformation -Text "Getting domain information - $Domain DomainServersCount" { Get-WinADDomainServersCount -DomainServers $Data.DomainServers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainServersCount [PSWinDocumentation.ActiveDirectory]::DomainServers ) $Data.DomainComputers = Get-DataInformation -Text "Getting domain information - $Domain DomainComputers" { Get-WinADDomainComputers -DomainComputersAll $Data.DomainComputersAll } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainComputers [PSWinDocumentation.ActiveDirectory]::DomainComputersAll ) $Data.DomainComputersCount = Get-DataInformation -Text "Getting domain information - $Domain DomainComputersCount" { Get-WinADDomainComputersCount -DomainComputers $Data.DomainComputers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainComputersCount [PSWinDocumentation.ActiveDirectory]::DomainComputers ) $Data.DomainComputersUnknown = Get-DataInformation -Text "Getting domain information - $Domain DomainComputersUnknown" { Get-WinADDomainComputersUnknown -DomainComputersAll $Data.DomainComputersAll } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknown [PSWinDocumentation.ActiveDirectory]::DomainComputersAll ) $Data.DomainComputersUnknownCount = Get-DataInformation -Text "Getting domain information - $Domain DomainComputersUnknownCount" { Get-WinADDomainComputersUnknownCount -DomainComputersUnknown $Data.DomainComputersUnknown } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknownCount [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknown ) $Data.DomainRIDs = Get-DataInformation -Text "Getting domain information - $Domain DomainRIDs" { Get-WinADDomainRIDs -DomainInformation $Data.DomainInformation -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainRIDs ) $Data.DomainGUIDS = Get-DataInformation -Text "Getting domain information - $Domain DomainGUIDS" { Get-WinADDomainGUIDs -RootDSE $Data.DomainRootDSE -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGUIDS [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsExtendedACL ) $Data.DomainAuthenticationPolicies = Get-DataInformation -Text "Getting domain information - $Domain DomainAuthenticationPolicies" { Get-ADAuthenticationPolicy -Server $Domain -LDAPFilter '(name=AuthenticationPolicy*)' } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainAuthenticationPolicies ) $Data.DomainAuthenticationPolicySilos = Get-DataInformation -Text "Getting domain information - $Domain DomainAuthenticationPolicySilos" { Get-ADAuthenticationPolicySilo -Server $Domain -Filter 'Name -like "*AuthenticationPolicySilo*"' } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainAuthenticationPolicySilos ) $Data.DomainCentralAccessPolicies = Get-DataInformation -Text "Getting domain information - $Domain DomainCentralAccessPolicies" { Get-ADCentralAccessPolicy -Server $Domain -Filter * } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainCentralAccessPolicies ) $Data.DomainCentralAccessRules = Get-DataInformation -Text "Getting domain information - $Domain DomainCentralAccessRules" { Get-ADCentralAccessRule -Server $Domain -Filter * } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainCentralAccessRules ) $Data.DomainClaimTransformPolicies = Get-DataInformation -Text "Getting domain information - $Domain DomainClaimTransformPolicies" { Get-ADClaimTransformPolicy -Server $Domain -Filter * } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainClaimTransformPolicies ) $Data.DomainClaimTypes = Get-DataInformation -Text "Getting domain information - $Domain DomainClaimTypes" { Get-ADClaimType -Server $Domain -Filter * } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainClaimTypes ) # This won't be in main Data, needed for DomainDNSSrv/DomainDNSA $DomainDNSData = Get-DataInformation -Text "Getting domain information - $Domain DomainDNSData" { Get-WinADDomainDNSData -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainDNSSRV [PSWinDocumentation.ActiveDirectory]::DomainDNSA ) $Data.DomainDNSSrv = Get-DataInformation -Text "Getting domain information - $Domain DomainDNSSrv" { $DomainDNSData.SRV } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainDNSSrv ) $Data.DomainDNSA = Get-DataInformation -Text "Getting domain information - $Domain DomainDNSA" { $DomainDNSData.A } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainDNSA ) $Data.DomainFSMO = Get-DataInformation -Text "Getting domain information - $Domain DomainFSMO" { Get-WinADDomainFSMO -Domain $Domain -DomainInformation $Data.DomainInformation } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainFSMO [PSWinDocumentation.ActiveDirectory]::DomainTrusts ) $Data.DomainTrustsClean = Get-DataInformation -Text "Getting domain information - $Domain DomainTrustsClean" { Get-WinADDomainTrustsClean -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainTrustsClean [PSWinDocumentation.ActiveDirectory]::DomainTrusts ) $Data.DomainTrusts = Get-DataInformation -Text "Getting domain information - $Domain DomainTrusts" { Get-WinADDomainTrusts -DomainPDC $Data.DomainFSMO.'PDC Emulator' -Trusts $Data.DomainTrustsClean -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainTrusts ) $Data.DomainGroupPoliciesClean = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupPoliciesClean" { Get-GPO -Domain $Domain -All } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesClean [PSWinDocumentation.ActiveDirectory]::DomainGroupPolicies [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesDetails [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesACL ) $Data.DomainGroupPolicies = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupPolicies" { Get-WinADDomainGroupPolicies -GroupPolicies $Data.DomainGroupPoliciesClean -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupPolicies ) $Data.DomainGroupPoliciesDetails = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupPoliciesDetails" { Get-WinADDomainGroupPoliciesDetails -GroupPolicies $Data.DomainGroupPoliciesClean -Domain $Domain -Splitter $Splitter } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesDetails ) $Data.DomainGroupPoliciesACL = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupPoliciesACL" { Get-GPOZaurrPermission -Forest $Forest -IncludeDomains $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesACL ) $Data.DomainGroupPoliciesACLConsistency = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupPoliciesACLConsistency" { Get-GPOZaurrPermissionConsistency -Forest $Forest -IncludeDomains $Domain -VerifyInheritance } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesACLConsistency ) $Data.DomainGroupPoliciesSysVol = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupPoliciesSysVol" { Get-GPOZaurrSysvol -Forest $Forest -IncludeDomains $Domain -GPOs $Data.DomainGroupPoliciesClean } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesSysVol ) $Data.DomainGroupPoliciesOwners = Get-DataInformation -Text "Gettting domain information - $Domain DomainGroupPoliciesOwners" { Get-GPOZaurrOwner -Forest $Forest -IncludeDomains $Domain -IncludeSysvol } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesOwners ) $Data.DomainGroupPoliciesWMI = Get-DataInformation -Text "Gettting domain information - $Domain DomainGroupPoliciesWMI" { Get-GPOZaurrWMI -Forest $Forest -IncludeDomains $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesWMI ) $Data.DomainGroupPoliciesLinksSummary = Get-DataInformation -Text "Gettting domain information - $Domain DomainGroupPoliciesLinksSummary" { Get-GPOZaurrLinkSummary -Report LinksSummary -Forest $Forest -IncludeDomains $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupPoliciesLinksSummary ) $Data.DomainBitlocker = Get-DataInformation -Text "Getting domain information - $Domain DomainBitlocker" { Get-WinADDomainBitlocker -Domain $Domain -Computers $Data.DomainComputersFullList } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainBitlocker ) $Data.DomainLAPS = Get-DataInformation -Text "Getting domain information - $Domain DomainLAPS" { Get-WinADDomainLAPS -Domain $Domain -Computers $Data.DomainComputersFullList -Splitter $Splitter } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainLAPS ) $Data.DomainDefaultPasswordPolicy = Get-DataInformation -Text "Getting domain information - $Domain DomainDefaultPasswordPolicy" { Get-WinADDomainDefaultPasswordPolicy -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainDefaultPasswordPolicy ) $Data.DomainOrganizationalUnitsClean = Get-DataInformation -Text "Getting domain information - $Domain DomainOrganizationalUnitsClean" { Get-ADOrganizationalUnit -Server $Domain -Properties * -Filter * } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsClean [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnits [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsDN [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsBasicACL [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsExtendedACL ) $Data.DomainOrganizationalUnits = Get-DataInformation -Text "Getting domain information - $Domain DomainOrganizationalUnits" { Get-WinADDomainOrganizationalUnits -Domain $Domain -OrgnaizationalUnits $Data.DomainOrganizationalUnitsClean -DomainObjects $Data.DomainObjects } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnits ) $Data.DomainOrganizationalUnitsDN = Get-DataInformation -Text "Getting domain information - $Domain DomainOrganizationalUnitsDN" { @( $Data.DomainInformation.DistinguishedName $Data.DomainOrganizationalUnitsClean.DistinguishedName # TODO: # Wth needs to fix $Data.DomainContainers.DistinguishedName ) } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsDN ) $Data.DomainOrganizationalUnitsBasicACL = Get-DataInformation -Text "Getting domain information - $Domain DomainOrganizationalUnitsBasicACL" { Get-WinADDomainOrganizationalUnitsACL ` -DomainOrganizationalUnitsClean $Data.DomainOrganizationalUnitsClean ` -Domain $Domain ` -NetBiosName $Data.DomainInformation.NetBIOSName ` -RootDomainNamingContext $Data.DomainRootDSE.rootDomainNamingContext } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsBasicACL ) $Data.DomainOrganizationalUnitsExtendedACL = Get-DataInformation -Text "Getting domain information - $Domain DomainOrganizationalUnitsExtendedACL" { Get-WinADDomainOrganizationalUnitsACLExtended ` -DomainOrganizationalUnitsClean $Data.DomainOrganizationalUnitsClean ` -Domain $Domain ` -NetBiosName $Data.DomainInformation.NetBIOSName ` -RootDomainNamingContext $Data.DomainRootDSE.rootDomainNamingContext ` -GUID $Data.DomainGUIDS } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainOrganizationalUnitsExtendedACL ) <# $Data.DomainUsers = Get-DataInformation -Text "Getting domain information - $Domain DomainUsers" { Get-WinUsers ` -Users $Data.DomainUsersFullList ` -Domain $Domain ` -ADCatalog $Data.DomainUsersFullList, $Data.DomainComputersFullList, $Data.DomainGroupsFullList ` -ADCatalogUsers $Data.DomainUsersFullList } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsers [PSWinDocumentation.ActiveDirectory]::DomainUsersAll [PSWinDocumentation.ActiveDirectory]::DomainUsersSystemAccounts [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiring [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiringInclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredInclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredExclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersCount ) #> $Data.DomainUsers = Get-DataInformation -Text "Getting domain information - $Domain DomainUsers" { Get-WinADDomainUsersAll -Users $Data.DomainUsersFullList -Domain $Domain -DomainObjects $Data.DomainObjects -Splitter $Splitter -DomainObjectsNetbios $Data.DomainObjectsNetBios -Domaininformation $Data.DomainInformation } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsers [PSWinDocumentation.ActiveDirectory]::DomainUsersAll [PSWinDocumentation.ActiveDirectory]::DomainUsersSystemAccounts [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiring [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiringInclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredInclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredExclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersCount [PSWinDocumentation.ActiveDirectory].GetEnumValues() | Where-Object { $_ -like 'DomainPassword*' } ) $Data.DomainUsersAll = Get-DataInformation -Text "Getting domain information - $Domain DomainUsersAll" { Get-WinADDomainUsersAllFiltered -DomainUsers $Data.DomainUsers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsersAll [PSWinDocumentation.ActiveDirectory].GetEnumValues() | Where-Object { $_ -like 'DomainPassword*' } ) $Data.DomainUsersSystemAccounts = Get-DataInformation -Text "Getting domain information - $Domain DomainUsersSystemAccounts" { Get-WinADDomainUsersSystemAccounts -DomainUsers $Data.DomainUsers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsersSystemAccounts ) $Data.DomainUsersNeverExpiring = Get-DataInformation -Text "Getting domain information - $Domain DomainUsersNeverExpiring" { Get-WinADDomainUsersNeverExpiring -DomainUsers $Data.DomainUsers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiring ) $Data.DomainUsersNeverExpiringInclDisabled = Get-DataInformation -Text "Getting domain information - $Domain DomainUsersNeverExpiringInclDisabled" { Get-WinADDomainUsersNeverExpiringInclDisabled -DomainUsers $Data.DomainUsers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiringInclDisabled ) $Data.DomainUsersExpiredInclDisabled = Get-DataInformation -Text "Getting domain information - $Domain DomainUsersExpiredInclDisabled" { Get-WinADDomainUsersExpiredInclDisabled -DomainUsers $Data.DomainUsers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredInclDisabled ) $Data.DomainUsersExpiredExclDisabled = Get-DataInformation -Text "Getting domain information - $Domain DomainUsersExpiredExclDisabled" { Get-WinADDomainUsersExpiredExclDisabled -DomainUsers $Data.DomainUsers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredExclDisabled ) $Data.DomainUsersCount = Get-DataInformation -Text "Getting domain information - $Domain DomainUsersCount" { Get-WinADDomainAllUsersCount ` -DomainUsers $Data.DomainUsers ` -DomainUsersAll $Data.DomainUsersAll ` -DomainUsersExpiredExclDisabled $Data.DomainUsersExpiredExclDisabled ` -DomainUsersExpiredInclDisabled $Data.DomainUsersExpiredInclDisabled ` -DomainUsersNeverExpiring $Data.DomainUsersNeverExpiring ` -DomainUsersNeverExpiringInclDisabled $Data.DomainUsersNeverExpiringInclDisabled ` -DomainUsersSystemAccounts $Data.DomainUsersSystemAccounts } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainUsersCount <# [PSWinDocumentation.ActiveDirectory]::DomainUsers [PSWinDocumentation.ActiveDirectory]::DomainUsersAll [PSWinDocumentation.ActiveDirectory]::DomainUsersSystemAccounts [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiring [PSWinDocumentation.ActiveDirectory]::DomainUsersNeverExpiringInclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredInclDisabled [PSWinDocumentation.ActiveDirectory]::DomainUsersExpiredExclDisabled #> ) $Data.DomainControllers = Get-DataInformation -Text "Getting domain information - $Domain DomainControllers" { Get-WinADDomainControllersInternal -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainControllers ) $Data.DomainFineGrainedPolicies = Get-DataInformation -Text "Getting domain information - $Domain DomainFineGrainedPolicies" { Get-WinADDomainFineGrainedPolicies -Domain $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPolicies [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPoliciesUsers [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPoliciesUsersExtended ) $Data.DomainFineGrainedPoliciesUsers = Get-DataInformation -Text "Getting domain information - $Domain DomainFineGrainedPoliciesUsers" { Get-WinADDomainFineGrainedPoliciesUsers -DomainFineGrainedPolicies $Data.DomainFineGrainedPolicies -DomainObjects $Data.DomainObjects #-DomainUsersFullList $Data.DomainUsersFullList ` # -DomainGroupsFullList $Data.DomainGroupsFullList ` } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPoliciesUsers ) $Data.DomainFineGrainedPoliciesUsersExtended = Get-DataInformation -Text "Getting domain information - $Domain DomainFineGrainedPoliciesUsersExtended" { Get-WinADDomainFineGrainedPoliciesUsersExtended -DomainFineGrainedPolicies $Data.DomainFineGrainedPolicies -Domain $Domain -DomainObjects $Data.DomainObjects # -DomainUsersFullList $Data.DomainUsersFullList ` # -DomainGroupsFullList $Data.DomainGroupsFullList ` } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainFineGrainedPoliciesUsersExtended ) $Data.DomainGroups = Get-DataInformation -Text "Getting domain information - $Domain DomainGroups" { Get-WinGroups -Groups $Data.DomainGroupsFullList -Domain $Domain -Splitter $Splitter -DomainObjects $Data.DomainObjects } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroups [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviliged [PSWinDocumentation.ActiveDirectory]::DomainGroupsSpecial ) $Data.DomainGroupsMembers = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupsMembers" { Get-WinGroupMembers -Groups $Data.DomainGroups ` -Domain $Domain ` -Option Standard ` -DomainObjects $Data.DomainObjects #-ADCatalog $Data.DomainUsersFullList, $Data.DomainComputersFullList, $Data.DomainGroupsFullList ` # -ADCatalogUsers $Data.DomainUsersFullList ` } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembers [PSWinDocumentation.ActiveDirectory]::DomainGroupsSpecialMembers [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviligedMembers [PSWinDocumentation.ActiveDirectory]::DomainAdministrators [PSWinDocumentation.ActiveDirectory]::DomainEnterpriseAdministrators ) $Data.DomainGroupsMembersRecursive = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupsMembersRecursive" { Get-WinGroupMembers -Groups $Data.DomainGroups ` -Domain $Domain ` -Option Recursive ` -DomainObjects $Data.DomainObjects # -ADCatalog $Data.DomainUsersFullList, $Data.DomainComputersFullList, $Data.DomainGroupsFullList ` # -ADCatalogUsers $Data.DomainUsersFullList ` } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupsMembersRecursive [PSWinDocumentation.ActiveDirectory]::DomainGroupsSpecialMembersRecursive [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviligedMembersRecursive [PSWinDocumentation.ActiveDirectory]::DomainAdministratorsRecursive [PSWinDocumentation.ActiveDirectory]::DomainEnterpriseAdministratorsRecursive ) $Data.DomainGroupsPriviliged = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupsPriviliged" { Get-DomainGroupsPriviliged -DomainGroups $Data.DomainGroups -DomainInformation $Data.DomainInformation } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviliged [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviligedMembers [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviligedMembersRecursive ) $Data.DomainGroupsSpecial = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupsSpecial" { Get-WinADDomainGroupsSpecial -DomainGroups $Data.DomainGroups } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupsSpecial [PSWinDocumentation.ActiveDirectory]::DomainGroupMembersRecursiveSpecial ) $Data.DomainGroupsSpecialMembers = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupsSpecialMembers" { Get-WinADDomainGroupsSpecialMembers -DomainGroupsMembers $Data.DomainGroupsMembers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupsSpecialMembers ) $Data.DomainGroupsSpecialMembersRecursive = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupsSpecialMembersRecursive" { Get-WinADDomainGroupsSpecialMembersRecursive -DomainGroupsMembersRecursive $Data.DomainGroupsMembersRecursive } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupsSpecialMembersRecursive ) $Data.DomainGroupsPriviligedMembers = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupsPriviligedMembers" { ### NEEDS REVIEW, something looks wrong Get-WinADDomainGroupsPriviligedMembers -DomainGroupsMembers $Data.DomainGroupsMembers -DomainGroupsPriviliged $Data.DomainGroupsPriviliged } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviligedMembers ) $Data.DomainGroupsPriviligedMembersRecursive = Get-DataInformation -Text "Getting domain information - $Domain DomainGroupsPriviligedMembersRecursive" { ### NEEDS REVIEW, something looks wrong Get-WinADDomainGroupsPriviligedMembersRecursive -DomainGroupsMembersRecursive $Data.DomainGroupsMembersRecursive -DomainGroupsPriviliged $Data.DomainGroupsPriviliged } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainGroupsPriviligedMembersRecursive ) $Data.DomainAdministrators = Get-DataInformation -Text "Getting domain information - $Domain DomainAdministrators" { Get-WinADDomainAdministrators -DomainGroupsMembers $Data.DomainGroupsMembers -DomainInformation $Data.DomainInformation } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainAdministrators ) $Data.DomainAdministratorsRecursive = Get-DataInformation -Text "Getting domain information - $Domain DomainAdministratorsRecursive" { Get-WinADDomainAdministratorsRecursive -DomainGroupsMembersRecursive $Data.DomainGroupsMembersRecursive -DomainInformation $Data.DomainInformation } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainAdministratorsRecursive ) $Data.DomainEnterpriseAdministrators = Get-DataInformation -Text "Getting domain information - $Domain DomainEnterpriseAdministrators" { Get-WinADDomainEnterpriseAdministrators -DomainGroupsMembers $Data.DomainGroupsMembers -DomainInformation $Data.DomainInformation } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainEnterpriseAdministrators ) $Data.DomainEnterpriseAdministratorsRecursive = Get-DataInformation -Text "Getting domain information - $Domain DomainEnterpriseAdministratorsRecursive" { Get-WinADDomainEnterpriseAdministratorsRecursive -DomainGroupsMembersRecursive $Data.DomainGroupsMembersRecursive -DomainInformation $Data.DomainInformation } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainEnterpriseAdministratorsRecursive ) $Data.DomainWellKnownFolders = Get-DataInformation -Text "Gettting domain information - $Domain DomainWellKnownFolders" { Get-WinADWellKnownFolders -IncludeDomains $Domain } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainWellKnownFolders ) # PASSWORD QUALITY SECTION $Data.DomainPasswordDataUsers = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordDataUsers" { Get-WinADDomainPassword -DnsRoot $Data.DomainInformation.DNSRoot -DistinguishedName $Data.DomainInformation.DistinguishedName } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory].GetEnumValues() | Where-Object { $_ -like 'DomainPassword*' } ) $Data.DomainPasswordDataPasswords = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordDataPasswords" { Get-WinADDomainPasswordQuality ` -FilePath $PathToPasswords ` -DomainDistinguishedName $Data.DomainInformation.DistinguishedName ` -DnsRoot $Data.DomainInformation.DnsRoot ` -Verbose:$false ` -PasswordQualityUsers $Data.DomainPasswordDataUsers ` -PasswordQuality:$PasswordQuality.IsPresent ` -DomainObjectsNetbios $Data.DomainObjectsNetBios } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory].GetEnumValues() | Where-Object { $_ -like 'DomainPassword*' } ) $Data.DomainPasswordDataPasswordsHashes = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordDataPasswordsHashes" { Get-WinADDomainPasswordQuality ` -FilePath $PathToPasswordsHashes ` -DomainDistinguishedName $Data.DomainInformation.DistinguishedName ` -DnsRoot $DomainInformation.DnsRoot ` -UseHashes ` -Verbose:$false ` -PasswordQualityUsers $Data.DomainPasswordDataUsers ` -PasswordQuality:$PasswordQuality.IsPresent ` -DomainObjectsNetbios $Data.DomainObjectsNetBios } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordHashesWeakPassword, [PSWinDocumentation.ActiveDirectory]::DomainPasswordHashesWeakPasswordEnabled, [PSWinDocumentation.ActiveDirectory]::DomainPasswordHashesWeakPasswordDisabled ) if ($Data.DomainPasswordDataPasswords) { $PasswordsQuality = $Data.DomainPasswordDataPasswords } elseif ($Data.DomainPasswordDataPasswordsHashes) { $PasswordsQuality = $Data.DomainPasswordDataPasswordsHashes } else { $PasswordsQuality = $null } $Data.DomainPasswordClearTextPassword = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordClearTextPassword" { $PasswordsQuality.DomainPasswordClearTextPassword } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordClearTextPassword ) $Data.DomainPasswordLMHash = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordLMHash" { $PasswordsQuality.DomainPasswordLMHash } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordLMHash ) $Data.DomainPasswordEmptyPassword = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordEmptyPassword" { $PasswordsQuality.DomainPasswordEmptyPassword } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordEmptyPassword ) $Data.DomainPasswordEmptyPassword = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordEmptyPassword" { $PasswordsQuality.DomainPasswordEmptyPassword } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordEmptyPassword ) $Data.DomainPasswordWeakPassword = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordWeakPassword" { $PasswordsQuality.DomainPasswordWeakPassword } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordWeakPassword ) $Data.DomainPasswordWeakPasswordEnabled = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordWeakPasswordEnabled" { $PasswordsQuality.DomainPasswordWeakPasswordEnabled } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordWeakPasswordEnabled ) $Data.DomainPasswordWeakPasswordDisabled = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordWeakPasswordDisabled" { $PasswordsQuality.DomainPasswordWeakPasswordDisabled } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordWeakPasswordDisabled ) $Data.DomainPasswordWeakPasswordList = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordWeakPasswordList" { $PasswordsQuality.DomainPasswordWeakPasswordList } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordWeakPasswordList ) $Data.DomainPasswordDefaultComputerPassword = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordDefaultComputerPassword" { $PasswordsQuality.DomainPasswordDefaultComputerPassword } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordDefaultComputerPassword ) $Data.DomainPasswordPasswordNotRequired = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordPasswordNotRequired" { $PasswordsQuality.DomainPasswordPasswordNotRequired } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordPasswordNotRequired ) $Data.DomainPasswordPasswordNeverExpires = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordPasswordNeverExpires" { $PasswordsQuality.DomainPasswordPasswordNeverExpires } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordPasswordNeverExpires ) $Data.DomainPasswordAESKeysMissing = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordAESKeysMissing" { $PasswordsQuality.DomainPasswordAESKeysMissing } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordAESKeysMissing ) $Data.DomainPasswordPreAuthNotRequired = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordPreAuthNotRequired" { $PasswordsQuality.DomainPasswordPreAuthNotRequired } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordPreAuthNotRequired ) $Data.DomainPasswordDESEncryptionOnly = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordDESEncryptionOnly" { $PasswordsQuality.DomainPasswordDESEncryptionOnly } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordDESEncryptionOnly ) $Data.DomainPasswordDelegatableAdmins = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordDelegatableAdmins" { $PasswordsQuality.DomainPasswordDelegatableAdmins } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordDelegatableAdmins ) $Data.DomainPasswordDuplicatePasswordGroups = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordDuplicatePasswordGroups" { $PasswordsQuality.DomainPasswordDuplicatePasswordGroups } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordDuplicatePasswordGroups ) $Data.DomainPasswordHashesWeakPassword = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordHashesWeakPassword" { $PasswordsQuality.DomainPasswordHashesWeakPassword } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordHashesWeakPassword ) $Data.DomainPasswordHashesWeakPasswordEnabled = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordHashesWeakPasswordEnabled" { $PasswordsQuality.DomainPasswordHashesWeakPasswordEnabled } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordHashesWeakPasswordEnabled ) $Data.DomainPasswordHashesWeakPasswordDisabled = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordHashesWeakPasswordDisabled" { $Data.DomainPasswordDataPasswordsHashes.DomainPasswordWeakPasswordDisabled } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordHashesWeakPasswordDisabled ) $Data.DomainPasswordSmartCardUsersWithPassword = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordSmartCardUsersWithPassword" { $Data.DomainPasswordDataPasswordsHashes.DomainPasswordSmartCardUsersWithPassword } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordSmartCardUsersWithPassword ) $Data.DomainPasswordStats = Get-DataInformation -Text "Getting domain information - $Domain DomainPasswordStats" { Get-WinADDomainPasswordStats -PasswordsQuality $PasswordsQuality -TypesRequired $TypesRequired ` -DomainPasswordHashesWeakPassword $Data.DomainPasswordHashesWeakPassword ` -DomainPasswordHashesWeakPasswordEnabled $Data.DomainPasswordHashesWeakPasswordEnabled ` -DomainPasswordHashesWeakPasswordDisabled $Data.DomainPasswordHashesWeakPasswordDisabled } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::DomainPasswordStats ) $EndTime = Stop-TimeLog -Time $TimeToGenerate Write-Verbose "Getting domain information - $Domain - Time to generate: $EndTime" return $Data } function Get-WinADForestInformation { [CmdletBinding()] param ( [PSWinDocumentation.ActiveDirectory[]] $TypesRequired, [switch] $RequireTypes, [string] $PathToPasswords, [string] $PathToPasswordsHashes, [switch] $PasswordQuality, [switch] $DontRemoveSupportData, [switch] $DontRemoveEmpty, [switch] $Formatted, [string] $Splitter, [switch] $Parallel, [switch] $Extended, [int] $ResultPageSize = 500000 ) $PSDefaultParameterValues["Get-DataInformation:Verbose"] = $PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent Write-Verbose -Message "Getting all information - Start" Write-Verbose -Message "Getting forest information - Start" $TimeToGenerateForest = Start-TimeLog if ($null -eq $TypesRequired) { # Gets all types Write-Verbose 'Getting forest information - TypesRequired is null. Getting all.' $TypesRequired = Get-Types -Types ([PSWinDocumentation.ActiveDirectory]) } # Forest is required to get all domains $Forest = Get-WinADForest if ($null -eq $Forest) { Write-Warning "Getting forest information - Failed to get information. This may mean that RSAT is not available or you can't connect to Active Directory." return } # Start of building data $Data = [ordered] @{ } $Data.ForestRootDSE = Get-DataInformation -Text 'Getting forest information - ForestRootDSE' { Get-WinADRootDSE } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestRootDSE [PSWinDocumentation.ActiveDirectory]::ForestInformation ) $Data.ForestInformation = Get-DataInformation -Text 'Getting forest information - Forest' { Get-WinADForestInfo -Forest $Forest -RootDSE $Data.ForestRootDSE } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestInformation ) # This is Forest Schema Properties for Users and Computers $Data.ForestSchemaPropertiesComputers = Get-DataInformation -Text "Getting forest information - ForestSchemaPropertiesComputers" { Get-WinADForestSchemaProperties -Schema 'Computers' } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSchemaPropertiesComputers [PSWinDocumentation.ActiveDirectory]::DomainComputersFullList [PSWinDocumentation.ActiveDirectory]::DomainComputersAll [PSWinDocumentation.ActiveDirectory]::DomainComputersAllCount [PSWinDocumentation.ActiveDirectory]::DomainServers [PSWinDocumentation.ActiveDirectory]::DomainServersCount [PSWinDocumentation.ActiveDirectory]::DomainComputers [PSWinDocumentation.ActiveDirectory]::DomainComputersCount [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknown [PSWinDocumentation.ActiveDirectory]::DomainComputersUnknownCount [PSWinDocumentation.ActiveDirectory]::DomainBitlocker [PSWinDocumentation.ActiveDirectory]::DomainLAPS [PSWinDocumentation.ActiveDirectory]::ForestOptionalFeatures ) $Data.ForestSchemaPropertiesUsers = Get-DataInformation -Text "Getting forest information - ForestSchemaPropertiesUsers" { Get-WinADForestSchemaProperties -Schema 'Users' } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSchemaPropertiesUsers [PSWinDocumentation.ActiveDirectory]::DomainUsersFullList ) ## Forest Information $Data.ForestUPNSuffixes = Get-DataInformation -Text 'Getting forest information - ForestUPNSuffixes' { Get-WinADForestUPNSuffixes -Forest $Forest } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestUPNSuffixes ) $Data.ForestSPNSuffixes = Get-DataInformation -Text 'Getting forest information - ForestSPNSuffixes' { Get-WinADForestSPNSuffixes -Forest $Forest } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSPNSuffixes ) # Forest DC GC - Review if required $Data.ForestGlobalCatalogs = Get-DataInformation -Text 'Getting forest information - ForestGlobalCatalogs' { $Forest.GlobalCatalogs } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestGlobalCatalogs ) $Data.ForestFSMO = Get-DataInformation -Text 'Getting forest information - ForestFSMO' { Get-WinADForestFSMO -Forest $Forest } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestFSMO ) $Data.ForestDomainControllers = Get-DataInformation -Text 'Getting forest information - ForestDomainControllers' { # External command from PSSharedGoods Get-WinADForestControllers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestDomainControllers ) # Forest Sites $Data.ForestSites = Get-DataInformation -Text 'Getting forest information - ForestSites' { Get-WinADForestSites -Formatted:$Formatted -Splitter $Splitter } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSites [PSWinDocumentation.ActiveDirectory]::ForestSites1 [PSWinDocumentation.ActiveDirectory]::ForestSites2 ) $Data.ForestSites1 = Get-DataInformation -Text 'Getting forest information - ForestSites1' { if ($Formatted) { $Data.ForestSites | Select-Object -Property Name, Description, Protected, 'Subnets Count', 'Domain Controllers Count', Modified } else { $Data.ForestSites | Select-Object -Property Name, Description, Protected, 'SubnetsCount', 'DomainControllersCount', Modified } #Get-WinADForestSites1 -ForestSites $Data.ForestSites } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSites1 ) $Data.ForestSites2 = Get-DataInformation -Text 'Getting forest information - ForestSites2' { if ($Formatted) { $Data.ForestSites | Select-Object -Property 'Topology Cleanup Enabled', 'Topology DetectStale Enabled', 'Topology MinimumHops Enabled', 'Universal Group Caching Enabled', 'Universal Group Caching Refresh Site' } else { $Data.ForestSites | Select-Object -Property TopologyCleanupEnabled, TopologyDetectStaleEnabled, TopologyMinimumHopsEnabled, UniversalGroupCachingEnabled, UniversalGroupCachingRefreshSite } #Get-WinADForestSites2 -ForestSites $Data.ForestSites } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSites2 ) ## Forest Subnets $Data.ForestSubnets = Get-DataInformation -Text 'Getting forest information - ForestSubnets' { Get-WinADForestSubnets } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSubnets [PSWinDocumentation.ActiveDirectory]::ForestSubnets1 [PSWinDocumentation.ActiveDirectory]::ForestSubnets2 ) $Data.ForestSubnets1 = Get-DataInformation -Text 'Getting forest information - ForestSubnets1' { Get-WinADForestSubnets1 -ForestSubnets $Data.ForestSubnets } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSubnets1 ) $Data.ForestSubnets2 = Get-DataInformation -Text 'Getting forest information - ForestSubnets2' { Get-WinADForestSubnets2 -ForestSubnets $Data.ForestSubnets } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSubnets2 ) ## Forest Site Links $Data.ForestSiteLinks = Get-DataInformation -Text 'Getting forest information - ForestSiteLinks' { Get-WinADForestSiteLinks } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestSiteLinks ) ## Forest Optional Features $Data.ForestOptionalFeatures = Get-DataInformation -Text 'Getting forest information - ForestOptionalFeatures' { Get-WinADForestOptionalFeatures -ComputerProperties $ForestSchemaPropertiesComputers } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestOptionalFeatures ) $Data.ForestReplication = Get-DataInformation -Text 'Getting forest information - ForestReplication' { Get-WinADForestReplication -Extended:$Extended } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory]::ForestReplication ) $EndTimeForest = Stop-TimeLog -Time $TimeToGenerateForest -Continue $Data.FoundDomains = Get-DataInformation -Text 'Getting forest information - Domains' { ### Generate Data from Domains $FoundDomains = @{ } foreach ($Domain in $Forest.Domains) { $FoundDomains.$Domain = Get-WinADDomainInformation -Domain $Domain ` -TypesRequired $TypesRequired ` -PathToPasswords $PathToPasswords ` -PathToPasswordsHashes $PathToPasswordsHashes ` -ForestSchemaComputers $Data.ForestSchemaPropertiesComputers ` -ForestSchemaUsers $Data.ForestSchemaPropertiesUsers -PasswordQuality:$PasswordQuality.IsPresent -Splitter $Splitter -Parallel:$Parallel.IsPresent -ResultPageSize $ResultPageSize -Formatted:$formatted.IsPresent } $FoundDomains } -TypesRequired $TypesRequired -TypesNeeded @( [PSWinDocumentation.ActiveDirectory].GetEnumValues() | Where-Object { $_ -like 'Domain*' } ) $EndTimeAll = Stop-TimeLog -Time $TimeToGenerateForest # cleans up empty fields created during gathering process Clear-DataInformation -Data $Data -TypesRequired $TypesRequired -DontRemoveSupportData:$DontRemoveSupportData -DontRemoveEmpty:$DontRemoveEmpty # final output Write-Verbose "Getting forest information - Stop - Time to generate: $EndTimeForest" Write-Verbose "Getting all information - Stop - Time to generate: $EndTimeAll" return $Data } function Invoke-ADPasswordAnalysis { [CmdletBinding()] param( [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string] $PathToPasswords, [switch] $UseNTLMHashes ) $Forest = Get-ADForest $Output = [ordered] @{ } $DomainObjectsNetbios = @{} # Cache $ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation $ForestSchemaComputers = Get-WinADForestSchemaProperties -Schema 'Computers' -Forest $Forest $ForestSchemaUsers = Get-WinADForestSchemaProperties -Schema 'Users' -Forest $Forest foreach ($Domain in $ForestInformation.Domains) { $Passwords = Get-WinADDomainPassword -DnsRoot $ForestInformation.DomainsExtended[$Domain].DNSRoot -DistinguishedName $ForestInformation.DomainsExtended[$Domain].DistinguishedName $Users = Get-WinADDomainUsersFullList -Domain $Domain -Extended:$Extended -ForestSchemaUsers $ForestSchemaUsers -DomainObjects $Data.DomainObjects -ResultPageSize $ResultPageSize $Computers = Get-WinADDomainComputersFullList -Domain $Domain -ForestSchemaComputers $ForestSchemaComputers -DomainObjects $Data.DomainObjects -ResultPageSize $ResultPageSize # We use null because it returns all data to DomainObjectsNetbios cache which is then used to $null = Get-WinADDomainUsersAll -Users $Users -DomainObjectsNetbios $DomainObjectsNetbios -DomainInformation $ForestInformation.DomainsExtended[$Domain] $null = Get-WinADDomainComputersAll -DomainComputersFullList $Computers -DomainObjectsNetbios $DomainObjectsNetbios -DomainInformation $ForestInformation.DomainsExtended[$Domain] $Quality = Get-WinADDomainPasswordQuality -DnsRoot $ForestInformation.DomainsExtended[$Domain].DnsRoot -DomainObjectsNetbios $DomainObjectsNetbios -PasswordQuality ` -DomainDistinguishedName $ForestInformation.DomainsExtended[$Domain].DistinguishedName -PasswordQualityUsers $Passwords -FilePath $PathToPasswords -UseHashes:$UseNTLMHashes.IsPresent $Output["$($ForestInformation.DomainsExtended[$Domain].DnsRoot)"] = $Quality } $Output } Export-ModuleMember -Function @('Get-WinADDomainInformation', 'Get-WinADForestInformation', 'Invoke-ADPasswordAnalysis') -Alias @() |