function Get-PrivPermission { <# .SYNOPSIS Retrieves permissions for a specified Group Policy Object (GPO) based on various criteria. .DESCRIPTION This function retrieves permissions for a specified Group Policy Object (GPO) based on the provided parameters. It allows filtering by principal, permission type, and other criteria. .PARAMETER GPO Specifies the Group Policy Object (GPO) for which permissions will be retrieved. .PARAMETER SecurityRights Specifies the security rights to be evaluated for the GPO. .PARAMETER Principal Specifies the principal for which permissions will be retrieved. .PARAMETER PrincipalType Specifies the type of principal to filter by. Valid values are 'DistinguishedName', 'Name', 'NetbiosName', or 'Sid'. .PARAMETER SkipWellKnown Skips well-known principals when evaluating permissions. .PARAMETER SkipAdministrative Skips administrative principals when evaluating permissions. .PARAMETER IncludeOwner Includes the owner of the GPO in the permission results. .PARAMETER IncludePermissionType Specifies the permission types to include in the results. .PARAMETER ExcludePermissionType Specifies the permission types to exclude from the results. .PARAMETER PermitType Specifies the type of permissions to include. Valid values are 'Allow', 'Deny', or 'All'. .PARAMETER ExcludePrincipal Specifies principals to exclude from the results. .PARAMETER ExcludePrincipalType Specifies the type of principal to exclude. Valid values are 'DistinguishedName', 'Name', or 'Sid'. .PARAMETER IncludeGPOObject Includes the GPO object in the permission results. .PARAMETER ADAdministrativeGroups Specifies the Active Directory administrative groups to consider. .PARAMETER Type Specifies the type of principals to include. Valid values are 'AuthenticatedUsers', 'DomainComputers', 'Unknown', 'WellKnownAdministrative', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'Administrative', or 'All'. .PARAMETER ExtendedForestInformation Specifies extended forest information to be used in evaluation. .EXAMPLE Get-PrivPermission -GPO $GPO -SecurityRights $SecurityRights -Principal 'Domain Admins' -PrincipalType 'Name' -PermitType 'Allow' Retrieves permissions for the specified GPO where 'Domain Admins' have 'Allow' permissions. .EXAMPLE Get-PrivPermission -GPO $GPO -SecurityRights $SecurityRights -Principal 'S-1-5-21-3623811015-3361044348-30300820-1013' -PrincipalType 'Sid' -PermitType 'Deny' Retrieves permissions for the specified GPO where the principal with the SID 'S-1-5-21-3623811015-3361044348-30300820-1013' has 'Deny' permissions. #> [cmdletBinding()] param( [Microsoft.GroupPolicy.Gpo] $GPO, [Object] $SecurityRights, [string[]] $Principal, [validateset('DistinguishedName', 'Name', 'NetbiosName', 'Sid')][string] $PrincipalType = 'Sid', [switch] $SkipWellKnown, [switch] $SkipAdministrative, [switch] $IncludeOwner, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, [validateSet('Allow', 'Deny', 'All')][string] $PermitType = 'All', [string[]] $ExcludePrincipal, [validateset('DistinguishedName', 'Name', 'Sid')][string] $ExcludePrincipalType = 'Sid', [switch] $IncludeGPOObject, [System.Collections.IDictionary] $ADAdministrativeGroups, [validateSet('AuthenticatedUsers', 'DomainComputers', 'Unknown', 'WellKnownAdministrative', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'Administrative', 'All')][string[]] $Type = 'All', #[System.Collections.IDictionary] $Accounts, [System.Collections.IDictionary] $ExtendedForestInformation ) Begin { Write-Verbose "Get-PrivPermission - Processing $($GPO.DisplayName) from $($GPO.DomainName)" } Process { $SecurityRights | ForEach-Object -Process { $GPOPermission = $_ if ($PermitType -ne 'All') { if ($PermitType -eq 'Deny') { if ($GPOPermission.Denied -eq $false) { return } } else { if ($GPOPermission.Denied -eq $true) { return } } } if ($ExcludePermissionType -contains $GPOPermission.Permission) { return } if ($IncludePermissionType) { if ($IncludePermissionType -notcontains $GPOPermission.Permission) { if ($IncludePermissionType -eq 'GpoRead' -and $GPOPermission.Permission -eq 'GpoApply') { # We treat GpoApply as GpoRead as well. This is because when GpoApply is set it becomes GpoRead as well but of course not vice versa } else { return } } } if ($SkipWellKnown.IsPresent -or $Type -contains 'NotWellKnown') { if ($GPOPermission.Trustee.SidType -eq 'WellKnownGroup') { return } } if ($SkipAdministrative.IsPresent -or $Type -contains 'NotAdministrative') { $IsAdministrative = $ADAdministrativeGroups['BySID'][$GPOPermission.Trustee.Sid.Value] if ($IsAdministrative) { return } } if ($Type -contains 'Administrative' -and $Type -notcontains 'All') { $IsAdministrative = $ADAdministrativeGroups['BySID'][$GPOPermission.Trustee.Sid.Value] if (-not $IsAdministrative) { return } } if ($Type -contains 'NotWellKnownAdministrative' -and $Type -notcontains 'All') { # We check for SYSTEM account # Maybe we should make it a function and provide more if ($GPOPermission.Trustee.Sid -eq 'S-1-5-18') { return } } if ($Type -contains 'WellKnownAdministrative' -and $Type -notcontains 'All') { # We check for SYSTEM account # Maybe we should make it a function and provide more if ($GPOPermission.Trustee.Sid -ne 'S-1-5-18') { return } } if ($Type -contains 'Unknown' -and $Type -notcontains 'All') { # May need updates if there's more types if ($GPOPermission.Trustee.SidType -ne 'Unknown') { return } } if ($Type -contains 'AuthenticatedUsers' -and $Type -notcontains 'All') { if ($GPOPermission.Trustee.Sid -ne 'S-1-5-11') { return } } if ($Type -contains 'DomainComputers' -and $Type -notcontains 'All') { $DomainComputersSID = -join ($ExtendedForestInformation['DomainsExtended'][$GPO.DomainName].DomainSID, '-515') if ($GPOPermission.Trustee.Sid -ne $DomainComputersSID) { return } } if ($GPOPermission.Trustee.Domain) { $UserMerge = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name) } else { $UserMerge = $null } if ($Principal) { if ($PrincipalType -eq 'Sid') { if ($Principal -notcontains $GPOPermission.Trustee.Sid.Value) { return } } elseif ($PrincipalType -eq 'DistinguishedName') { if ($Principal -notcontains $GPOPermission.Trustee.DSPath) { return } } elseif ($PrincipalType -eq 'Name') { if ($Principal -notcontains $GPOPermission.Trustee.Name) { return } } elseif ($PrincipalType -eq 'NetbiosName') { if ($Principal -notcontains $UserMerge) { return } } } if ($ExcludePrincipal) { if ($ExcludePrincipalType -eq 'Sid') { if ($ExcludePrincipal -contains $GPOPermission.Trustee.Sid.Value) { return } } elseif ($ExcludePrincipalType -eq 'DistinguishedName') { if ($ExcludePrincipal -contains $GPOPermission.Trustee.DSPath) { return } } elseif ($ExcludePrincipalType -eq 'Name') { if ($ExcludePrincipal -contains $GPOPermission.Trustee.Name) { return } } elseif ($ExcludePrincipalType -eq 'NetbiosName') { if ($ExcludePrincipal -contains $UserMerge) { return } } } <# # Sets permissions name, domain, distinguishedname to proper values if ($GPOPermission.Trustee.Name) { $DomainPlusName = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name) if ($GPOPermission.Trustee.DSPath) { $NetbiosConversion = ConvertFrom-NetbiosName -Identity $DomainPlusName if ($NetbiosConversion.DomainName) { $UserNameDomain = $NetbiosConversion.DomainName $UserName = $NetbiosConversion.Name } } else { $UserNameDomain = '' $Username = $DomainPlusName } } else { $DomainPlusName = '' $UserNameDomain = '' $Username = '' } #> # I don't trust the returned data, some stuff like 'alias' shows up for groups. To unify it with everything else... using my own function $PermissionAccount = Get-WinADObject -Identity $GPOPermission.Trustee.Sid.Value -AddType -Cache -Verbose:$false if ($PermissionAccount) { $UserNameDomain = $PermissionAccount.DomainName $UserName = $PermissionAccount.Name $SidType = $PermissionAccount.Type $ObjectClass = $PermissionAccount.ObjectClass } else { $ConvertFromSID = ConvertFrom-SID -SID $GPOPermission.Trustee.Sid.Value $UserNameDomain = '' $Username = $ConvertFromSID.Name $SidType = $ConvertFromSID.Type if ($SidType -eq 'Unknown') { $ObjectClass = 'unknown' } else { $ObjectClass = 'foreignSecurityPrincipal' } } $ReturnObject = [ordered] @{ DisplayName = $GPO.DisplayName # : ALL | Enable RDP GUID = $GPO.ID DomainName = $GPO.DomainName # : ad.evotec.xyz Enabled = $GPO.GpoStatus Description = $GPO.Description CreationDate = $GPO.CreationTime ModificationTime = $GPO.ModificationTime PermissionType = if ($GPOPermission.Denied -eq $true) { 'Deny' } else { 'Allow' } Permission = $GPOPermission.Permission # : GpoEditDeleteModifySecurity Inherited = $GPOPermission.Inherited # : False PrincipalNetBiosName = $UserMerge PrincipalDistinguishedName = $GPOPermission.Trustee.DSPath #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz PrincipalDomainName = $UserNameDomain #: EVOTEC PrincipalName = $UserName #: Domain Admins PrincipalSid = $GPOPermission.Trustee.Sid.Value #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 PrincipalSidType = $SidType #$GPOPermission.Trustee.SidType #: Group PrincipalObjectClass = $ObjectClass } if ($IncludeGPOObject) { $ReturnObject['GPOObject'] = $GPO $ReturnObject['GPOSecurity'] = $SecurityRights $ReturnObject['GPOSecurityPermissionItem'] = $GPOPermission } [PSCustomObject] $ReturnObject } if ($IncludeOwner) { if ($GPO.Owner) { # I don't trust the returned data, some stuff like 'alias' shows up for groups. To unify it with everything else... using my own function $OwnerAccount = Get-WinADObject -Identity $GPO.Owner -AddType -Cache -Verbose:$false if ($OwnerAccount) { $UserNameDomain = $OwnerAccount.DomainName $UserName = $OwnerAccount.Name $SidType = $OwnerAccount.Type $OwnerObjectClass = $OwnerAccount.ObjectClass $SID = $OwnerAccount.ObjectSID } else { $ConvertFromSID = ConvertFrom-SID -SID $GPO.Owner $UserNameDomain = '' $Username = $ConvertFromSID.Name $SidType = $ConvertFromSID.Type if ($SidType -eq 'Unknown') { $OwnerObjectClass = 'unknown' } else { $OwnerObjectClass = 'foreignSecurityPrincipal' } $SID = $ConvertFromSID.SID } } else { $UserName = '' $UserNameDomain = '' $SID = '' $SIDType = 'Unknown' $DistinguishedName = '' $OwnerObjectClass = 'unknown' } # We have to process it for owners after querying user because $Owners are not as established as standard permissions so we don't know a lot if ($Type -contains 'Administrative' -and $Type -notcontains 'All') { if ($SID) { $IsAdministrative = $ADAdministrativeGroups['BySID'][$SID] if (-not $IsAdministrative) { return } } else { # if there is no SID, it's not administrative return } } if ($Type -contains 'NotWellKnownAdministrative' -and $Type -notcontains 'All') { # We check for SYSTEM account # Maybe we should make it a function and provide more if ($SID -eq 'S-1-5-18') { return } } if ($Type -contains 'WellKnownAdministrative' -and $Type -notcontains 'All') { # We check for SYSTEM account # Maybe we should make it a function and provide more if ($SID -ne 'S-1-5-18') { return } } if ($Type -contains 'Unknown' -and $Type -notcontains 'All') { # May need updates if there's more types if ($SidType -ne 'Unknown') { return } } if ($Type -contains 'AuthenticatedUsers' -and $Type -notcontains 'All') { if ($SID -ne 'S-1-5-11') { return } } if ($Type -contains 'DomainComputers' -and $Type -notcontains 'All') { $DomainComputersSID = -join ($ExtendedForestInformation['DomainsExtended'][$GPO.DomainName].DomainSID, '-515') if ($SID -ne $DomainComputersSID) { return } } if ($Principal) { if ($PrincipalType -eq 'Sid') { if ($Principal -notcontains $SID) { return } } elseif ($PrincipalType -eq 'DistinguishedName') { if ($Principal -notcontains $DistinguishedName) { return } } elseif ($PrincipalType -eq 'Name') { if ($Principal -notcontains $UserName) { return } } elseif ($PrincipalType -eq 'NetbiosName') { if ($Principal -notcontains $GPO.Owner) { return } } } if ($ExcludePrincipal) { if ($ExcludePrincipalType -eq 'Sid') { if ($ExcludePrincipal -contains $SID) { return } } elseif ($ExcludePrincipalType -eq 'DistinguishedName') { if ($ExcludePrincipal -contains $DistinguishedName) { return } } elseif ($ExcludePrincipalType -eq 'Name') { if ($ExcludePrincipal -contains $UserName) { return } } elseif ($ExcludePrincipalType -eq 'NetbiosName') { if ($ExcludePrincipal -contains $GPO.Owner) { return } } } $ReturnObject = [ordered] @{ DisplayName = $GPO.DisplayName # : ALL | Enable RDP GUID = $GPO.Id DomainName = $GPO.DomainName # : ad.evotec.xyz Enabled = $GPO.GpoStatus Description = $GPO.Description CreationDate = $GPO.CreationTime ModificationTime = $GPO.ModificationTime PermissionType = 'Allow' Permission = 'GpoOwner' # : GpoEditDeleteModifySecurity Inherited = $false # : False PrincipalNetBiosName = $GPO.Owner PrincipalDistinguishedName = $DistinguishedName #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz PrincipalDomainName = $UserNameDomain PrincipalName = $UserName PrincipalSid = $SID #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 PrincipalSidType = $SIDType # #: Group PrincipalObjectClass = $OwnerObjectClass } if ($IncludeGPOObject) { $ReturnObject['GPOObject'] = $GPO $ReturnObject['GPOSecurity'] = $SecurityRights $ReturnObject['GPOSecurityPermissionItem'] = $null } [PSCustomObject] $ReturnObject } } End { } }