Does "Set-Content" in PowerShell keep the File Access rights? - powershell

I plan to update some files via PowerShell. Will Set-Content keep the access rights (ACL) or do I have to backup and restore these rights explicitly?

Set-Content (and Add-Content) and Out-File / > (>>) do not recreate an existing target file, they replace (append to) its contents, so its ACLs are preserved.
You can verify this with the following example code:
Push-Location $env:TEMP
Remove-Item tmp.txt -EA SilentlyContinue
# Create file 'tmp.txt with default ACL.
'original content' | Set-Content tmp.txt
# Modify the ACL to allow the Guests groups read access.
$acl = Get-Acl tmp.txt
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule Guests, Read, Allow))
Set-Acl tmp.txt $acl
'ACL *before* Set-Content:'
(Get-Acl tmp.txt).Access.IdentityReference | Out-Host
# Use Set-Content to replace the existing content.
'new content' | Set-Content tmp.txt
# Verify that the file's ACL hasn't changed.
'ACL *after* Set-Content:'
(Get-Acl tmp.txt).Access.IdentityReference | Out-Host
Remove-Item tmp.txt
The above yields something like the following, showing that the custom ACL was preserved even after replacing the file's content with Set-Content:
ACL *before* Set-Content:
Value
-----
BUILTIN\Guests
NT AUTHORITY\SYSTEM
BUILTIN\Administrators
WS1\jdoe
ACL *after* Set-Content:
Value
-----
BUILTIN\Guests
NT AUTHORITY\SYSTEM
BUILTIN\Administrators
WS1\jdoe

Related

Why is a Powershell-script working at Windows 10 but not at Windows 11

I have a script that should override the inheritance of files and set selected permissions for certain user groups. The user group, the permissions to be set and the files on which it should be executed are read from a .txt file
The .txt file looks like this:
The script reads from line 1 the user group as parameter $group, from line 3 the parameter $rights and from line 5 the parameter $path reads all lines, so that you can add as much filepaths as you want.
This is the script:
#declare the file from which preferences are to be read
$standartpath = "C:\_TEST\PathAndGroup.txt"
#reads parameters from file
$path = Get-Content -path $standartpath|Select-Object -Skip 5
$group = (Get-Content -path $standartpath)[1]
$rights = (Get-Content -path $standartpath)[3]
#uninherits inheritance of parent folders
$Berechtigung = Get-ACL -Path $path
$Berechtigung.SetAccessRuleProtection($true, $true)
$Berechtigung | Set-Acl -Path $path
#Changes the group's access rights to the file
$Berechtigung = Get-ACL -Path $path
$NEUBerechtigung = New-Object System.Security.AccessControl.FileSystemAccessRule($group,$rights,”Allow”)
$Berechtigung.SetAccessRule($NEUBerechtigung)
$Berechtigung | Set-Acl -Path $path
This script works on Windows 10 without any problems. With Windows 11, however, it only overrides inheritance, but does not set the newly set permissions for the user groups.
I ran the script on both operating systems in the same location with the same administrator privileges.

Substitute icacls.exe with powershell

