# Set-acl on resource cross trusted forest

**URL:** <https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911>\
**Category:** PowerShell Help\
**Created:** [September 25, 2013, 2:48am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911 "2013-09-25T02:48:53Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![jason-mcmahan](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@jason-mcmahan](https://forums.powershell.org/u/jason-mcmahan)\
**Post date:** [September 25, 2013, 2:48am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/1 "2013-09-25T02:48:53Z")

</div>

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)}

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

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

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

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

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

$ftpFolder

#endregion

###########################################

If i perform

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

It returns

FileSystemRights : FullControl  
AccessControlType: Allow  
IdentityReference:BUILTIN\Administrators  
IsInherited:False  
InheritanceFlags: ContainerInherit,ObjectInherit  
PropagationFlags:None

FileSystemRights: ReadAndExecute, Synchronize  
AccessControlType:Allow  
IdentityReference:S-1-5-11-1111111111-1111111111-1111111111-1111  
IsInherited:False  
InheritanceFlags:ContainerInherit  
PropagationFlags: None

If i would like to add the rule i get error

$aclFtpRoot.AddAccessRule($rule3)

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

At line:1 char:1

- $aclFtpRoot.AddAccessRule($rule3)

- 

```auto

```

- CategoryInfo : NotSpecified: (🙂 , MethodInvocationException

- FullyQualifiedErrorId : IdentityNotMappedException

Thank you

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/1X/385e4f9fe133561ad30a814262fe0e0ae6bc3ef0.png) [@system](https://forums.powershell.org/u/system)\
**Post date:** [September 25, 2013, 3:10am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/2 "2013-09-25T03:10:06Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![jason-mcmahan](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@jason-mcmahan](https://forums.powershell.org/u/jason-mcmahan)\
**Post date:** [September 25, 2013, 5:02am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/3 "2013-09-25T05:02:17Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/1X/385e4f9fe133561ad30a814262fe0e0ae6bc3ef0.png) [@system](https://forums.powershell.org/u/system)\
**Post date:** [September 25, 2013, 5:07am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/4 "2013-09-25T05:07:36Z")

</div>

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 [http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemaccessrule.filesystemaccessrule.aspx](http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemaccessrule.filesystemaccessrule.aspx)). 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.

---

<div class="post-metadata">

**Author:** ![jason-mcmahan](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@jason-mcmahan](https://forums.powershell.org/u/jason-mcmahan)\
**Post date:** [September 25, 2013, 5:46am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/5 "2013-09-25T05:46:35Z")

</div>

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”)  
$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)
- 

```auto
  + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
  + FullyQualifiedErrorId : SystemException

```

When i show getType  
IsPublic IsSerial Name BaseType

* * *

True True String System.Object

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/1X/385e4f9fe133561ad30a814262fe0e0ae6bc3ef0.png) [@system](https://forums.powershell.org/u/system)\
**Post date:** [September 25, 2013, 6:08am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/6 "2013-09-25T06:08:23Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![jason-mcmahan](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@jason-mcmahan](https://forums.powershell.org/u/jason-mcmahan)\
**Post date:** [September 25, 2013, 7:00am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/7 "2013-09-25T07:00:26Z")

</div>

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)
- 

```auto
  + 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.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/1X/385e4f9fe133561ad30a814262fe0e0ae6bc3ef0.png) [@system](https://forums.powershell.org/u/system)\
**Post date:** [September 25, 2013, 12:33pm UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/8 "2013-09-25T12:33:03Z")

</div>

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'
$account.Translate([System.Security.Principal.SecurityIdentifier])
```

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 http://www.pinvoke.net/default.aspx/advapi32.LookupAccountName

function Get-Sid
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [System.String]
        $Account,

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

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

        public enum SID_NAME_USE 
        {
            SidTypeUser = 1,
            SidTypeGroup,
            SidTypeDomain,
            SidTypeAlias,
            SidTypeWellKnownGroup,
            SidTypeDeletedAccount,
            SidTypeInvalid,
            SidTypeUnknown,
            SidTypeComputer
        }
    
        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
    $ERROR_INSUFFICIENT_BUFFER = 122
    $ERROR_INVALID_FLAGS = 1004

    $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()
            }
        }
    }
    else
    {
        $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
    }
    else
    {
        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.

---

<div class="post-metadata">

**Author:** ![jason-mcmahan](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@jason-mcmahan](https://forums.powershell.org/u/jason-mcmahan)\
**Post date:** [September 25, 2013, 11:18pm UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/9 "2013-09-25T23:18:27Z")

</div>

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])
- 

```auto
  + 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

---

<div class="post-metadata">

**Author:** ![jason-mcmahan](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@jason-mcmahan](https://forums.powershell.org/u/jason-mcmahan)\
**Post date:** [October 7, 2013, 12:27am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/10 "2013-10-07T00:27:11Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/1X/385e4f9fe133561ad30a814262fe0e0ae6bc3ef0.png) [@system](https://forums.powershell.org/u/system)\
**Post date:** [October 7, 2013, 2:01am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/11 "2013-10-07T02:01:26Z")

</div>

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")
$aclFtpRoot.AddAccessRule($rule3)

# Try this:

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

---

<div class="post-metadata">

**Author:** ![jason-mcmahan](https://avatars.discourse-cdn.com/v4/letter/j/b487fb/32.png) [@jason-mcmahan](https://forums.powershell.org/u/jason-mcmahan)\
**Post date:** [November 4, 2013, 4:39am UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/12 "2013-11-04T04:39:41Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [May 16, 2024, 8:57pm UTC](https://forums.powershell.org/t/set-acl-on-resource-cross-trusted-forest/1911/13 "2024-05-16T20:57:50Z")

</div>


