Search code examples
powershellbatch-filecommand-linechmodicacls

Using ICACLS to set file permission to 'read-only'


I'm having a heck of a time transferring from the simple, intuitive chmod 400 to trying to do the same thing in Windows Command Prompt using ICACLS. Compared to the sleek, octal representation of UNIX/LINUX's chmod, ICACLS seems a complex nightmare.

I have a SSH .pem key which I'm trying to make read-only. I want to replace the old permissions which are currently on it with this new, read-only permission. The closest I've come to finding an answer is the following:

ICACLS "D:\Folder A\Another Folder\File Name Here.ext" /GRANT:R "DOMAIN\USERNAME":R
(found here: https://www.experts-exchange.com/questions/27624477/What-command-can-give-user-read-only-permission.html)

I believe the :R at the very end allows me to replace the current permissions, which is what I want. But I don't know what to put for the "DOMAIN\USERNAME"segment. Any advice?


Solution

  • Permissions in Unix and Windows work in different ways. In Windows you have inheritance by default and permissions are more granular because you have ACEs (permissions per identity), not just owner/group/other. Permissions for the owner is only given on creation. If you change owner later, you need to manually update ACEs before the owner can modify the file.

    Because of this, you need to know who you want to give permissions to. If you want to only give read permission to the user you are logged on with, you can use $env:username in PowerShell or %USERNAME% in cmd.

    Examples using PowerShell:

    $path = ".\test.txt"
    #Reset to remove explict permissions
    icacls.exe $path /reset
    #Give current user explicit read-permission
    icacls.exe $path /GRANT:R "$($env:USERNAME):(R)"
    #Disable inheritance and remove inherited permissions
    icacls.exe $path /inheritance:r
    

    If you want set it equal to chmod 400, you can check who's the owner and assign permissions to that account. Be aware that this can also be a group like Administrators:

    $path = ".\test.txt"
    icacls.exe $path /reset
    icacls.exe $path /GRANT:R "$((Get-Acl -Path $path).Owner):(R)"
    icacls.exe $path /inheritance:r
    

    Or you can use the built-in cmdlets in PowerShell:

    $path = ".\test.txt"
    
    #Get current ACL to file/folder
    $acl = Get-Acl $path
    
    #Disable inheritance and remove inherited permissions
    $acl.SetAccessRuleProtection($true,$false)
    
    #Remove all explict ACEs
    $acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) }
    
    #Create ACE for owner with read-access. You can replace $acl.Owner with $env:UserName to give permission to current user
    $ace = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $acl.Owner, "Read", "Allow"
    $acl.AddAccessRule($ace)
    
    #Save ACL to file/folder
    Set-Acl -Path $path -AclObject $acl