I want to replace the following CMD command with a Powershell command:
Icacls.exe "%SystemDrive%\xxx" /grant *S-X-X-XX-XXX:(CI)(OI)(F) /t /c
I also know how to do this with Icacls, but I think there is a nicer way to do it with the PowerShell.
I would be happy if someone could help me in this regard. :-)
Thanks.
The built-in help files, provide you the guidance for this.
Set-Acl Changes the security descriptor of a specified item, such
as a file or a registry key.
# Get specifics for a module, cmdlet, or function
(Get-Command -Name Get-Acl).Parameters
(Get-Command -Name Get-Acl).Parameters.Keys
<#
# Results
Path
InputObject
LiteralPath
Audit
AllCentralAccessPolicies
Filter
Include
Exclude
...
#>
Get-help -Name Get-Acl -Examples
<#
# Results
Get-Acl C:\Windows
Get-Acl -Path "C:\Windows\k*.log" |
Format-List -Property PSPath, Sddl
Get-Acl -Path "C:/Windows/k*.log" -Audit |
ForEach-Object { $_.Audit.Count }
Get-Acl -Path "HKLM:\System\CurrentControlSet\Control" |
Format-List
Get-Acl -InputObject (Get-StorageSubsystem -Name S087)
#>
Get-help -Name Get-Acl -Full
Get-help -Name Get-Acl -Online
(Get-Command -Name Set-Acl).Parameters
(Get-Command -Name Set-Acl).Parameters.Keys
<#
# Results
Path
InputObject
LiteralPath
AclObject
CentralAccessPolicy
ClearCentralAccessPolicy
Passthru
Filter
Include
Exclude
...
#>
Get-help -Name Set-Acl -Examples
<#
# Results
$DogACL = Get-Acl -Path "C:\Dog.txt"
Set-Acl -Path "C:\Cat.txt" -AclObject $DogACL
Get-Acl -Path "C:\Dog.txt" |
Set-Acl -Path "C:\Cat.txt"
$NewAcl = Get-Acl File0.txt
Get-ChildItem -Path "C:\temp" -Recurse -Include "*.txt" -Force |
Set-Acl -AclObject $NewAcl
#>
Get-help -Name Set-Acl -Full
Get-help -Name Set-Acl -Online
There are other modules via the Microsoft PowerShellGallery.com for you to leverage as well.
Find-Module -Name '*acl*', '*ntfs*' |
Format-Table -AutoSize
<#
# Results
Version Name Repository Description
------- ---- ---------- -----------
1.0.1 ACL-Permissions PSGallery A couple of ACL utilities, for repairing c...
1.30.1.28 ACLReportTools PSGallery Provides Cmdlets for reporting on Share ACLs.
1.7 ACLHelpers PSGallery Modules to help work with ACLs (Access Control Rights)
1.0.1.0 ACLCleanup PSGallery A set of tools to help you clean your files...
0.1.2 ACLTools PSGallery Module for managing NTFS Acls on files and folders
...
0.4 FileAclTools PSGallery Tools for quickly fixing file system ACLs
...
4.2.6 NTFSSecurity PSGallery Windows PowerShell Module for managing file ...
1.4.1 cNtfsAccessControl PSGallery The cNtfsAccessControl module contains DSC re...
1.0 NTFSPermissionMigration PSGallery This module is used as a wrapper to the popular ...
#>
So, for what you are showing
# Review current settings
Get-Acl -Path $env:SystemDrive |
Format-List -Force
<#
# Results
Path : Microsoft.PowerShell.Core\FileSystem::C:\Windows\system32
Owner : NT SERVICE\TrustedInstaller
Group : NT SERVICE\TrustedInstaller
Access : CREATOR OWNER Allow 268435456
NT AUTHORITY\SYSTEM Allow 268435456
NT AUTHORITY\SYSTEM Allow Modify, Synchronize
BUILTIN\Administrators Allow 268435456
BUILTIN\Administrators Allow Modify, Synchronize
BUILTIN\Users Allow -1610612736
BUILTIN\Users Allow ReadAndExecute, Synchronize
NT SERVICE\TrustedInstaller Allow 268435456
NT SERVICE\TrustedInstaller Allow FullControl
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow ReadAndExecute, Synchronize
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow -1610612736
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES Allow ReadAndExecute, Synchronize
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES Allow -1610612736
Audit :
Sddl : O:S-1-5-80-956008885-34...
#>
Description
The Set-Acl cmdlet changes the security descriptor of a specified
item, such as a file or a registry key, to match the values in a
security descriptor that you supply.
To use Set-Acl, use the Path or InputObject parameter to identify the
item whose security descriptor you want to change. Then, use the
AclObject or SecurityDescriptor parameters to supply a security
descriptor that has the values you want to apply. Set-Acl applies the
security descriptor that is supplied. It uses the value of the
AclObject parameter as a model and changes the values in the item's
security descriptor to match the values in the AclObject parameter.
Parameters
-AclObject Specifies an ACL with the desired property values. Set-Acl changes the ACL of item specified by the Path or InputObject parameter
to match the values in the specified security object.
You can save the output of a Get-Acl command in a variable and then
use the AclObject parameter to pass the variable, or type a Get-Acl
command.
TABLE 1 Type: Object
Position: 1 Default value: None Accept
pipeline input: True (ByValue) Accept wildcard characters: False
So, you just do something like this... as per the above examples
$AclSettings = 'WhatEverSettingsYouWant'
Set-Acl -Path $env:SystemDrive -AclObject $AclSettings
A similar question on StackOverflow is here:
Setting Inheritance and Propagation flags with set-acl and
Powershell
Then there is this guidance:
Here's the MSDN page describing the flags and what is the result of
their various combinations.
https://msdn.microsoft.com/en-us/library/ms229747(v=vs.100).aspx
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit
PropagationFlags.None
Here's some succinct PowerShell code to apply new permissions to a
folder by modifying its existing ACL (Access Control List).
# Get the ACL for an existing folder
$existingAcl = Get-Acl -Path 'C:\DemoFolder'
# Set the permissions that you want to apply to the folder
$permissions = $env:username, 'Read,Modify', 'ContainerInherit,ObjectInherit', 'None', 'Allow'
# Create a new FileSystemAccessRule object
$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permissions
# Modify the existing ACL to include the new rule
$existingAcl.SetAccessRule($rule)
# Apply the modified access rule to the folder
$existingAcl | Set-Acl -Path 'C:\DemoFolder'
<#
Each of the values in the $permissions variable list pertain to the parameters of this constructor for the FileSystemAccessRule class.
#>

