PowerShell IF Matches - powershell

I'm looking to apply NTFS folder permissions using PowerShell, there are different sec groups for each of the folders. What i'm looking to do is to be able to say IF security group matches folder name which contains add permissions. Below is the code I have currently, just doing the foreach loop works but adds the sec groups to each of the folders which isn't what I want.
$folderpath = $datafromcsv.contentpath
foreach ($folder in $folderpath) {
if ($GroupName.StartsWith(DATA-$row.FolderName){
$dfsnfolder = Get-Acl -path $folder.Contains($row.FolderName)
$applysecgrouppermissions = New-Object System.Security.AccessControl.FileSystemAccessRule("Russells.com\$GroupName","ReadData","ContainerInherit","None","Allow")
$dfsnfolder.SetAccessRule($applysecgrouppermissions)
$dfsnfolder | Set-Acl $folder
}
}

This should do it if I understood everything correctly.
foreach ($folder in $datafromcsv) {
$dfsnfolder = Get-Acl -path $folder.contentpath
$filter = $GroupName | ? {$_ -like "$($folder.FolderName)*"} // I'm assuming $GroupName contains an array with all the AD group names.
foreach ($g in $filter) {
$applysecgrouppermissions = New-Object System.Security.AccessControl.FileSystemAccessRule("Russells.com\$g","ReadData","ContainerInherit","None","Allow")
$dfsnfolder.SetAccessRule($applysecgrouppermissions)
$dfsnfolder | Set-Acl $folder.contentpath
}
}

Related

Exclude specific users when listing Windows folder permissions in PowerShell

I'm trying to list all users who have access to a specific directory and the subfolders in this directory.
I've found this website that shows me how to do this pretty well. But I want to modify this script slightly so I can exclude certain built-in Windows users from the output.
So I found another link on StackOverflow that shows how to exclude a list of users from the results. But when I add the -notmatch to the existing PS script, the Group/User changes from the actual username to True or False for some reason.
What can I do to have this script filter out the users in the $ignore variable and have the Group/User show the username?
$ignore = #('BUILTIN\Administrators','CREATOR OWNER')
$ExcludeUsersRegex = ($ignore | % { [regex]::Escape($_) }) -join '|'
$FolderPath = Get-ChildItem -Directory -Path "D:\MSSQL" -Recurse -Force
$Output = #()
ForEach ($Folder in $FolderPath) {
$Acl = Get-Acl -Path $Folder.FullName
ForEach ($Access in $Acl.Access) {
$Properties = [ordered]#{'Folder Name'=$Folder.FullName;'Group/User'=$Access.IdentityReference -notmatch $ExcludeUsersRegex;'Permissions'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
#$Properties = [ordered]#{'Folder Name'=$Folder.FullName;'Group/User'=$Access.IdentityReference;'Permissions'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
$Output += New-Object -TypeName PSObject -Property $Properties
}
}
$Output | Out-GridView
You can filter at the loop level, so undesirable users aren't iterated through the loop.
ForEach($Access in ($Acl.Access|Where{$_.IdentityReference -notmatch $ExcludeUsersRegex})) {
That filters out the accesses that match a specific user name.

Exporting & Import Folder Structure and rigts with CSV file using PS Script

I'm BRAND new to ps scripting and am looking for some advice please.
We replace a data share server every couple of years, and creating the complete folder structure and permissions by hand is very tedious, so I'm trying to automate it with a powershell script. Since I'm new I've been googling for some examples and snippets and have been compiling what I need from it.
My export script reads the folder structure and rites it to a text file, and my import script creates it once I move the folder over to new server, no problem.
The problem comes with the access rights.
It reads the rights and writes it to a CSV, but once I try to import it I get an error:
new-object : Cannot convert argument "2", with value: "TRUE", for
"FileSystemAccessRule" to type
"System.Security.AccessControl.AccessControlType": "Cannot convert
value "TRUE" to type
"System.Security.AccessControl.AccessControlType". Error: "Unable to
match the identifier name TRUE to a valid enumerator name. Specify one
of the following enumerator names and try again: Allow, Deny"" At
line:1 char:23
... ccessRule = new-object System.Security.AccessControl.FileSystemAccess ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
As I understand it it's looking for a Allow/Deny and not a True/False, but the export gives a True/False. So I'm guessing there's something wrong with my export...
Here is my code if anyone could point me in the correct direction I would greatly appreciate it!!
(Let me know if I should post ALL the code, I just don't want to clutter any more than I already do :D)
Export:
$FolderPath = dir -Directory -Path $DriveLetter -Force
$Report = #()
Foreach ($Folder in $FolderPath)
{
if ($Folder.Name -notlike '*$RECYCLE.BIN*')
{
if ($Folder.Name -notlike '*System Volume Information*')
{
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access)
{
$Properties = [ordered]#{'FolderName'=$Folder.Name;'IDRef'=$Access.IdentityReference;'FSRights'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
}
}
$Report | Export-Csv -path $ExportACL -NoTypeInformation
Import:
foreach ( $LItem in $ACL_Imp )
{
$path_full = $Drivepath.ToString() + $LItem.FolderName
$ACL_Set = Get-Acl $path_full
$permission = $LItem.IDRef, $LItem.FSRights, $LItem.Inherited
$accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission <<<--- Error occurs here
$ACL_Set.SetAccessRule($accessRule)
$ACL_Set | Set-Acl $path_full
}
Example of one user in the export csv ( I remove the drive letter cause it isn't the same drive letter always.)
#TYPE System.Management.Automation.PSCustomObject;;; FolderName;IDRef;FSRights;Inherited
Data\UserA;Domain\UserA;FullControl;FALSE
Data\UserA;NT AUTHORITY\SYSTEM;FullControl;TRUE
Data\UserA;DOMAIN\UserB;FullControl;TRUE
Data\UserA;BUILTIN\Administrators;FullControl;TRUE
Data\UserA;DOMAIN\GRP_A;ReadAndExecute, Synchronize;TRUE
Data\UserA;Domain\GRP_A;ReadAndExecute, Synchronize;TRUE
Once again thanks in advance for any assistance!
And if you can't provide any, thanx for taking the time to check it out anycase!! :)
I've changed the number of variables I export and import, and that seemed to do the trick. (Exporting all variables, and only using 5)
I'm posting my Full Code in case someone else also wants to use this, or want to modify for their needs :)
Hope this will help someone in the future, and that my comments make sense..
Our Directory structure:
ImportExport <-- Location of scripts and output files (whole folder to be copied to new server)
Shared
Software
Users/UserA/
Users/UserB/
....
Users/UserZ/
Export:
#Variables
$drivepath = Get-Location #Get working drives' letter
$DriveLetter = Split-Path -qualifier $drivepath
$ExportACL = $DriveLetter.ToString() + "\ImportExport\export_acl.csv" #ACL Location
$ExportFolders = $DriveLetter.ToString() + "\ImportExport\export_folders.txt" #File with List of Folders
$UsersPath = $DriveLetter.ToString() + "\Users" #"Users" folders location on working drive located in Data folder
#Read user access levels on each folder on working drive and write to file.
cd.. #<-- add this if script is not run from within the PS environment.
$FolderPath = dir -Directory -Path $DriveLetter -Force
$Report = #()
Foreach ($Folder in $FolderPath)
{
if ($Folder.Name -notlike '*$RECYCLE.BIN*')
{
if ($Folder.Name -notlike '*ImportExport*')
{
if ($Folder.Name -notlike '*System Volume Information*')
{
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access)
{
$Properties = [ordered]#{'FolderName'=$Folder.Name;'FSRights'=$Access.FileSystemRights;'ACType'=$Access.AccessControlType;'IDRef'=$Access.IdentityReference;'Inherited'=$Access.IsInherited;'IFlags'=$Access.InheritanceFlags;'PFlags'=$Access.PropagationFlags}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
}
}
}
$Report | Export-Csv -path $ExportACL -NoTypeInformation
#Read user access levels on each child folder of Users folders on working drive and add to file.
$FolderPath = dir -Directory -Path $UsersPath -Force
$UserReport = #()
Foreach ($Folder in $FolderPath)
{
if ($Folder.Name -notlike '*$RECYCLE.BIN*')
{
if ($Folder.Name -notlike '*ImportExport*')
{
if ($Folder.Name -notlike '*System Volume Information*')
{
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access)
{
$StrFolderPath = $Folder.Parent.ToString() + "\" + $Folder.BaseName
$Properties = [ordered]#{'FolderName'=$StrFolderPath;'FSRights'=$Access.FileSystemRights;'ACType'=$Access.AccessControlType;'IDRef'=$Access.IdentityReference;'Inherited'=$Access.IsInherited;'IFlags'=$Access.InheritanceFlags;'PFlags'=$Access.PropagationFlags}
$UserReport += New-Object -TypeName PSObject -Property $Properties
}
}
}
}
}
$UserReport | Export-Csv -append $ExportACL
#Read Directory Structure and Export to File
$Dirs = Dir -Directory -Path $DriveLetter -Force
foreach($Dir in $Dirs)
{
if ($Dir.Name -notlike '*$RECYCLE.BIN*')
{
if ($Dir.Name -notlike '*ImportExport*')
{
if ($Dir.Name -notlike '*System Volume Information*')
{
$Dir.Name | out-file -Append $ExportFolders
}
}
}
}
$Dirs = Get-ChildItem -Path $UsersPath -Force
foreach($Dir in $Dirs)
{
$DirName = "Users\" + $Dir.Name
$DirName | out-file -Append $ExportFolders
}
Before import I open csv file in excel and make it different columns, so I use ";" as the delimiter, I'm struggling if I do not edit it. Variables with multiple values is split with a "," and that messes up the import.
Also, due to Admin rights needs to apply ACL, script needs to be run within elevated PS Environment, can't figure out how to do it outside. Can probably run a batch file to do a RunAs, but I had enough of this scripts for the time being. :p
Import:
#Variables
$drivepath = Get-Location #Get working drives' letter
$DriveLetter = Split-Path -qualifier $drivepath
$ImportACL = $DriveLetter.ToString() + "\ImportExport\export_acl.csv" #ACL Location
$ACL_Imp = Import-Csv $ImportACL -Delimiter ';' #Import ACL
$ImportFolders = $DriveLetter.ToString() + "\ImportExport\export_folders.txt" #File with List of Folders
$UsersPath = $DriveLetter.ToString() + "\Users" #Users' folder location on working drive
#Create Folders from text file.
Get-Content $ImportFolders | %{mkdir "$DriveLetter\$_"}
#Apply ACL to created Folder structure
foreach ( $LItem in $ACL_Imp )
{
$path_full = $Drivepath.ToString() + $LItem.FolderName
$ACL_Set = Get-Acl $path_full
$permission = $LItem.IDRef, $LItem.FSRights, $LItem.IFlags, $LItem.PFlags, $LItem.ACType
$accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission
$ACL_Set.SetAccessRule($accessRule)
$ACL_Set | Set-Acl $path_full
}

Apply rights to folders every night via a CSV file where rights are located

I am developing a PowerShell script to read the rights of 2-level folders from the root and re-apply them each night.
I managed to extract the rights in a CSV but to re-apply them I find a great difficulty. Can somebody help me, please, to develop this code?
This is the first part done :
$FolderPath = "C:\Users\klengliz\Documents\"
$extractPathDad = "C:\Users\klengliz\Documents\FolderPermissions.csv"
$FoldersToScan = Get-ChildItem -Path $FolderPath -Directory
$Report = #()
Foreach ($Folder in $FoldersToScan) {
#Get-ChildItem -Path $Folder.FullName -Directory| ForEach-Object {
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.SDDL)
{
$Properties = [ordered]#{'FolderName'=$Folder.FullName;'SDDL'=$Access}
$Report += New-Object -TypeName PSObject -Property $Properties
}
# }
}
$Report | Export-CSV $extractPathDad -NoTypeInformation

powershell permissions

I am currently using this to get a list of all permissions for specific folders.
`$InputFile = "C:\temp\Folders.txt"
$OutputFile = "C:\temp\FolderPermissions.txt"
$FolderList = Get-Content $InputFile
ForEach ($Folder in $FolderList)
{
Get-Acl $folder | Format-list >>$OutputFile
}
`
What i would like is for it to then remove all access apart from administrator from each of the specified folders.
I have looked at using SetAccessControl but can only manage to get it to remove all.
Could someone please point me in the right direction.
Thanks
The following code will remove any user execpt users matching 'administrator'
If you want to add more accounts add it to the Where-Object filter, for example:
Where-Object {$_.IdentityReference -match 'Administrator' -or $_.IdentityReference -eq 'NT AUTHORITY\SYSTEM'}
$InputFile = "C:\temp\Folders.txt"
$OutputFile = "C:\temp\FolderPermissions.txt"
$FolderList = Get-Content $InputFile
ForEach ($Folder in $FolderList)
{
Get-Acl $folder | Format-list >>$OutputFile
### Remove all ACL Rules exepet 'Administrator(s)'
$ACL = Get-ACL -Path $Folder
$Rules = $ACL.Access | Where-Object {$_.IdentityReference -notmatch 'Administrator'}
Foreach ($Rule in $Rules)
{
[Void]$ACL.RemoveAccessRule($Rule)
}
Set-Acl -Path $folder -AclObject $acl
}

Change ACL - Recurse All Directories Powershell

I am stumped!
Here is what I need to do. We have migrated to a new domain, I basically need a script that we can run on a server that will re-curse all directories and files looking at the ACL's for each. It will search the ACL for OLDDOMAIN\USER etc. if found change the ACL to NEWDOMAIN\USER but maintain all the permissions
Here is what I have so far
$access = ""
$accessarray = #()
$filesarray = #()
$permarray = #()
$filesarray = Get-ChildItem C:\Users -Recurse
ForEach($path in $filesarray) {
$pathcheck = $path.fullname
$access = get-acl $pathcheck
$accessarray = $access.AccessToString.Split(",")
foreach ($item in $accessarray) {
if ($item -match "OLDDOMAIN") {
Write-Host $pathcheck
Write-Host $item
$item = $item -replace ("OLDDOMAIN","NEWDOMAIN")
$permarray = $item.split(” “) | where-object {$_ -ne ”“}
foreach($perm in $permarray) {
$ar = New-Object system.security.accesscontrol.filesystemaccessrule $perm
$acl.SetAccessRule($ar)
$acl | Set-Acl $pathcheck
}
}
}
}
It works kind of, but the problem is that when it goes to reapply the permissions the array is not in the correct order and it fails at the set-acl command
Any ideas? Pulling my hair out here :P
Thanks
$ar = New-Object system.security.accesscontrol.filesystemaccessrule $perm
The constructor for FileSystemAccessRule takes 3 arguments, and after all your splitting and foreach, $perm will have only one argument and that construction itself will fail.
Avoid the splits etc. Powershell provides you objects. Operate on them. Don't get strings, then split etc.
You can do what you want with something like this:
gci c:\users -recurse | %{
$acl = get-acl $_.fullname
$acl.Access | ?{$_.IdentityReference.Value.StartsWith("OLDDOMAIN")} | %{
$identity = $_.IdentityReference.Value -replace "OLDDOMAIN", "NEWDOMAIN"
$permission = $identity,$_.FileSystemRights,$_.AccessControlType
$ar = New-Object system.security.accesscontrol.filesystemaccessrule $permission
$acl.SetAccessRule($ar)
}
$acl | set-acl $_.fullname
}