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
}
Related
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
}
}
I am trying to make a script that creates file areas for different groups in a company. All the members in the group need to have full access to the shared files, but any member from the other groups can not have access - not even see them. This is what I have. For the "Limit access" section you need to change up the name of the group, and repeat this for each group. Can I put this in a foreach loop?
I am new to Powershell and really want to learn how to improve my script. So how can I improve and automate this code?
# Creates file areas
$folders = ('C:\shares\it-drift','C:\shares\dev-team','C:\shares\regnskap','C:\shares\renhold','C:\shares\HR')
mkdir -path $folders
$folders | Where-Object {$_ -like "*shares*"} | ForEach-Object {$name = (Get-Item $_).name; $DfsPath = (‘\\sec.core\files\’ + $name); $targetPath = (‘\\dc1\’ + $name);New-DfsnFolderTarget -Path $dfsPath -TargetPath $targetPath}
# Limits access
$folder = ('C:\shares\dev-team')
$ACL = Get-Acl -path \\sec.core\files\dev-team
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("sec.core\g_dev_team","FullControl","Allow")
$ACL.SetAccessRule($AccessRule)
$ACL | Set-Acl -Path "\\sec.core\files\dev-team"
$ACL.SetAccessRuleProtection($true,$true)
$ACL = Get-Acl "\\sec.core\files\dev-team"
$ACL.Access | where {$_.IdentityReference -eq "BUILTIN\Users" } | foreach { $acl.RemoveAccessRuleSpecific($_) }
Set-Acl "\\sec.core\files\dev-team" $acl
(Get-ACL -Path "\\sec.core\files\dev-team").Access | Format-Table IdentityReference,FileSystemRights,AccessControlType,IsInherited,InheritanceFlags -AutoSize
Appreciate all tips:)
Here is how you can automate set of the same ACL for each shared folder:
# Creates file areas
$folders = #(
'C:\shares\it-drift'
'C:\shares\dev-team'
'C:\shares\regnskap'
'C:\shares\renhold'
'C:\shares\HR'
)
mkdir -path $folders
$folders | Where-Object {$_ -like "*shares*"} |
ForEach-Object {
$name = (Get-Item $_).name
$DfsPath = '\\sec.core\files\' + $name
$targetPath = '\\dc1\' + $name
New-DfsnFolderTarget -Path $dfsPath -TargetPath $targetPath
}
# Limits access
foreach($folder in $folders)
{
$leaf = Split-Path $folder -Leaf
$path="\\sec.core\files\$leaf"
$acl = Get-Acl -Path $path
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("sec.core\g_dev_team","FullControl","Allow")
$acl.SetAccessRule($AccessRule)
Set-Acl -Path $path -AclObject $acl
$acl.SetAccessRuleProtection($true,$true)
$acl = Get-Acl "\\sec.core\files\dev-team"
$acl.Access.where({$_.IdentityReference -eq "BUILTIN\Users"}).foreach({
$acl.RemoveAccessRuleSpecific($_)
})
Set-Acl -Path $path -AclObject $acl
(Get-ACL -Path $path).Access |
Format-Table IdentityReference,FileSystemRights,AccessControlType,IsInherited,InheritanceFlags -AutoSize
}
Try to use vertical coding instead of horizontal coding. People reading your code will be thankful.
Once a User is removed in AD their name is changes to a S-X-XX-XXX
I have a script to pull all folders where the S-X-XX-XXX has permissions, what I am trying to do is take that list of Folders and remove all S-X-XX-XXX's.
Code
<# The S-* is to represent the User ID that I am wanting to remove their folder permissions #>
$TargetUser = "S-*"
$TargetPath = "C:\Depts"
$Paths = get-childitem -path $TargetPath -Recurse -Directory
$FolderList = $Paths.FullName
ForEach ($Folder in $FolderList) {
$ACL = Get-Acl -Path $Folder
$ACLlist = $ACL.Access | where {$_.IdentityReference -like "*mike*"}
$RemoveUser = $ACLlist.IdentityReference
if ($ACLlist.IdentityReference -like "$TargetUser") {
Write-Host $Folder
Write-Host $RemoveUser
$ACE = New-Object System.Security.Accesscontrol.FileSystemAccessRule($RemoveUser, "None", "ContainerInherit,ObjectInherit", "InheritOnly", "Deny")
$ACL.AddAccessRule($ACE)
Set-Acl -Path $Folder -AclObject $ACL
}
}
I have found code on how to set folder permission from another folders permissions, however this are users that were not added through inheritance.
I know I am missing something simple so any help would be great.
Folder Permissions
Big thanks to everyone that replied, I appreciate you guys taking the time to help.
You can check what type of user login in acl, you don't need template.And you must go for each access rule in each folder to check this,because removeaccesrule method take only one object at time.
$DebugPreference = 'Continue'
$TargetPath = "D:\testdir"
$Paths = get-childitem -path $TargetPath -Recurse -Directory
$FolderList = $Paths.FullName
ForEach ($Folder in $FolderList) {
$ACLs = Get-Acl -Path $Folder
foreach($acl in $ACLs.Access){
If (($acl.IdentityReference -is [System.Security.Principal.SecurityIdentifier]) -and (-not $acl.IsInherited)){
Write-Debug ("Removing ACl for {0}`r`n" -f $acl.IdentityReference.Value)
[Void]$ACLs.RemoveAccessRule($acl)
}
}
Write-Debug ("Setting ACL for {0}`r`n" -f $folder.FullName)
Set-Acl -path $folder -aclObject $ACLs
}
I have one more solution:
Use module ntfsSecurity(folder and files management manual)
Lists all permissions that can no longer be resolved. This normally happens if the account is no longer available so the permissions show up as a SID and not as an account name.
To remove all non-resolvable or orphaned permissions you can use the following line. But be very careful with that as maybe the account is not resolvable due to a network problem.
Install-Module -Name NTFSSecurity
dir -Recurse | Get-NTFSOrphanedAccess | Remove-NTFSAccess
The answer for the problem is below.
Clear
$TargetUser = Read-Host -Prompt "Enter the target account you are targeting [Full or Parital works]"
$RootPath = Read-Host -Prompt "Enter the root folder to start looking in and removing permissions"
$SubPaths = Get-ChildItem -Path $RootPath -Recurse -Directory
$SubFolderList = $SubPaths.FullName
$rootdone = $false
$FolderPurgeList = #()
if ($rootdone -eq $false) {
$ACL = Get-Acl -Path $RootPath
$ACLlist = $ACL.Access | where {$_.IdentityReference -like "*$TargetUser*"}
$RemoveUser = $ACLlist.IdentityReference
$count = $RemoveUser.count
ForEach ($UserName in $RemoveUser ) {
$UserID = New-Object System.Security.Principal.Ntaccount ($UserName)
$ACL.PurgeAccessRules($UserID)
$ACL | Set-Acl $RootPath
$itemHasPerm = New-Object –TypeName PSObject
$itemHasPerm | Add-Member –MemberType NoteProperty –Name "Target User" -Value $UserName
$itemHasPerm | Add-Member –MemberType NoteProperty –Name "Folder Path" -Value $RootPath
$FolderPurgeList += $itemHasPerm
$count -= 1
}
if ($count -eq 0 ) {
$rootdone = $true
}
}
if ($rootdone -eq $true) {
ForEach ($SubFolder in $SubFolderList) {
$ACL = Get-Acl -Path $SubFolder
$ACLlist = $ACL.Access | where {$_.IdentityReference -like "*$TargetUser*"}
$RemoveUser = $ACLlist.IdentityReference
ForEach ($UserName in $RemoveUser ) {
$UserID = New-Object System.Security.Principal.Ntaccount ($UserName)
$ACL.PurgeAccessRules($UserID)
$ACL | Set-Acl $SubFolder
$itemHasPerm = New-Object –TypeName PSObject
$itemHasPerm | Add-Member –MemberType NoteProperty –Name "Target User" -Value $UserName
$itemHasPerm | Add-Member –MemberType NoteProperty –Name "Folder Path" -Value $SubFolder
$FolderPurgeList += $itemHasPerm
}
}
}
$FolderPurgeList
$DateStamp = Get-Date -Format "dd-MMM-yyyy - hh-ss"
$FolderPurgeList | Export-CSV $env:USERProfile\Documents\Purged_Permission_List_$DateStamp.csv
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 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
}