How can I add ACL permissions for IIS APPPOOL\* accounts via Powershell?

Solution 1:

First of all, use Set-Acl like this, as the directory path is the first positional argument:

Set-Acl $directory $acl

Second, you should create the user object with only one argument:

$user = New-Object System.Security.Principal.NTAccount("$domain\\$username")

UPDATE: Seems that it won't accept the "IIS APPPOOL\AppPoolName" as an NTAccount identifier. Now, there are two ways to accomplish what you are trying to do:

  1. Create a new SID object with the AppPoolIdentities SID and translate it into an NTAccount, like this: http://iformattable.blogspot.com/2007/12/convert-sid-to-ntaccount-with.html, and you should be able to treat it like any other NTAccount object. If you still want to be able to pass domain/usernames for real accounts, built in some simple logic that defaults to the AppPool SID if username is "AweSomeAppPool" and domain is empty, just as an example.

  2. Use PowerShell to invoke icacls.exe, and use it to grant/revoke whatever permissions you want, like this (first normal icacls form command prompt, then powershell, notice the difference):

    icacls.exe test.txt /grant "IIS AppPool\DefaultAppPool":(OI)(CI)M

    cmd /c icacls test.txt /grant "IIS AppPool\DefaultAppPool:(OI)(CI)M"

If you go for the second option, be sure to test them manually first, i haven't had a chance to test these specific examples myself, but it should work

Solution 2:

Something like this should do the trick for you. It should be able to resolve IIS APPPOOl\Anything as well...

function Set-AclOnPath
{
    param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string] $Path,

        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string] $DomainAccount
    )

    #Put whatever permission you want here
    $permission = $DomainAccount,"ReadAndExecute","Allow"
    $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission

    $acl = Get-Acl $Path
    $acl.SetAccessRule($accessRule)
    $acl | Set-Acl $Path
}

Solution 3:

The following works in Windows 2012 to get a SID for the IIS site. It requires the IIS Provider which uses the WebAdministration powershell module, but this article indicates it will work on Windows 2008R2.

$appPoolName = 'MyAppPool'
$appPoolSid = (Get-ItemProperty IIS:\AppPools\$appPool).applicationPoolSid
$identifier = New-Object System.Security.Principal.SecurityIdentifier $appPoolSid
$user = $identifier.Translate([System.Security.Principal.NTAccount])

Solution 4:

The following worked for me in Windows 2012, couldn't get the other examples working:

Import-Module WebAdministration

$appPoolName='MyAppPool'
$folderDirectory='C:\MyWebFolder'

$appPoolSid = (Get-ItemProperty IIS:\AppPools\$appPoolName).applicationPoolSid

Write-Output "App Pool User $appPoolSid"

$identifier = New-Object System.Security.Principal.SecurityIdentifier $appPoolSid
$user = $identifier.Translate([System.Security.Principal.NTAccount])

Write-Output "Translated User $user.Value"

$acl = Get-Acl $folderDirectory
$acl.SetAccessRuleProtection($True, $False)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($user, "FullControl", "ContainerInherit", ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$acl | set-acl -path $folderDirectory

Solution 5:

As of IIS 10/Windows 10/Server 2016, the WebAdministration module is deprecated and we're expected to use the new IISAdministration Powershell module instead. Here's how to get the application pool SID translated to the virtual user using the new module:

Import-Module IISAdministration
$manager = Get-IISServerManager
$appPoolName = 'MyAppPool'
$appPoolSid = $manager.ApplicationPools["$appPoolName"].RawAttributes['applicationPoolSid']
$identifier = New-Object System.Security.Principal.SecurityIdentifier $appPoolSid
$user = $identifier.Translate([System.Security.Principal.NTAccount])