I'm pretty new to powershell scripting (nearly 1 month since I started learning powershell.)
I'm currently working on a script with powershell 2.0 to clean folder NTFS ACL. I want to delete every acl except the administrator one.
My problem is that I can't find a way to delete every acl that are not administrator, without knowing them.
So I came here to sought for powershell pro.
This code remove acl :
$acl = Get-Acl \\remote_server\share_folder\HAL.9000
$acl.Access | %{$acl.RemoveAccessRule($_)}
This code add administrator acl :
#BUILTIN administrator
$acl = Get-Acl \\remote_server\share_folder\HAL.9000
$permission = "BUILTIN\Administrators","FullControl", "ContainerInherit,ObjectInherit","None","Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
Set-Acl \\remote_server\share_folder\HAL.9000 $acl
#Domain controller administrator
$acl = Get-Acl \\remote_server\share_folder\HAL.9000
$permission = "DOMAINCONTROLLER\Administrators","FullControl", "ContainerInherit,ObjectInherit","None","Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
Set-Acl \\remote_server\share_folder\HAL.9000 $acl
Hope this will help someone :)
For convenience I've copy/pasted all this stuff together in a function. If it can be of use to anyone, here it is:
Function Remove-ACL {
[CmdletBinding(SupportsShouldProcess=$True)]
Param(
[parameter(Mandatory=$true,ValueFromPipeline=$true,Position=0)]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path $_ -PathType Container})]
[String[]]$Folder,
[Switch]$Recurse
)
Process {
foreach ($f in $Folder) {
if ($Recurse) {$Folders = $(Get-ChildItem $f -Recurse -Directory).FullName} else {$Folders = $f}
if ($Folders -ne $null) {
$Folders | ForEach-Object {
# Remove inheritance
$acl = Get-Acl $_
$acl.SetAccessRuleProtection($true,$true)
Set-Acl $_ $acl
# Remove ACL
$acl = Get-Acl $_
$acl.Access | %{$acl.RemoveAccessRule($_)} | Out-Null
# Add local admin
$permission = "BUILTIN\Administrators","FullControl", "ContainerInherit,ObjectInherit","None","Allow"
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($rule)
Set-Acl $_ $acl
Write-Verbose "Remove-HCacl: Inheritance disabled and permissions removed from $_"
}
}
else {
Write-Verbose "Remove-HCacl: No subfolders found for $f"
}
}
}
}
Usage:
# For only one folder:
Remove-ACL 'C:\Folder' -Verbose
# For all subfolders:
Remove-ACL 'C:\Folder' -Recurse -Verbose
# Pipe stuff
'C:\Folder 1', 'C:\Folder 2' | Remove-ACL -Verbose
This code remove acl : $acl = Get-Acl
\remote_server\share_folder\HAL.9000 $acl.Access |
%{$acl.RemoveAccessRule($_)}
it does not work until you do
Set-Acl \\remote_server\share_folder\HAL.9000 $acl
Why not create a new list. For example:
$identity = New-Object System.Security.Principal.NTAccount('NT AUTHORITY\SYSTEM')
$acl = New-Object System.Security.AccessControl.DirectorySecurity
$acl.SetOwner($identity)
$acl.SetGroup($identity)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule('NT AUTHORITY\SYSTEM', ’FullControl’, ’ContainerInherit, ObjectInherit’, ’None’,’Allow’)
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule('BUILTIN\Administrators', ’FullControl’, ’ContainerInherit, ObjectInherit’, ’None’, ’Allow’)
$acl.AddAccessRule($rule)
Set-Acl -LiteralPath "C:\MyFolder" -AclObject $acl
Get-Acl -LiteralPath "C:\MyFolder" | Format-List
Related
I am trying to enable "replace all child object permission entries with inheritable permission entries from this object" method using PowerShell, below is my Script
$ProfileDir = 'C:\Users\'
$Profiles = Get-ChildItem $ProfileDir \ Select-Object -ExpandProperty Name
ForEach ($X in $Profiles)
{
$Profile = $ProfileDir + $X
Write-Host "Starting $Profile"
$Acl = Get-Acl $Profile
$Acl.SetAccessRuleProtection($false, $true)
(Get-Item $Profile).SetAccessControl($Acl)
$Permissions = (Get-Acl $Profile).Access | Where-Object
{
(-not $_.isInherited) -and $_.IdentityReference -like "domain\*"
}
ForEach ($Y in $Permissions)
{
$Acl.AddAccessRule($Y)
}
(Get-Item $Profile).SetAccessRule($Acl)
(Get-Acl $Profile).Access
}
Below is the script I have created and it worked as expected.
Thank you for your suggestions and help. To replace all child objects, I have used Get-ChildItem with -recurse and it worked.
$objName = (Get-CimInstance -ClassName Win32_ComputerSystem).UserName.Split("\")[1]
$objDir = "C:\Users\$objName\"
$objUser = (Get-CimInstance -ClassName Win32_ComputerSystem).UserName
$objAccount = New-Object System.Security.Principal.NTAccount($objUser)
$objRule = $objUser,"FullControl","ContainerInherit,ObjectInherit","None","Allow"
$objFileSec = New-Object System.Security.AccessControl.FileSecurity
$objAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($objRule)
$objFileSec.SetOwner($objAccount)
$objAclSec = Get-Acl $objDir
$objAclSec.SetAccessRuleProtection($true,$true)
$objAclSec.PurgeAccessRules($objAccount)
$objAclSec.SetAccessRule($objAccessRule)
Get-ChildItem -Path $objDir | Set-Acl -AclObject $objAclSec
$objAclSec.Access | Format-Table
Pause
I have two very similar scripts for permissions and they keep overwriting each other.
When the two scripts grant permission to the same folder only Supervisor or Logistics group get it(the last script that i have executed.
Supervisor.ps1
$dir = "E:\test\template\"
$acl = Get-Acl $dir
$permissions2 = 'Supervisors', 'ReadAndExecute,Write', 'ContainerInherit,ObjectInherit', 'None', 'Allow'
$permissions3 = 'Supervisors', 'ReadAndExecute', 'ContainerInherit,ObjectInherit', 'None', 'Allow'
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permissions3
$acl.SetAccessRule($accessRule)
$acl | Set-Acl "$dir\01.Offers\02.Out\01.Main_Offer\02.Draft"
$acl | Set-Acl "$dir\01.Offers\02.Out\01.Main_Offer\03.Sent"
$acl | Set-Acl "$dir\01.Offers\02.Out\01.Main_Offer\04.Approved"
$acl | Set-Acl "$dir\01.Offers\02.Out\02.Additional_offers\01.Add_offer_1"
$acl | Set-Acl "$dir\02.Projects\01.Drawings"
$acl | Set-Acl "$dir\02.Projects\02.BoQ"
$acl | Set-Acl "$dir\03.Documents\01.Request_for_Offer"
$acl | Set-Acl "$dir\03.Documents\06.Other"
$acl | Set-Acl "$dir\04.Contracts"
$acl | Set-Acl "$dir\08.Logistics"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permissions2
$acl.SetAccessRule($accessRule)
$acl | Set-Acl "$dir\01.Offers\01.In"
$acl | Set-Acl "$dir\01.Offers\02.Out\01.Main_Offer\01.Calc"
$acl | Set-Acl "$dir\02.Projects\03.Reports"
$acl | Set-Acl "$dir\03.Documents\02.Schedules"
$acl | Set-Acl "$dir\03.Documents\03.Reports"
$acl | Set-Acl "$dir\03.Documents\04.Protocols"
$acl | Set-Acl "$dir\03.Documents\05.Construction_Programs"
$acl | Set-Acl "$dir\06.Correspondence"
$acl | Set-Acl "$dir\07.Pictures"
Logistics.ps1
$dir = "E:\test\template"
$acl = Get-Acl $dir
$permissions = 'Logistics', 'ReadAndExecute,Write', 'ContainerInherit,ObjectInherit', 'None', 'Allow'
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permissions
$acl.SetAccessRule($accessRule)
$acl | Set-Acl "$dir\01.Offers\01.In"
$acl | Set-Acl "$dir\01.Offers\02.Out\01.Main_Offer\01.Calc"
$acl | Set-Acl "$dir\02.Projects"
$acl | Set-Acl "$dir\03.Documents\04.Protocols"
$acl | Set-Acl "$dir\06.Correspondence"
$acl | Set-Acl "$dir\07.Pictures"
$acl | Set-Acl "$dir\08.Logistics"
$permissions1 = 'Logistics', 'ReadAndExecute', 'ContainerInherit,ObjectInherit', 'None', 'Allow'
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permissions1
$acl.SetAccessRule($accessRule)
$acl | Set-Acl "$dir\01.Offers\02.Out\01.Main_Offer\04.Approved"
$acl | Set-Acl "$dir\01.Offers\02.Out\02.Additional_offers\01.Add_offer_1\03.Approved"
$acl | Set-Acl "$dir\03.Documents\02.Schedules"
$acl | Set-Acl "$dir\03.Documents\03.Reports"
Have you tried AddAccessRule instead of SetAccessRule?
The SetAccessRule method adds the specified access control list (ACL) rule or overwrites any identical ACL rules that match the FileSystemRights value of the rule parameter.
My script in a nutshell should create 5 Folders, 1 root level folder, 3 2nd level folders, and 1 3rd level folder.
Permissions are granted at the 2nd level, either ReadWrite or ReadOnly. No user should be able to create anything within the second level or delete a second level.
I seem to be having issues with Set-Acl and permissions. I'm wondering if there's a better way to script this out that I don't need elevated privileges for. Our DA's can run the script fine, and I can do the folder and security group creation manually but its tedious and prone to errors. Any insight into what I'm doing wrong or how I could do it better would be appreciated.
Import-Module ActiveDirectory
$path = "\\earth\data\group\"
$newFolderName = Read-Host -Prompt "Enter Name of New Folder"
$newFolderFull = $path + $newFolderName
Write-Output "New Folder will be: $newFolderFull"
$confirm = Read-Host "Confirm? Y/N"
if (!(($confirm) -ne "y")) {
Write-Output "Create AD Groups"
$groupNamePGroup = "P_$newFolderName"
$groupNameAdminRW = "EG-$newFolderName-Admin-RW"
$groupNameAdminRF = "EG-$newFolderName-Admin-RF"
$groupNameEveryoneRW = "EG-$newFolderName-Everyone-RW"
$groupNameEveryoneRF = "EG-$newFolderName-Everyone-RF"
$groupNameScannedDocsRW = "EG-$newFolderName-ScannedDocs-RW"
New-ADGroup $groupNamePGroup -samAccountName $groupNamePGroup -GroupScope DomainLocal -path "OU=SecurityGroups,OU=Metro,DC=metrogr,DC=org"
New-ADGroup $groupNameAdminRW -samAccountName $groupNameAdminRW -GroupScope DomainLocal -path "OU=SecurityGroups,OU=Metro,DC=metrogr,DC=org"
New-ADGroup $groupNameAdminRF -samAccountName $groupNameAdminRF -GroupScope DomainLocal -path "OU=SecurityGroups,OU=Metro,DC=metrogr,DC=org"
New-ADGroup $groupNameEveryoneRW -samAccountName $groupNameEveryoneRW -GroupScope DomainLocal -path "OU=SecurityGroups,OU=Metro,DC=metrogr,DC=org"
New-ADGroup $groupNameEveryoneRF -samAccountName $groupNameEveryoneRF -GroupScope DomainLocal -path "OU=SecurityGroups,OU=Metro,DC=metrogr,DC=org"
New-ADGroup $groupNameScannedDocsRW -samAccountName $groupNameScannedDocsRW -GroupScope DomainLocal -path "OU=SecurityGroups,OU=Metro,DC=metrogr,DC=org"
Write-Output "Add Folder.."
New-Item $newFolderFull -ItemType Directory
New-Item $newFolderFull\Admin -ItemType Directory
New-Item $newFolderFull\Everyone -ItemType Directory
New-Item $newFolderFull\ScannedDocs -ItemType Directory
New-Item $newFolderFull\Everyone\ScannedDocs -ItemType Directory
Write-Output "Remove Inheritance.."
icacls $newFolderFull /inheritance:d
icacls $newFolderFull\Admin /inheritance:d
icacls $newFolderFull\Everyone /inheritance:d
icacls $newFolderFull\Everyone\ScannedDocs /inheritance:d
#icacls $newFolderFull\ScannedDocs /inheritance:d
# Rights
$readOnly = [Security.AccessControl.FileSystemRights]"ReadAndExecute"
$readWrite = [Security.AccessControl.FileSystemRights]"Write, DeleteSubdirectoriesAndFiles,ReadAndExecute"
# Inheritance
$inheritanceFlag = [Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
# Propagation
$propagationFlag = [Security.AccessControl.PropagationFlags]::None
# User
$PUserRF = New-Object System.Security.Principal.NTAccount($groupNamePGroup)
$AdminUserRW = New-Object System.Security.Principal.NTAccount($groupnameAdminRW)
$AdminUserRF = New-Object System.Security.Principal.NTAccount($groupnameAdminRF)
$EveryoneUserRW = New-Object System.Security.Principal.NTAccount($groupnameEveryoneRW)
$EveryoneUserRF = New-Object System.Security.Principal.NTAccount($groupnameEveryoneRF)
$ScannedDocsUserRW = New-Object System.Security.Principal.NTAccount($groupnameScannedDocsRW)
# Type
$type = [Security.AccessControl.AccessControlType]::Allow
#Add Group membership
Add-ADGroupMember -Identity $groupNamePGroup -Members $groupNameAdminRW,$groupNameAdminRF,$groupNameEveryoneRW,$groupNameEveryoneRF,$groupNameScannedDocsRW
Add-ADGroupMember -Identity $groupNameEveryoneRW -Members NDPSSCAN
Add-ADGroupMember -Identity $groupNameScannedDocsRW -Members NDPSSCAN
# ACL
$accessControlEntryDefault = New-Object System.Security.AccessControl.FileSystemAccessRule #("Domain Users", $readOnly, $inheritanceFlag, $propagationFlag, $type)
$accessControlRootEntryRF = New-Object System.Security.AccessControl.FileSystemAccessRule #($PUserRF, $readOnly, $inheritanceFlag, $propagationFlag, $type)
$accessControlAdminEntryRW = New-Object System.Security.AccessControl.FileSystemAccessRule #($AdminUserRW, $readWrite, $inheritanceFlag, $propagationFlag, $type)
$accessControlAdminEntryRF = New-Object System.Security.AccessControl.FileSystemAccessRule #($AdminUserRF, $readOnly, $inheritanceFlag, $propagationFlag, $type)
$accessControlEveryoneEntryRW = New-Object System.Security.AccessControl.FileSystemAccessRule #($EveryoneUserRW, $readWrite, $inheritanceFlag, $propagationFlag, $type)
$accessControlEveryoneEntryRF = New-Object System.Security.AccessControl.FileSystemAccessRule #($EveryoneUserRF, $readOnly, $inheritanceFlag, $propagationFlag, $type)
$accessControlScannedDocsEntryRW = New-Object System.Security.AccessControl.FileSystemAccessRule #($ScannedDocsUserRW, $readWrite, $inheritanceFlag, $propagationFlag, $type)
$objACL = Get-Acl $newFolderFull
$objACL.RemoveAccessRuleAll($accessControlEntryDefault)
$objACL.AddAccessRule($accessControlRootEntryRF)
Set-Acl $newFolderFull $objACL
$objACL = Get-Acl $newFolderFull\Admin
$objACL.RemoveAccessRuleAll($accessControlEntryDefault)
$objACL.AddAccessRule($accessControlAdminEntryRW)
$objACL.AddAccessRule($accessControlAdminEntryRF)
Set-Acl $newFolderFull\Admin $objACL
$objACL = Get-Acl $newFolderFull\Everyone
$objACL.RemoveAccessRuleAll($accessControlEntryDefault)
$objACL.AddAccessRule($accessControlEveryoneEntryRW)
$objACL.AddAccessRule($accessControlEveryoneEntryRF)
Set-Acl $newFolderFull\Everyone $objACL
$objACL = Get-Acl $newFolderFull\ScannedDocs
$objACL.RemoveAccessRuleAll($accessControlEntryDefault)
$objACL.AddAccessRule($accessControlScannedDocsEntryRW)
Set-Acl $newFolderFull\ScannedDocs $objACL
}
SetAccessControl($objACL) worked for me.
Set-ACL didn't work as my account didn't have elevated permissions.
When I set user access via set-acl I can loop through all existing subfolders. How do I set it to include future subfolders created under the main folder?
Also... Once the access is set it only displays in 'Advanced' settings for the folders. The first security screen shows the user but shows no access rights.
This is in Windows Server 2012 R2.
$SubFolder = "name"
$UserName = "domain\" + $SubFolder
$Folder = "R:\User Files\" + $SubFolder + "\"
$Acl = Get-Acl $Folder
$Ar = New-Object system.security.accesscontrol.filesystemaccessrule($UserName,"FullControl","Allow")
$Acl.SetAccessRule($Ar)
#Get-Variable
Set-Acl -Path $Folder -AclObject $Acl
$Folder = Get-childItem $Folder
foreach ($TempFolder in $Folder)
{
$Folder = $TempFolder.FullName
$Acl = Get-Acl $Folder
$Ar = New-Object system.security.accesscontrol.filesystemaccessrule($UserName,"FullControl","Allow")
$Acl.SetAccessRule($Ar)
#Get-Variable
Set-Acl -Path $Folder -AclObject $Acl
}
You will need to set your Inheritance and Propagation flags in order for it to affect files and folders within your target. Here's my typical template that I use when I'm working on setting up new ACLs for users:
$Rights = [System.Security.AccessControl.FileSystemRights]"FullControl"
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ObjectInherit,ContainerInherit"
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
$objType =[System.Security.AccessControl.AccessControlType]::Allow
#Define the user's account using their samAccountName
$objUser = New-Object System.Security.Principal.NTAccount("samAccountName")
$objACE = New-Object System.Security.AccessControl.FileSystemAccessRule($objUser, $Rights, $InheritanceFlag, $PropagationFlag, $objType)
$objACL = Get-ACL "C:\Temp"
$objACL.AddAccessRule($objACE)
Set-ACL "C:\Temp" $objACL
The settings here will make future things inherit the settings that you define for the target folder.
i am trying to write a script which adds"CreatorOwner" permission to profile$ folders on all file servers;
i.e , add "CreatorOwner" permissions to "\FileServer\Profile$"
can anybody tell me whats the command and syntax for it?
Please do ask if any questions.
One way of doing this is using WMI and UNC paths.
$AccessRule = New-Object system.security.accesscontrol.filesystemaccessrule("CREATOR OWNER","FullControl","ContainerInherit, ObjectInherit","InheritOnly","Allow")
$profileshare = Get-WmiObject Win32_Share -ComputerName fileserver -Filter "name = 'profile$'"
$driveletter, $path = $profileshare.path
$path = $path.TrimStart("\")
$ACL = Get-Acl "\\fileserver\$driveletter`$\$path"
$ACL.SetAccessRule($AccessRule)
Set-Acl \\fileserver\$driveletter`$\$path -AclObject $ACL
Now if you have a list of server names you could do the following:
$servers = #("fileserver1","fileserver2","fileserver3")
$AccessRule = New-Object system.security.accesscontrol.filesystemaccessrule("CREATOR OWNER","FullControl","ContainerInherit, ObjectInherit","InheritOnly","Allow")
$servers | % {
$profileshare = Get-WmiObject Win32_Share -ComputerName $_ -Filter "name = 'profile$'"
$driveletter, $path = $profileshare.path
$path = $path.TrimStart("\")
$ACL = Get-Acl "\\$_\$driveletter`$\$path"
$ACL.SetAccessRule($AccessRule)
Set-Acl \\$_\$driveletter`$\$path -AclObject $ACL
}
This will do it:
#Change the CSV file path
$Permissions = Import-Csv C:\Test.CSV -delimiter '|'
ForEach ($line in $Permissions)
$inherit = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit,
ObjectInherit"
$propagation = [system.security.accesscontrol.PropagationFlags]"None"
$acl = Get-Acl $line.Path
$acl.SetAccessRuleProtection($True, $False)
$accessrule = New-Object system.security.AccessControl.FileSystemAccessRule("domain users", "Read", $inherit, $propagation, "Allow")
#Adding the Rule
$acl.AddAccessRule($accessrule)
#Setting the Change
Set-Acl $line.Path $acl
What the CSV file looks Like
\SRV01\Folder1\Folder2 etc.