I would like to do something similar to How to Remove all permissions for a specific user?, but I want to remove all access to the file for everybody except the owner of the file.
Is it possible to do that in a relatively clean way?
I suppose I could call get-acl C:\users\myusername\AppData\Local\Temp\TheFile.txt and then walk through all the users listed there, and remove all rights for each one (as described in the linked question above), but is there an easier way?
Examplecode in a function (Put it simply in the same Scriptfile, above all your own code):
function Remove-ACLEntries
{
[CmdletBinding()]
param(
[string]$File
)
$authusers = ((New-Object System.Security.Principal.SecurityIdentifier 'S-1-5-11').Translate([System.Security.Principal.NTAccount])).Value
$acl = Get-Acl $File
$acl.SetAccessRuleProtection($True, $False)
$owner = $acl.owner;
For($i=$acl.Access.Count - 1; $i -gt 0; $i--)
{
$rule = $acl.Access[$i]
if ($rule.IdentityReference -ne $owner -or $rule.IdentityReference -eq $authusers)
{
$acl.RemoveAccessRule($rule)
}
}
Set-ACL -Path $file -AclObject $acl | Out-Null
}
Usage Single File:
Remove-ACLEntries -File c:\your\path\to\file.txt
Usage Multiple Files:
$files = Get-Childitem c:\your\path -Recurse
foreach ($file in $files){ Remove-ACLEntries -File $file.Fullname }
Attention: The User you are using to operate this function must have fullaccess to the file by himself. If the function don't working, try to run the powershell in Adminmode.
Greetings, Ronny
The example below removes all the ACLs and sets the ACL to allow Full Control for the owner of the file.
$acl = Get-Acl "$filePath"
$object = New-Object System.Security.Principal.Ntaccount($acl.owner)
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($acl.owner,"FullControl","Allow")
$acl.SetOwner($object)
$acl.SetAccessRuleProtection($true,$false)
$acl.SetAccessRule($AccessRule)
#$acl.SetAccessRule($sysUserAccessRule)
$acl | Set-Acl "$filePath"
Related
Attempting to set the owner of a folder as Domain Admins and force inheritance on all sub-folder/files. Using a combination of scripts I've found:
$Account = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList $DomainAdmins;
#Get a list of folders and files
$ItemList = Get-ChildItem -Path $Dir -Recurse;
#Iterate over files/folders
foreach ($Item in $ItemList) {
$Acl = $null; # Reset the $Acl variable to $null
$Acl = Get-Acl -Path $Item.FullName; # Get the ACL from the item
$Acl.SetOwner($Account); # Update the in-memory ACL
$isProtected = $false
$preserveInheritance = $false
$Acl.SetAccessRuleProtection($isProtected, $preserveInheritance)
Set-Acl -Path $Item.FullName -AclObject $Acl; # Set the updated ACL on the target item
}
Error: Set-Acl : Cannot bind argument to parameter 'AclObject' because it is null.
Some folders assign properly, however, not all. I suspect it breaks were there is no owner (possibly an account that's been removed from AD.)
Any ideas on how to approach this?
We will end up using this, even though it's not handling the long file paths correctly.
Import-Module -Name NTFSSecurity
#Remove Inheritance on user's root folder
Get-Item $UserRoot | Disable-NTFSAccessInheritance
#Add Domain Admin to user's root folder
Add-NTFSAccess -Path $UserRoot -Account 'BUILTIN\Administrators', 'yourDomain\Domain Admins' -AccessRights FullControl
#Set Inheritance on all sub-folders on user's directory
Get-ChildItem -Path $UserRoot -Recurse | Enable-NTFSAccessInheritance -PassThru
Check SetOwner() method for setting up owner for a folder
# Define the owner account/group
$Account = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList 'BUILTIN\Administrators';
# Get a list of folders and files
$ItemList = Get-ChildItem -Path c:\test -Recurse;
# Iterate over files/folders
foreach ($Item in $ItemList) {
$Acl = $null; # Reset the $Acl variable to $null
$Acl = Get-Acl -Path $Item.FullName; # Get the ACL from the item
$Acl.SetOwner($Account); # Update the in-memory ACL
Set-Acl -Path $Item.FullName -AclObject $Acl; # Set the updated ACL on the target item
}
Specify Inheritance in FileSystemAccessRule()
$Acl = Get-Acl "\\R9N2WRN\Share"
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("user", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
$Acl.SetAccessRule($Ar)
Set-Acl "\\R9N2WRN\Share" $Acl
Check the SO1 and SO2 for further related information.
I have a PowerShell script that I wrote to create a subfolder "Admin", if it doesn't already exist, in over 4000 folders in a shared directory. After creating the subfolders I need the permissions of the subfolders to only be for a specific group within the domain. I get no errors, other than the folder already exist errors on the subfolder, but I let the script run for 12 hours and it never completed. I stopped the script to find that all the Admin subfolders were created but the permissions were not set.
If I take out the * wildcard in the $folder add input a folder name it works perfectly. How can I get it work with the * wildcard so I don't have to manually enter over 4000 folder names?
Here is my script:
# If the folder for Equipment Images does not exist, make a new one and set the correct permissions.
$Location = "E:\Images\Equipment\*\"
$file = "E:\Images\Equipment\*\Admin"
foreach ($_ in (Get-ChildItem E:\Images\Equipment\*\)) {
if (($_.PSIsContainer -AND $_.name -eq "Admin")-eq $false) {
New-Item -Path $location -Name "Admin" -ItemType directory
$errorActionPreference = "continue"
}
$folder = "E:\Images\Equipment\*\Admin"
$acl = Get-Acl $folder
if ($acl.AreAccessRulesProtected) {
$acl.Access | % {$acl.purgeaccessrules($_.IdentityReference)}
} else {
$isProtected = $true
$preserveInheritance = $false
$acl.SetAccessRuleProtection($isProtected, $preserveInheritance)
}
$account = "recoequip\folder sales group"
$rights = [System.Security.AccessControl.FileSystemRights]::FullControl
$inheritance = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]::None
$allowdeny = [System.Security.AccessControl.AccessControlType]::Allow
$dirACE = New-Object System.Security.AccessControl.FileSystemAccessRule ($account,$rights,$inheritance,$propagation,$allowdeny)
$ACL.AddAccessRule($dirACE)
Set-Acl -aclobject $ACL -Path $folder
Write-Host $folder Permissions added
}
Just don't use the wildcard with any Acl cmdlets, I don't think that will work.
Set the permission on a single folder in the loop before, or if you have to do it later, just loop through all the folders and set the permissions on all admin folders individually, one by one.
Some tips:
Start with a small sub-set of the 400 folders for testing, and Write-Host the currently processed folder so you can see the progress.
Code sample:
Get-ChildItem E:\Images\Equipment\ -Directory -Filter "admin" -Recurse | ForEach-Object {
$acl = Get-Acl $_.FullName
... # do your permission stuff
}
I know this question was answered for a specific folder, but I would like to remove a user from all subfolders as well.
I tried to set the inheritance and propagation values to make sure the setting is inherited, but it still only applies for the root directory, no matter how I set the arguments. (part of) my code looks like this:
$inherit = "ContainerInherit, ObjectInherit"
$propagation = "None"
$Acl=get-acl $o2
$Accessrule = New-Object system.security.AccessControl.FileSystemAccessRule($o1,"Read", $inherit, $propagation,"Allow")
$Acl.RemoveAccessRuleAll($Accessrule)
Set-Acl -Path $o2 -AclObject $Acl
Careful with the following, it will remove ACLs
TEST BEFORE USING
I will strongly recommend making a ROBOCOPY with the full ACLs on a separate drive before using the following. If something is not right, you can always copy the files or the ACLs or both back.
Ok here is something you can start with. Like Ansgar says, you pretty much loop through, the folder list, and for each folder you retrieve all Access Controls Entry (ACE) in each ACL.
If the ACE is not inherited, you remove it.
Updated to use $o1
Ok in this version the ACE needs to be assigned to the user defined by $o1.
I have not tested it, so make some tests and check the values step by step before unleashing hell.
$filepath = "<your drive letter>:"
$folders = #((get-item $filePath))
$folders += Get-ChildItem $filePath -Recurse | where { $_.PSIsContainer -ne $false }
Foreach ($folder in $folders)
{
$acl = Get-Acl -Path $folder.FullName
Foreach($access in $acl.access)
{
if ($access.isinherited -eq $false -and $access.IdentityReference.Value -eq $o1)
{
$acl.RemoveAccessRule($access)
}
}
Set-Acl -path $folder.fullname -aclObject $acl
}
I want to export in a csv file the ACL of every subfolder starting from a root folder and then to import them of mirroring folders on another computer.
I'm using this code to export from C:\Users\user\Desktop\a :
Get-ChildItem "C:\Users\user\Desktop\a" -Recurse | ?{ $_.PsIsContainer } | %{
$Path = $_.FullName
# Exclude inherited rights from the report
(Get-Acl $Path).Access | ?{ !$_.IsInherited } | Select-Object `
#{n='Path';e={ $Path }}, IdentityReference, AccessControlType, `
InheritanceFlags, PropagationFlags, FileSystemRights
} | Export-CSV "C:\Users\user\Desktop\Permissions.csv"
and this code to import ACL:
$par = Import-Csv -Path "C:\Users\user\Desktop\Permissions.csv"
foreach ( $i in $par ) {
$path= $i.Path
$IdentityReference= $i.IdentityReference
$AccessControlType=$i.AccessControlType
$InheritanceFlags= $i.InheritanceFlags
$PropagationFlags=$i.PropagationFlags
$FileSystemRights=$i.FileSystemRights
echo $path $IdentityReference
$acl = Get-Acl C:\Users\user\Desktop
$permission = $i.IdentityReference,$i.FileSystemRights,$i.AccessControlType
$accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$acl | Set-Acl $path
}
Permissions.csv is something like this:
#TYPE Selected.System.Security.AccessControl.FileSystemAccessRule
"Path","IdentityReference","AccessControlType","InheritanceFlags","PropagationFlags","FileSystemRights"
"C:\Users\user\Desktop\a\b","DITOADMIN\pluto","Allow","None","None","ReadAndExecute, Synchronize"
"C:\Users\user\Desktop\a\b\c","DITOADMIN\pluto","Allow","ContainerInherit, ObjectInherit","None","ReadAndExecute, Synchronize"
"C:\Users\user\Desktop\a\b\c","DITOADMIN\admin","Allow","None","None","FullControl"
"C:\Users\user\Desktop\a\b\c","DITOADMIN\pippo","Allow","ContainerInherit, ObjectInherit","None","ReadAndExecute, Synchronize"
unfortunately, import action doesn't work since only last permission is imported (so only for pippo user and not for pluto).
anybody knows why?
I've fixed it.
the problem was the line, the path I use here was wrong (should be the path from the CSV import)
$acl = Get-Acl C:\Users\user\Desktop
$permission = $i.IdentityReference,$i.FileSystemRights,$i.AccessControlType
I've changed with
$acl = Get-Acl $path
$permission = $IdentityReference, $FileSystemRights, $InheritanceFlags, $PropagationFlags, $AccessControlType
bye
It's almost perfect. Here you add the permission from the CSV to the folder, but you keep the old permission on it. You dont "reset/copy" the ACL from one folder to the other.
So instead of getting the ACL of the receiving folder:
$acl = Get-Acl $path
Ive create a new one:
$acl = New-Object System.Security.AccessControl.DirectorySecurity
But then, i lose the Owner attribute. So i need a way to export the owner in the CSV with the rights..
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
}