Public/Get-ALHADOUPermission.ps1
<#PSScriptInfo
.VERSION 1.3.0 .GUID c731d7d1-bf89-441a-8b85-47b435ac1492 .AUTHOR Dieter Koch .COMPANYNAME .COPYRIGHT (c) 2021-2023 Dieter Koch .TAGS .LICENSEURI https://github.com/admins-little-helper/ALH/blob/main/LICENSE .PROJECTURI https://github.com/admins-little-helper/ALH .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES 1.0.0 - Initial release 1.1.0 - Made script accept values for paramter ComputerName from pipeline. 1.2.0 - Reworked code. 1.3.0 - Added parameter 'Recurse'. #> <# .DESCRIPTION Contains a function to query the securtiy event log for event id 4740 which is logged in case a user account gets locked out. #> function Get-ALHADOUPermission { <# .SYNOPSIS Retrieves permissions set on a specified Active Directory organizational unit or container. .DESCRIPTION The 'Get-ALHADOUPermission' function retrieves permissions set on a specified Active Directory organizational unit or container. .PARAMETER OrganizationalUnit One or more distinguished Names of Active Directory organizational units or containers for which to retrieve permissions. .PARAMETER IncludeContainer If specified, the query will include permissions for containers. Otherwise permissions are quried only for Organizational Units. .PARAMETER Recurse If specified, the query will include permissions for the specified OU string(s) and all child OUs (and containers if parameter 'IncludeContainer' was specified). .EXAMPLE Get-ALHADOUPermission Get permissions for all OUs in current domain. .EXAMPLE Get-ALHADOUPermission -OrganizationalUnit "OU=DepartmentX,DC=company,DC=tld" Get permissions for a specific OU in current domain. .EXAMPLE Get-ALHADOUPermission -OrganizationalUnit "OU=DepartmentX,DC=company,DC=tld" -Recurse Get permissions for a specific OU and all sub-OUs in current domain. .EXAMPLE Get-ALHADOUPermission -OrganizationalUnit "*" -IncludeContainer Get permissions for all OUs and containers in current domain. .INPUTS System.String .OUTPUTS System.DirectoryServices.ActiveDirectoryAccessRule .NOTES Author: Dieter Koch Email: diko@admins-little-helper.de .LINK https://github.com/admins-little-helper/ALH/blob/main/Help/Get-ALHADOUPermission.txt #> [OutputType([System.DirectoryServices.ActiveDirectoryAccessRule])] [CmdletBinding()] param ( [Parameter(ValueFromPipeline, HelpMessage = 'Enter one or more organizational unit DNs')] [ValidateNotNullOrEmpty()] [string[]] $OrganizationalUnit = @(, "*"), [switch] $IncludeContainer, [switch] $Recurse ) begin { # Define required modules for this function and check if these are available and loaded. $RequiredModules = "ActiveDirectory" foreach ($RequiredModule in $RequiredModules) { if (-not [bool](Get-Module -Name $RequiredModule)) { if (-not [bool](Get-Module -Name $RequiredModule -ListAvailable)) { Write-Warning -Message "Module $RequiredModule not found. Stopping function." break } Write-Verbose -Message "Importing $RequiredModule Module" Import-Module ActiveDirectory } } # Make sure the AD PSDrive is available. if (-not (Test-Path -Path "AD:")) { $null = New-PSDrive -Name "AD" -PSProvider ActiveDirectory -Root "//RootDSE/" -Scope Global } $SchemaGUIDList = @{} # Get the GUID of all object in the AD schema. $GetADObjectParamsSchemaIDGUID = @{ SearchBase = (Get-ADRootDSE).schemaNamingContext LDAPFilter = "(schemaIDGUID=*)" Properties = @("Name", "schemaIDGUID") } $SchemaIdGuids = Get-ADObject @GetADObjectParamsSchemaIDGUID # Add the schema GUIDs to the hashtable. foreach ($Guid in $SchemaIdGuids) { if (-not $SchemaGUIDList.ContainsKey([System.GUID]$Guid.schemaIDGUID)) { $SchemaGUIDList.add([System.GUID]$Guid.schemaIDGUID, $Guid.Name) } } # Get the GUID of all access rights. $GetADObjectParamsRightsGUID = @{ SearchBase = "CN=Extended-Rights,$((Get-ADRootDSE).configurationNamingContext)" LDAPFilter = "(objectClass=controlAccessRight)" Properties = @("Name", "rightsGUID") } $RightsGUIDs = Get-ADObject @GetADObjectParamsRightsGUID # Add the access rights GUIDs to the hashtable, if there is not already the same GUID in the list. foreach ($Guid in $RightsGUIDs) { if (-not $SchemaGUIDList.ContainsKey([System.GUID]$Guid.rightsGUID)) { $SchemaGUIDList.add([System.GUID]$Guid.rightsGUID, $Guid.Name) } } # Get all OUs and containers in the current AD domain. if ($IncludeContainer.IsPresent) { Write-Verbose -Message "Including containers in query." $AllOUs = Get-ADObject -Filter { objectClass -eq 'organizationalUnit' -or objectClass -eq 'Container' } } else { Write-Warning -Message "Ignoring containers in query. Use parameter '-IncludeContainer' to include them in the results." $AllOUs = Get-ADObject -Filter { objectClass -eq 'organizationalUnit' } } } process { if ( $OrganizationalUnit -eq "*" ) { Write-Verbose -Message "Getting all OUs in current domain..." $OUsToProcess = $AllOUs } else { Write-Verbose -Message "Checking if specfied OU(s) exist in current domain..." $OUsToProcess = foreach ($OUString in $OrganizationalUnit) { if ($AllOUs.DistinguishedName -contains $OUString) { if ($Recurse.IsPresent) { # return the OU objects where the DN ends with the specified OU string. $AllOUs.where({ $_.DistinguishedName -like "*$OUString" }) } else { # return the OU object where the DN is exactle the specified OU string. $AllOUs.where({ $_.DistinguishedName -eq $OUString }) } } else { Write-Warning -Message "No OU or container found with DistinguishedName [$OUString]." } } } if ($null -ne $OUsToProcess) { Write-Verbose -Message "Getting OU permissions..." foreach ($OU in $OUsToProcess) { Write-Verbose -Message "Getting permissions for OU [$($OU.DistinguishedName)]." $OUACL = Get-Acl -Path "AD:\$($OU.DistinguishedName)" $AccessEntries = $OUACL.Access foreach ($AccessEntry in $AccessEntries) { # Add properties. $AccessEntry | Add-Member -Name "organizationalUnit" -MemberType NoteProperty -Value $null $AccessEntry | Add-Member -Name "objectTypeName" -MemberType NoteProperty -Value $null $AccessEntry | Add-Member -Name "inheritedObjectTypeName" -MemberType NoteProperty -Value $null # Add property values. $AccessEntry.organizationalUnit = $OU $AccessEntry.objectTypeName = $( if ($AccessEntry.objectType.ToString() -eq '00000000-0000-0000-0000-000000000000') { 'All' } else { $SchemaGUIDList.Item($AccessEntry.objectType) } ) $AccessEntry.inheritedObjectTypeName = $SchemaGUIDList.Item($AccessEntry.inheritedObjectType) # Return updated access object. $AccessEntry } } } } } #region EndOfScript <# ################################################################################ ################################################################################ # # ______ _ __ _____ _ _ # | ____| | | / _| / ____| (_) | | # | |__ _ __ __| | ___ | |_ | (___ ___ _ __ _ _ __ | |_ # | __| | '_ \ / _` | / _ \| _| \___ \ / __| '__| | '_ \| __| # | |____| | | | (_| | | (_) | | ____) | (__| | | | |_) | |_ # |______|_| |_|\__,_| \___/|_| |_____/ \___|_| |_| .__/ \__| # | | # |_| ################################################################################ ################################################################################ # created with help of http://patorjk.com/software/taag/ #> #endregion |