powershell add user permission to a folder in windows server

So I've got the next path: C:\folder1\folder2\fileName. Looking in the security tab on the C:\folder1 there is Alice username with full permissions. But going to the C:\folder1\folder2\fileName Alice isn't there yet. How can I insert with powershell v2 Alice member recursively in C:\folder1 so that all the files under root C:\folder1 will also have the same Alice username set with full permissions.
I've tried:
$acl = Get-Acl C:\folder1
$permission = "domain\Alice","FullControl","Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$acl | Set-Acl C:\folder1
But it doesn't seem to apply for the C:\folder1\folder1\fileName. Guess I'm trying to apply permissions for Alice, which doesn't exist yet in the last fileName item.
As you can see in the FileSystemAccessRule documentation, the class has a property for inheritance.
You have to add the property to your $permission
$permission = "domain\Alice",
"FullControl",
[System.Security.AccessControl.InheritanceFlags]"ContainerInherit",
[system.security.accesscontrol.PropagationFlags]"None",
"Allow"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
You could also recursively add the permissions by getting all child items with the Get-ChildItems cmdlet and piping them to the Set-Acl cmdlet like they have done in an examle in the documentation on microsoft site here: Set-Acl. Look at "Example 3: Apply a security descriptor to multiple files" or read below (copied from the page):
PS C:\> $NewAcl = Get-Acl File0.txt
PS C:\> Get-ChildItem -Path "C:\temp" -Recurse -Include "*.txt" -Force | Set-Acl - AclObject $NewAcl
These commands apply the security descriptors in the File0.txt file to all text files in the C:\Temp directory and all of its subdirectories.
The first command gets the security descriptor of the File0.txt file in the current directory and uses the assignment operator (=) to store it in the $NewACL variable.
The first command in the pipeline uses the Get-ChildItem cmdlet to get all of the text files in the C:\Temp directory. The Recurse parameter extends the command to all subdirectories of C:\temp. The Include parameter limits the files retrieved to those with the ".txt" file name extension. The Force parameter gets hidden files, which would otherwise be excluded. (You cannot use "c:\temp*.txt", because the -Recurse parameter works on directories, not on files.)
The pipeline operator (|) sends the objects representing the retrieved files to the Set-Acl cmdlet, which applies the security descriptor in the AclObject parameter to all of the files in the pipeline.
In practice, it is best to use the Whatif parameter with all Set-Acl commands that can affect more than one item. In this case, the second command in the pipeline would be "Set-Acl -AclObject $NewAcl -WhatIf". This command lists the files that would be affected by the command. After reviewing the result, you can run the command again without the Whatif parameter.
This is an example using ".txt" files but can be modified to apply to directories as well.

How to export shared folder with permissions and groups associated

