powershellpermissionswindows-server-2012network-share

Setting network share permissions on subdirectory with PowerShell


I want to setup a network share granting READ only permissions to the root, but READ/WRITE permissions to a sub directory within it.

I can do this manually, but I want to be able to do it using PowerShell.

\\myserver\MyShare           (READ access here for user TESTUSER)
\\myserver\MyShare\subfolder (READ/WRITE access here for user TESTUSER)

Manual steps in Windows Explorer - open folder properties dialog, "Sharing" tab, "Share..." button, I can then add my user and set the permissions. I can do this to BOTH the root of the network share and the "subfolder".

The closest thing I have managed in PowerShell is the following, which sets up the root only:

New-SmbShare –Name MyShare –Path e:\MyShare -ReadAccess "Domain\TESTUSER"

However, this seems to do the equivalent of the "Advanced sharing" options that appear on the folder properties dialog, which only apply when setting up a NEW network share, and not to folders WITHIN an existing network share. When I run this script, the TESTUSER isn't added to the list of users in the simple "Share..." dialog so there must be another way of setting up the permissions.

My question: How do I setup permissions using PowerShell in the same way Windows does from the "Share..." button on the folder properties?

I'm using Windows Server 2012 R2.


Solution

  • Share permissions apply to shares as a whole, meaning they affect the shared folder and everything it contains. It's not possible to apply different share permissions to a subfolder without publishing that subfolder as a different share, and even then the modified permissions would only become effective when accessing the subfolder through the new share, not when accessing it as a subfolder of the original share.

    For fine-grained access control you MUST use filesystem ACLs. However, if the share is defined as read-only via share permissions, the user will be denied write access even if the filesystem ACLs would allow it.

    Because of these limitations it's common practice to set share permissions to full control for everyone and do the entire permission handling on the filesystem level. The simplest way of setting file ACLs is still the icacls command:

    icacls C:\path\to\shared_folder /grant "DOMAIN\testuser:(CI)(OI)RX"
    icacls C:\path\to\shared_folder\subfolder /grant "DOMAIN\testuser:(CI)(OI)M"
    

    You could also use Set-Acl to the same end, but it'd require more code:

    function New-Ace($user, $permission) {
        New-Object Security.AccessControl.FileSystemAccessRule $user, $permission, 'ContainerInherit, ObjectInherit', 'None', 'Allow'
    }
    
    $acl = Get-Acl -LiteralPath 'C:\path\to\shared_folder'
    $acl.AddAccessRule((New-Ace 'DOMAIN\testuser' 'ReadOrExecute')
    Set-Acl -AclObject $acl -LiteralPath 'C:\path\to\shared_folder'
    
    $acl = Get-Acl -LiteralPath 'C:\path\to\shared_folder\subfolder'
    $acl.AddAccessRule((New-Ace 'DOMAIN\testuser' 'Modify'))
    Set-Acl -AclObject $acl -LiteralPath 'C:\path\to\shared_folder\subfolder'
    

    By enabling access-based enumeration you can make sure users will only see those folders and files they actually have access to (avoiding confusion from trying to access an object only to get an "access denied" error).