Set-acl on resource cross trusted forest

I have a script to create folders in a trusted domain, the script will create the folders properly and get-acl information for the folders however i am unable to change the ace/alc

When i get-acl it returns the sids instead of the friendly names for the groups.

I am running the script from Forest A attempting to get/set-acl on resources in Forest B

What is have so far is


#region Apply Access Controls to $ftpFolder
$aclFtpRoot = {Get-Acl -Path $($ftpFolder)}

($aclFtpRoot.AreAccessRulesProtected) { $aclFtpRoot.Access | % {$aclFtpRoot.purgeaccessrules($_.IdentityReference)} }

$isProtected = $true
$preserveInheritance = $false
$aclFtpRoot.SetAccessRuleProtection($isProtected, $preserveInheritance)}

$rule1 = New-Object System.Security.AccessControl.FileSystemAccessRule(“BUILTIN\Administrators”,“FullControl”,“ContainerInherit,ObjectInherit”,“None”,“Allow”)
Set-Acl -aclobject $aclFtpRoot -Path $ftpFolder

$rule2 = New-Object System.Security.AccessControl.FileSystemAccessRule($filerDRwGroup,“FullControl”,“ContainerInherit,ObjectInherit”,“None”,“Allow”)
Set-Acl -aclobject $aclFtpRoot -Path $ftpFolder

$rule3 = New-Object System.Security.AccessControl.FileSystemAccessRule($divisionListGroup,“ListDirectory”,“None”,“None”,“Allow”)
Set-Acl -aclobject $aclFtpRoot -Path




If i perform

$ftpfolder = ‘\Filer\’
$aclFtpRoot = Get-Acl -Path $ftpFolder
$aclFtpRoot | Select-Object -ExpandProperty access

It returns

FileSystemRights : FullControl
AccessControlType: Allow
InheritanceFlags: ContainerInherit,ObjectInherit

FileSystemRights: ReadAndExecute, Synchronize
PropagationFlags: None

If i would like to add the rule i get error


Exception calling “AddAccessRule” with “1” argument(s): “Some or all identity references could not be translated.”

