0

I've used a script to import ACLs into a csv from one system and have another script to read in the csv, create the folder structure and apply the permissions to a new system. Due to security restrictions, it's not possible for the systems to connect to each other, so robocopy is not an option.

The new folder structure is being created but the ACLs are not applying and I'm getting an error.

Here is a sample of the test csv:

FolderName,FolderPath,IdentityReference,FileSystemRights,InheritanceFlag
user1,DEEPP\Working\user1,AD\user1,Modify,"ContainerInherit, ObjectInherit"
user2,DEEPP\Working\user2,AD\user2,Modify,"ContainerInherit, ObjectInherit"

Here is the test script to read the csv and set the ACLs. Stepping through, I get no errors until the Set-ACL line at the bottom.

#Create folders and apply AD permissions
#Note: Remove drive letter in FolderPath column of csv file (ex, F:\); remove non-AD user rows

# Location Where your folders are to be created
$RootDir = "C:\Users\TR\Documents\Scripts\ACL"
Set-Location "$RootDir" 

# Import CSV file from location
$Folders = Import-Csv "$RootDir\ACLs_Proj-2023-01-25.csv"
$FolderPath = $Folder.FolderPath

# Create Folders from FolderPath column in csv; set ACL
ForEach ($Folder in $Folders) 
{ 

$a = Test-Path $RootDir\$FolderPath #{continue} #{Write-Verbose "Folder: $Path Already Exists"}
if ($a -eq $false) {
 
New-Item $FolderPath -type directory
}
        $IdentityReference = $Folder.IdentityReference
        $FileSystemRights = $Folder.FileSystemRights
        $InheritanceFlag = "ContainerInherit"
        $PropagationFlag = "None"
        $AccessControlType = "Allow"

#New-Object System.Security.AccessControl.FileSystemAccessRule('IdentityReference','FileSystemRights','InheritanceFlags','PropagationFlags','AccessControlType')
$New_ACL = New-Object Security.AccessControl.FileSystemAccessRule $IdentityReference, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType
Set-Acl -Path "$RootDir\$FolderPath" -AclObject $New_ACL -WhatIf
}

Error from the Set-ACL line:

Set-Acl : AclObject
At line:1 char:1
+ Set-Acl -Path "$RootDir\$FolderPath" -AclObject $New_ACL -WhatIf
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (System.Security...ystemAccessRule:FileSystemAccessRule) [Set-Acl], ArgumentException
    + FullyQualifiedErrorId : SetAcl_AclObject,Microsoft.PowerShell.Commands.SetAclCommand

If I type $New_ACL by itself, I get MOSTLY the expected output for a single entry:

FileSystemRights  : Modify, Synchronize
AccessControlType : Allow
IdentityReference : AD\user2
IsInherited       : False
InheritanceFlags  : ContainerInherit
PropagationFlags  : None

The "mostly" is because, as seen in the csv example, "Synchronize" is not in the FileSystemRights column of my csv file. Typing only $FileSystemRights gives me only the Modify value as expected.

Is the Synchronize entry confusing my poor script, or did I screw up something different? If it's the synchronize, how do I get rid of it? My understanding is that it would be applied by default if not listed.

Thanks!

tr_cpc1
  • 1
  • 2
  • Remove the double quotes (-Path "$RootDir\$FolderPath"). Cmdlet is not substituting the variables. Should be : -Path ($RootDir + "\" + $FolderPath) – jdweng Jan 27 '23 at 22:22
  • Thanks, jdweng. Unfortunately, that didn't change the output and it still gave me the error. – tr_cpc1 Jan 30 '23 at 19:16
  • jdweng, my bad. Your suggestion did fix the missing variable problem. I just hadn't applied it everywhere I needed to. – tr_cpc1 Jan 30 '23 at 20:43
  • In a command argument, `"$RootDir\$FolderPath"` is _equivalent_ to `($RootDir + "\" + $FolderPath)` (assuming both variables are _strings_, as is the case here) - your comment is an unhelpful distraction. If you wanted to make the point that you cannot use _property-access expressions_ inside `"..."` (e.g. `"...\$FolderPath.SomeProperty"`), that would require framing your point fundamentally differently. – mklement0 Mar 11 '23 at 22:35

2 Answers2

1

Ah, ok, so you're exporting a list of Access Control Rules (ACR), and then trying to apply a single rule as an Access Control List. You need a list of rules, not a single rule. Usually what you would do is get the current list of rules, modify it (add more rules or remove unwanted rules), then apply the modified list back to the object.

You obviously know how to get the ACL if you exported it, but I'll include it here. This gives an example of getting the ACL, adding your rule to it, and then applying the updated ACL back to the folder.

# Define the access rule(s) to add to the ACL
$New_ACR = New-Object Security.AccessControl.FileSystemAccessRule $IdentityReference, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType
# Get Access Control List from directory
$ACL = Get-Acl -Path "$RootDir\$FolderPath"
# Add new rule to ACL
$ACL.AddAccessRule($New_ACR)
# Apply updated ACL to directory
Set-Acl -Path "$RootDir\$FolderPath" -AclObject $ACL -WhatIf
TheMadTechnician
  • 34,906
  • 3
  • 42
  • 56
  • Thanks, MadTech. That info is very helpful. The good news is that the error went away and permissions were applied. The bad news is that it's only creating the folder structure for the last record in the csv and applying all the permissions for all of the users in the other records to that one folder, so I have to figure out where my logic is going wacky. I'll post back with progress. – tr_cpc1 Jan 30 '23 at 19:21
  • The jdweng suggestion above fixed the problem. – tr_cpc1 Mar 10 '23 at 15:43
  • @tr_cpc1, jdweng's suggestion was misleading - see my comment on your question and [this post](https://stackoverflow.com/questions/1145704/how-can-you-use-an-objects-property-in-a-double-quoted-string). – mklement0 Mar 11 '23 at 23:08
0

OK, the combination of jdweng and MadTech's suggestions fixed the problem. The working test script:

#Create folders and apply AD permissions
#Note: Remove drive letter in FolderPath column of csv file (ex, F:\); remove non-AD user rows

# Location Where your folders are to be created $RootDir = "C:\Users\TR\Documents\Scripts\ACL" Set-Location "$RootDir" 

# Import CSV file from location $Folders = Import-Csv "$RootDir\ACLs_Proj-2023-01-25.csv" $FolderPath = $Folder.FolderPath

# Create Folders from FolderPath column in csv; set ACL ForEach ($Folder in $Folders)  {  if(Test-Path $RootDir\$Folder.FolderPath) {continue} #{Write-Verbose "Folder: $Path Already Exists"} else{   New-Item $Folder.FolderPath -type directory }

        $IdentityReference = $Folder.IdentityReference
        $FileSystemRights = $Folder.FileSystemRights
        $InheritanceFlag = "ContainerInherit"
        $PropagationFlag = "None"
        $AccessControlType = "Allow"

#From stackoverflow response;
# Define the access rule(s) to add to the ACL $New_ACR = New-Object Security.AccessControl.FileSystemAccessRule $IdentityReference, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType
# Get Access Control List from directory $ACL = Get-Acl -Path ($RootDir + "\" + $Folder.FolderPath)
# Add new rule to ACL $ACL.AddAccessRule($New_ACR)
# Apply updated ACL to directory Set-Acl -Path ($RootDir + "\" + $Folder.FolderPath) -AclObject $ACL }

Thanks!

tr_cpc1
  • 1
  • 2