This one is stumping me. I am trying to do this with PowerShell, but it does not have to be...
Basically, I have a text file containing ACLs information for a large directory structure that has been migrated (I realize there is much to be desired from the contents, but we no longer can access the original filesystem, so this is what we have to work with).
I need to generate a batch file to re-acl the new (copied) file system.
So in a nutshell, I need to convert text like this (sorry for the scroll, but I am trying to preserve the line spacing):
Path: \\Share.Domain.com\Directory01$\Subdirectory01
AccessToString : DOMAIN\Group01-Knuckleheads Allow ReadAndExecute, Synchronize
BUILTIN\Administrators
Path: \\Share.Domain.com\Directory02$\Subdirectory01
AccessToString : DOMAIN\Different-Group02 Allow FullControl
BUILTIN\Administrators Allow FullControl
Into new files (or the same files, doesn't matter really) with the content like this:
ICacls "\\Share.Domain.com\Directory01$\Subdirectory01" /Grant "DOMAIN\Group01-Knuckleheads":(OI)(CI)R,X,S /t /c /l /q /inheritance:r
ICacls "\\Share.Domain.com\Directory01$\Subdirectory01" /Grant "BUILTIN\Administrators":(OI)(CI)F /t /c /l /q /inheritance:r
ICacls "\\Share.Domain.com\Directory02$\Subdirectory01" /Grant "DOMAIN\Different-Group02":(OI)(CI)F /c /l /q /inheritance:r
ICacls "\\Share.Domain.com\Directory02$\Subdirectory01" /Grant "BUILTIN\Administrators":(OI)(CI)F /c /l /q /inheritance:r
My semi-pathetic attempt to work this out are still progressing, but I realize that this foe is greater than my mojo:
#$ACLs = Get-Content C:\Scripts\Test\AndTest.txt
#ForEach-Object ($ACL in $ACLs)
#{
#Figure out how to break strings into variables....
#}
#Declare Var - Need to populate from the imported text file
$FilePath = "\\Share.Domain.com\Directory01$\Subdirectory01"
$GroupName = "DOMAIN\Domain Admins"
$TestPerm = "ReadAndExecute"
If ($TestPerm = "FullControl"){$Perms = "F"}
Elseif ($TestPerm = "ReadAndExecute"){$Perms = "RX"}
Elseif ($TestPerm = "Modify"){$Perms = "M"}
Elseif ($TestPerm = "Deny"){$Perms = "D"}
Elseif ($TestPerm = "Read"){$Perms = "R"}
Elseif ($TestPerm = "Write"){$Perms = "W"}
cls
#Build icacls string -Test Output
Write-Host "ICacls ""$FilePath"" /Grant ""$GroupName"":(OI)(CI)$Perms /t /c /l /q /inheritance:r"
#Write icacls batch file
#Out-File "C:\Scripts\Test\re-acl.cmd" "ICacls ""$FilePath"" /Grant ""$GroupName"":(OI)(CI)$Perms /t /c /l /q /inheritance:r"
I realize that there is a bunch of work to do here & I am just starting to figure this out. For example, I am thinking I need to list the permissions into an array and build the string as such. There are also bound to be special permissions etc...
But for now, I am trying to figure out how to import the text file and then break it down into variables... Like I said, I am working in Powershell, but it really can be anything... VB or Python perhaps?
Big thanks in advance!
Ok, I think most of your issue is parsing the text, so that's mainly what I helped with here. I did build the strings, and if you have more permissions that you want to include you should be able to figure out how to add them to the switch
. For this we will want to read the entire text file in as a large multi-line string. Then we split it up into chunks based on the keyword "Path:". Then for each record I get the path out as a string, grab the permissions, and parse out accounts, allow/deny, and individual accesses. Then I convert the accesses to short versions accepted by icacls, and build the arguments out as a formatted string.
I output to the host, but once you are satisfied that it looks right to you, you can remove the Write-Host "
and the trailing "
and it will just execute it (assuming icacls is in the same folder that you're in, or in the PATH environment variable).
$Text = Get-Content C:\Scripts\Test\AndTest.txt -Raw
$Records = $Text -split "(?s)(Path:.*?)(?=Path:|$)"|?{$_}
#Loop through each file/ACL
ForEach($Record in $Records){
$FilePath = ($Record -split "[\r\n]+")[0].Substring(6)
$PermRecords = ($Record -split "(?s)AccessToString : "|Select -skip 1) -split "[\r\n]+"|?{$_}
$Perms = $PermRecords|?{$_ -match "(.*\\.*?)\s+(Allow|Deny)(.*)$"}|%{[pscustomobject]@{'Account'=$Matches[1].Trim();'Type'=$Matches[2];'Perms'=$Matches[3].Trim()}}
#Loop through each perm for the current file
$Perms | %{
#Convert friendly names to abbreviations
$ShortPerms = ''
Switch -regex ($_.Perms){
"FullControl" {$ShortPerms = "F";Continue}
"ReadAndExecute" {$ShortPerms += "RX,"}
"Synchronize" {$ShortPerms += "S,"}
"Modify" {$ShortPerms += "M,"}
"Read(?=,|$)" {$ShortPerms += "R,"}
"Write" {$ShortPerms += "W,"}
}
$ShortPerms = $ShortPerms.TrimEnd(',')
$Arguments = '"{0}" /{4} "{1}":(OI)(CI)({2}) /t /c /l /q /inheritance:r' -f $FilePath, $_.Account, $ShortPerms,$(If($_.Type -eq 'Allow'){'Grant'}else{'Deny'})
write-host "& ICAcls $Arguments"
}
}
If the -Raw
argument doesn't work for you, you can work around that with
(Get-Content C:\Scripts\Test\AndTest.txt) -join "`r`n"
Let me know if you have questions or issues.