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
}
Related
I want to write a powershell script which identify number of drives on server and then get NTFS permission from all drives and pull end to end NTFS permissions from folders and there subfolders only not the files on multiple servers.
I tried to write a below script but its only for D drive, unable to trap errors.
As I am very new to powershell, need your help on above.
Note: system drive must be excluded.
$FolderPath = Get-ChildItem -Path "D:\" -Recurse -Force -Directory
$Servers = Get-Content .\Servers.txt
$Output = #()
ForEach ($Server in $Servers)
{
Write-Host "Getting NTFS permission from " $Server
ForEach ($Folder in ($FolderPath)) {
$Acl = Get-Acl -Path $Folder.FullName
ForEach ($Access in $Acl.Access) {
$Properties = [ordered]#{'Server'=$Server;'Folder Name'=$Folder.FullName;'Group/User'=$Access.IdentityReference;'Permissions'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
$Output += New-Object -TypeName PSObject -Property $Properties
}
}
}
$Output | export-csv -path .\NTFSPerm.csv
I created this script that will create a folder for each user that has a title of Customer Service Representative on a UNC path.There is a users group that is inherited from the parent. How can I remove that users group?
$names = (Get-ADUser -Filter 'Title -eq "Customer Service Representative"').name
foreach ($name in $names)
{
New-Item -ItemType "directory" -Path "\\unc\$name" -ErrorAction SilentlyContinue
$path = "\\unc\$name" #Replace with whatever file you want to do this to.
$user = "domain\group" #User account to grant permisions too.
$Rights = "Full" #"Read, ReadAndExecute, ListDirectory" #Comma seperated list.
$InheritSettings = "Containerinherit, ObjectInherit" #Controls how permissions are inherited by
children
$PropogationSettings = "None" #Usually set to none but can setup rules that only apply to children.
$RuleType = "Allow" #Allow or Deny.
$acl = Get-Acl $path
$perm = $user, $Rights, $InheritSettings, $PropogationSettings, $RuleType
$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $perm
$acl.SetAccessRule($rule)
$acl | Set-Acl -Path $path
}
Not sure if you're comfortable with an add-on, but you may want to check out this NTFS PowerShell module:
I've been using it for years. It's quite capable, and very easy to use.
From an admin console of PowerShell
install-package ntfssecurity
Before your closing { add the line
Remove-NTFSAccess -AccessRights FullControl -Account DOMAIN\Group -Path $path -AccessType Deny -AppliesTo ThisFolderSubfoldersAndFiles
At least, that's what I'm guessing would be appropriate? Haven't studied your code that deeply to know what you're doing exactly. I'd probably drop it in right after folder creation, but that doesn't appear to happen in here?
We have a server that houses the My Documents folder for all our users. Some of the folder owner changed to administrator. I am trying to devise a PowerShell script that goes to each user's root my documents folder and applies the user as the owner for all the sub folders and files with in it. Is this Possible?
I have the following from a previous script that attempted to set the user as full permissions per each my document root folder:
$FolderPath = "E:\mydocuredir\"
$MyDocsMain = Get-ChildItem -Path $FolderPath -Directory
Get-ChildItem -Path $FolderPath -Directory | ForEach-Object{
$HomeFolders = Get-ChildItem $FolderPath $_.Name -Directory
$Path = $HomeFolders.FullName
$Acl = (Get-Item $Path).GetAccessControl('Access')
$Username = $_.Name
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($Username, 'FullControl', 'ObjectInherit', 'InheritOnly', 'Allow')
$Acl.SetAccessRule($Ar)
Set-Acl -path $Path -AclObject $Acl
}
Firstly ensure that the share and root folder permissions for redirected folders follow best practice.
I would use the NTFSSecurity PS Module (blog on its use). This module has commands that are much easier to understand as they follow they way your would set permissions via the GUI.
$FolderPath = "E:\mydocuredir"
Get-ChildItem -Path $FolderPath -Directory | ForEach-Object{
Add-NTFSAccess -Path $_.FullName -Account "domain\$($_.Name)" -AccessRights FullControl -AppliesTo ThisFolderSubfoldersAndFiles
}
To set Owner, replace the Add-NTFSAccess command with:
Set-NTFSOwner -Path $_.FullName -Account "domain\$($_.Name)"
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"
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
}