8

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?

Kyle Vassella
  • 2,296
  • 10
  • 32
  • 62
  • If you're not on a domain, there should be no reason not to provide just `%UserName%` or the chosen user's name without the domain\ part. – Compo Apr 10 '17 at 00:39

2 Answers2

33

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
Frode F.
  • 52,376
  • 9
  • 98
  • 114
  • 3
    Thank you. This is still relevant and saved me after quite a bit of searching – Joe Berg Dec 15 '19 at 00:29
  • 2
    great answer, thanks. Typo in the second example where you are not modifying the owner. Line 3 should be `icacls.exe $path /GRANT:R "$((Get-Acl -Path $path).Owner):(R)"` – Dennis Jun 24 '20 at 09:21
  • Worked a treat for me, just typing each command in at the PowerShell prompt. Thank you @frode-f – Paul Pritchard Jun 27 '22 at 10:09
0

Does

attrib +r "D:\Folder A\Another Folder\File Name Here.ext"

do what you want?

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • 1
    I don't think so - I was reading that you're really supposed to use `ICACLS` to change the file permissions and not `attrib` - plus I don't think adding the read attribute will remove the write and execute permissions already on the file. Thank you for trying though! – Kyle Vassella Apr 10 '17 at 00:18