internal/functions/Convert-Principal.ps1

function Convert-Principal {
    <#
    .SYNOPSIS
        Converts a principal to either SID or NTAccount format.
     
    .DESCRIPTION
        Converts a principal to either SID or NTAccount format.
        It caches all resolutions, uses Convert-BuiltInToSID to resolve default builtin account names,
        uses Get-Domain to resolve foreign domain SIDs and names.
 
        Basically, it is a best effort attempt to resolve principals in a useful manner.
     
    .PARAMETER Name
        The name of the entity to convert.
     
    .PARAMETER OutputType
        Whether to return an NTAccount or SID.
        Defaults to SID
     
    .PARAMETER Server
        The server / domain to work with.
     
    .PARAMETER Credential
        The credentials to use for this operation.
     
    .EXAMPLE
        PS C:\> Convert-Principal @parameters -Name contoso\administrator
 
        Tries to convert the user contoso\administrator into a SID
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]
        $Name,

        [ValidateSet('SID','NTAccount')]
        [string]
        $OutputType = 'SID',

        [PSFComputer]
        $Server,
        
        [PSCredential]
        $Credential
    )
    
    begin {
        $parameters = $PSBoundParameters | ConvertTo-PSFHashtable -Include Server, Credential
    }
    process {
        Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing' -StringValues $Name
        
        # Terminate if already cached
        if ($OutputType -eq 'SID' -and $script:cache_PrincipalToSID[$Name]) { return $script:cache_PrincipalToSID[$Name] }
        if ($OutputType -eq 'NTAccount' -and $script:cache_PrincipalToNT[$Name]) { return $script:cache_PrincipalToNT[$Name] }

        $builtInIdentity = Convert-BuiltInToSID -Identity $Name
        if ($builtInIdentity -ne $Name) { return $builtInIdentity }

        #region Processing Input SID
        if ($Name -as [System.Security.Principal.SecurityIdentifier]) {
            Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing.InputSID' -StringValues $Name
            if ($OutputType -eq 'SID') {
                $script:cache_PrincipalToSID[$Name] = $Name -as [System.Security.Principal.SecurityIdentifier]
                return $script:cache_PrincipalToSID[$Name]
            }

            $script:cache_PrincipalToNT[$Name] = Get-Principal @parameters -Sid $Name -Domain $Name -OutputType NTAccount
            return $script:cache_PrincipalToNT[$Name]
        }
        #endregion Processing Input SID
        
        Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing.InputNT' -StringValues $Name
        $ntAccount = $Name -as [System.Security.Principal.NTAccount]
        if ($OutputType -eq 'NTAccount') {
            $script:cache_PrincipalToNT[$Name] = $ntAccount
            return $script:cache_PrincipalToNT[$Name]
        }

        try {
            $script:cache_PrincipalToSID[$Name] = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier])
            return $script:cache_PrincipalToSID[$Name]
        }
        catch {
            $domainPart, $namePart = $ntAccount.Value.Split("\", 2)
            $domain = Get-Domain @parameters -DnsName $domainPart
            Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing.NTDetails' -StringValues $domainPart, $namePart

            $param = @{
                Server = $domain.DNSRoot
            }
            $cred = Get-DMDomainCredential -Domain $domain.DNSRoot
            if ($cred) { $param['Credential'] = $cred }
            Write-PSFMessage -Level Debug -String 'Convert-Principal.Processing.NT.LdapFilter' -StringValues "(samAccountName=$namePart)"
            $adObject = Get-ADObject @param -LDAPFilter "(samAccountName=$namePart)" -Properties ObjectSID
            $script:cache_PrincipalToSID[$Name] = $adObject.ObjectSID
            $adObject.ObjectSID
        }
    }
}