At line:1 char:1

  • $aclFtpRoot.AddAccessRule($rule3)

  • CategoryInfo : NotSpecified: (:slight_smile: , MethodInvocationException

  • FullyQualifiedErrorId : IdentityNotMappedException

Thank you

What are the contents of your $divisionListGroup variable? Make sure that it’s a DOMAIN\GroupName format string (or [System.Security.Principal.NTAccount] object), and that the group actually exists; no typos in the name, etc.

If, for some reason, the .NET IdentityReference classes aren’t translating names to SIDs across these forest trusts properly, it’s always possible to code around them (either using the underlying Win32 API functions to translate names to SIDs, or fetching the SIDs with ADSI, etc.) However you accomplish it, all you should need to do is pass a [System.Security.Principal.SecurityIdentifier] object to the FileSystemAccessRule constructor in place of your current String or [System.Security.Principal.NTAccount] object.

The variable is IsPublic IsSerial Name BaseType

True False ADGroup Microsoft.ActiveDirectory.Management.ADPrincipal
It is the same group that appears with only the SID. I added the group to the resource (manually) and gave it read access to test this portion of the script.
It is aggravating because i am able to open explorer with my administrator creds then perform this one small portion of the script is stopping the entire thing.

Oh. There’s no constructor for FileSystemAccessRule that would accept an ADPrincipal object; it either needs a subclass of IdentityReference (NTAccount or SecurityIdentifier), or a string (see PowerShell is probably casting your ADPrincipal object to a string, to make it fit one of these constructors, but that string value might not quite match what the FileSystemAccessRule expects.

Try running ([string]$divisionListGroup) and ($divisionListGroup.ToString()), and see what the output is.

Instead of that i removed the variable and input domain\groupname to try to simplify it.
I attempted
New-Object System.Security.AccessControl.FileSystemAccessRule(“Domain\Groupname”,“ListDirectory”,“None”,“None”,“Allow”)
Exception calling “AddAccessRule” with “1” argument(s): "The trust relationship between the primary domain and the trusted domain failed.
At line:1 char:1

  • $aclFtpRoot.AddAccessRule($rule3)
  •   + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
      + FullyQualifiedErrorId : SystemException

When i show getType
IsPublic IsSerial Name BaseType

True True String System.Object

Presumably that means you either really have a problem with your trust relationship (which I doubt, or you’d have known about it already), or we’re back to my original statement, that you might need to work around a .NET Framework limitation here, if it’s not behaving well.

I’d test this myself, but I don’t have a multi-forest test environment set up at the moment. If I have time later, I’ll build a new domain controller VM and see if I get the same results.

THank you, just Fyi
for giggles i ran the following command from my elevated powershell console in forest A
PS C:\Sysutil\bin> $rule3 = New-Object System.Security.AccessControl.FileSystemAccessRule(“domain\groupname”,“ListDirectory”,“None”,“None”,“Allow”)

PS C:\Sysutil\bin> $aclFtpRoot.AddAccessRule($rule3)
Exception calling “AddAccessRule” with “1” argument(s): "The trust relationship between the primary domain and the trusted domain failed.
At line:1 char:1

  • $aclFtpRoot.AddAccessRule($rule3)
  •   + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
      + FullyQualifiedErrorId : SystemException

Then i ran the exact same command from a server in forset B
PS C:\sysUtil\bin> $rule3 = New-Object System.Security.AccessControl.FileSystemAccessRule(“domain\groupname”,“ListDirectory”,“None”,“None”,“Allow”)

PS C:\sysUtil\bin> $aclFtpRoot.AddAccessRule($rule3)

PS C:\sysUtil\bin> Set-Acl -aclobject $aclFtpRoot -Path $ftpFolder1
It added the rule and set perms as it should have.
The only thing that sticks out for me is in forest A the get-acl returns SID of list group
When run get-acl in forest B it returns friendly name domain\groupname

Thank you very much for any help.

I’m not sure how soon I’ll have a second AD forest set up for my own testing, but in the meantime, try this as an experiment:

$account = [System.Security.Principal.NTAccount]'DOMAIN\GroupName'

I expect this to fail; it’s basically doing exactly the same thing that AddAccessRule is doing behind the scenes.

Then try this, and see if it succeeds (or if it fails with a similar error message):

# Based on sample code at

function Get-Sid
    param (
        [Parameter(Mandatory = $true, Position = 0)]

        [Parameter(Mandatory = $false, Position = 1)]
        $Domain = $null

    Add-Type -TypeDefinition @'
        using System;
        using System.Runtime.InteropServices;
        using System.Text;

        public enum SID_NAME_USE 
            SidTypeUser = 1,
        public class NativeMethods
            [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError = true)]
            public static extern bool LookupAccountName (
                string lpSystemName,
                string lpAccountName,
                [MarshalAs(UnmanagedType.LPArray)] byte[] Sid,
                ref uint cbSid,
                StringBuilder ReferencedDomainName,
                ref uint cchReferencedDomainName,
                out SID_NAME_USE peUse);

    $NO_ERROR = 0

    $sidBytes = $null
    $sidByteCount = 0
    $referencedDomainName = New-Object System.Text.StringBuilder
    $referencedDomainNameCharCount = [System.UInt32]$referencedDomainName.Capacity
    [SID_NAME_USE]$sidNameUse = [SID_NAME_USE]::SidTypeUnknown

    $errorCode = $NO_ERROR

    if (-not [NativeMethods]::LookupAccountName($Domain, $Account, $sidBytes, [ref]$sidByteCount, $referencedDomainName, [ref] $referencedDomainNameCharCount, [ref] $sidNameUse))
        $errorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
        if ($errorCode -eq $ERROR_INSUFFICIENT_BUFFER -or $errorCode -eq $ERROR_INVALID_FLAGS)
            $sidBytes = New-Object Byte[]($sidByteCount)
            $null = $referencedDomainName.EnsureCapacity([int]$referencedDomainNameCharCount)
            $errorCode = $NO_ERROR

            if (-not [NativeMethods]::LookupAccountName($Domain, $Account, $sidBytes, [ref]$sidByteCount, $referencedDomainName, [ref] $referencedDomainNameCharCount, [ref] $sidNameUse))
                $errorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
        $displayAccount = ""
        if (-not [string]::IsNullOrEmpty($Domain))
            $displayAccount += "$Domain\"

        $displayAccount += $Account

        throw "Account '$displayAccount' could not be translated to a SID."

    if ($errorCode -eq $NO_ERROR)
        $sid = New-Object System.Security.Principal.SecurityIdentifier($sidBytes,0)
        Write-Output $sid
        throw (New-Object System.ComponentModel.Win32Exception($errorCode))

Get-Sid -Domain 'DOMAIN' -Account 'GroupName'

This code uses the Win32 API; if anything’s going to work, it should work. If this does work, you can use it to get around the .NET problem. The SecurityIdentifier object returned by Get-Sid (unless it throws an exception) can be passed to the constructor of FileSystemAccessRule objects.

You were right,
PS C:\Sysutil\bin> $account = [System.Security.Principal.NTAccount]‘Domain\Groupname’

PS C:\Sysutil\bin> $account.Translate([System.Security.Principal.SecurityIdentifier])
Exception calling “Translate” with “1” argument(s): "The trust relationship between the primary domain and the trusted domain failed.
At line:1 char:1

  • $account.Translate([System.Security.Principal.SecurityIdentifier])
  •   + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
      + FullyQualifiedErrorId : SystemException

I then added the function and ran Get-sid which returned:
BinaryLength AccountDomainSid Value
------------ ---------------- -----
28 S-1-1-11-1111111111-1111111111-1111111111 S-1-1-11-1111111111-1111111111-1111111111-1111

Good morning Just wanted to follow up with this thread to see if there is any more info that may help.
Thank you very much for you time.

Sorry, I thought you said that the Get-Sid function I posted was working. I did build a second AD forest in my lab, but wasn’t able to reproduce the problem.

The intended use of the Get-Sid function is like this:

# Instead of this:

$rule3 = New-Object System.Security.AccessControl.FileSystemAccessRule("Domain\Groupname","ListDirectory","None","None","Allow")

# Try this:

    $sid = Get-Sid -Domain "Domain" -Account "Groupname"
    $rule3 = New-Object System.Security.AccessControl.FileSystemAccessRule($sid, "ListDirectory", "None", "None", "Allow")
    # If an error occurred, handle it however you like.
    Write-Error -ErrorRecord $_

I am sorry i did not respond sooner, Thank you for your help.
This was the correct method and i can set the rules as expected.
I really appreciate all the time and effort you gave on this issue.