I'm working on a windows server 2008 r2 and I'm trying to export the configuration of shared folder with all the groups associated to them,permissions and file system permissions.
is there a way to do that?
maybe with powershell?
#edit: another problem is that I need to do that after a reboot, so I have to save the configuration in a file for example and then reimport it.
If you want to backup/restore all existing shares you could export/import the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares.
Backup:
reg export HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares shares.reg
Restore:
reg import shares.reg
net stop server && net start server
File/folder ACLs can be saved and restored like this:
Backup:
Get-WmiObject -Class Win32_Share -Filter 'Type = 0' | select -Expand Path | % {
$path = $_
Get-Acl $path | select #{n='Path';e={$path}}, Sddl
} | Export-Csv 'C:\path\to\acls.csv'
Restore:
Import-Csv 'C:\path\to\acls.csv' | % {
$acl = Get-Acl $_.Path
$acl.SetSecurityDescriptorSddlForm($_.Sddl)
Set-Acl -Path $_.Path -AclObject $acl
}
Interesting question, I think the only way to do so is manually getting the acl on original folder and then re-apply them to the copied folder. The cmdlet to be used are Get-Acl -path $youfolder, Copy-Item and Set-Acl
I'm working on a module (see here) that should be able to do this for you. It's a script module, so you can actually open it up and look at/modify the code. If you use it, you could do something like this (the Export-Csv call is commented out, but you can put it in after confirming this is the output you're looking for):
Get-WmiObject Win32_Share -ComputerName ServerName |
Get-AccessControlEntry #| Export-Csv -Path CsvLocation.csv
You'll get errors for built-in system shares, e.g., C$, so you may want to add an -ErrorAction SilentlyContinue and/or an -ErrorVariable to the Get-AccessControlEntry call.
To bring the permissions back in, you'd just feed the Get-AccessControl output into Add-AccessControlEntry:
Import-Csv -Path CsvLocation.csv | Add-AccessControlEntry -WhatIf
Add-AccessControlEntry prompts for confirmation by default. Use the -Force switch to suppress the prompts.
Changing this to work for the NTFS permissions is very easy, too. Just change the Get-WmiObject call into a Get-ChildItem call, and everything else should be the same.

How to remove an User from a file, using Cywin or Powershell

Thank you very much in advance for helping.
So I have hundreds of files and folders from which I'd like to remove the user: C850-108.
I can do this using Windows interface, but it'd take me days to do it in every file.
The reason I'd like to do this is because Cobian Backup tool can't have access to this files (Permission denied) and I think that user is the problem.
So I have Cygwin (bash) an PowerShell to help me in this tedious task.
I attach 3 screenshots:
Windows Security tab
PowerShell output of the command get-acl | format-list
Cygwin output of getfacl
I'm more experienced with bash, so I tried adding an user like this:
setfacl.exe -m u:rafaelgp:rwx myfile
Which apparently did nothing, but when I check with PowerShell, I saw that it actually worked and added a new user (rafaelgp) with the specified permissions. You can see this in the screenshots. So after this I lost some trust in Cygwin.
I've also tried deleting the user like this:
setfacl.exe -d u:C850-108 myfile
But I get the following message:
setfacl: illegal acl entries
So what can I do? As I said, I'm happy trying anything using bash or PowerShell.
Cheers!
UPDATE:
Screenshot of Musaab Al-Okaidi solution. There seems to be a problem with the '$file' parameter
The simplest way would arguably be icacls:
icacls file /remove C850-180
You can't remove permissions that were inherited from the parent folder with this, though. I suspect that this is the reason why setfacl failed. Unfortunately the inheritance information is suppressed when you pipe the output of Get-Acl into Format-List. Try this instead:
Get-Acl file | % { $_.Access } | ? { $_.IdentityReference -match 'C850-180' }
The IsInherited property will show you whether or not the ACL is inherited. If the ACL is inherited, you have to disable inheritance first before you can remove an ACL:
icacls file /inheritance:d
icacls is available since Windows Server 2003 SP2.
Update:
You can apply this recursively to a folder tree by adding the option /t:
icacls C:\some\folder\* /t /inheritance:d
icacls C:\some\folder\* /t /remove C850-180
Be advised, though, that it's not a good idea to recursively disable inheritance as it will make managing permissions a nightmare. Depending on your folder structure it might be better to simply remove inheritance and that particular ACE from the parent folder:
icacls C:\some\folder /inheritance:d
icacls C:\some\folder /remove C850-180
The subfolders and files will automatically inherit their parent folder's changed permissions. If necessary you can enforce that by resetting permissions on subfolders and files:
icacls C:\some\folder\* /reset /t /c
Add the following function to your shell, simply copy and paste, then you will have Remove-UserAccess as a usable Cmdlet
Function Remove-UserAccess()
{
Param
(
[Parameter(Mandatory=$true)][String]$Path,
[Parameter(Mandatory=$true)][String]$User
)
$Files = New-Object System.Collections.ArrayList
$Files.Add($Path) | Out-Null
#Add all files and folders to an array
$PathSubtree = Get-ChildItem -Path $Path -Recurse
Foreach ( $File in $PathSubtree )
{
$Files.Add($File.FullName) | Out-Null
}
# Remove access of the $User from each file in the array
Foreach ( $File in $Files )
{
$AccessRule = Get-Acl $File | % { $_.Access } | ? { $_.IdentityReference -eq $User}
IF ( $AccessRule -eq $null )
{
Write-Host "$User does not have access to $File" -ForegroundColor Yellow
}
ELSE
{
$ACL = Get-Acl $File
$ACL.RemoveAccessRule($AccessRule) | out-Null
Set-Acl -Path $File -AclObject $ACL -ErrorAction Stop
Write-Host "Permissions for $user have been removed from the following path: $File" -ForegroundColor Green
}
}
}
Execute the command as follows:
Remove-UserAccess -Path C:\temp -User RAFALAPTOP\C850-108
This will remove the access for the user from C:\temp and all sub-files and folders.