How to Grant Modify Permissions to IIS APPPOOL Accounts Using PowerShell


2 views

When configuring permissions for IIS application pools, many administrators encounter issues with the special IIS APPPOOL\ account prefix. Unlike domain accounts, these local virtual accounts require specific handling in PowerShell ACL operations.

The error you're seeing occurs because IIS APPPOOL isn't a traditional domain or local machine reference. The correct approach is to use the local computer name (or just the account name with the IIS APPPOOL\ prefix) when constructing the NTAccount object.

Here's the corrected function that properly handles IIS application pool identities:

function Set-IISAppPoolPermission {
    param (
        [Parameter(Mandatory=$true)]
        [string]$Directory,
        
        [Parameter(Mandatory=$true)]
        [string]$AppPoolName,
        
        [string]$Permission = "Modify"
    )
    
    $inherit = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
    $propagation = [System.Security.AccessControl.PropagationFlags]"None"
    $acl = Get-Acl -Path $Directory
    
    # Correct way to reference IIS AppPool accounts
    $account = New-Object System.Security.Principal.NTAccount("IIS APPPOOL\$AppPoolName")
    
    $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
        $account,
        $Permission,
        $inherit,
        $propagation,
        "Allow"
    )
    
    $acl.AddAccessRule($accessRule)
    Set-Acl -Path $Directory -AclObject $acl
}

# Example usage:
Set-IISAppPoolPermission -Directory "C:\Websites\MySite" -AppPoolName "MyAppPool"

After running the script, you can verify the permissions were applied correctly with:

Get-Acl "C:\Websites\MySite" | Format-List
  • For IIS 10.0 or later, application pools run as virtual accounts by default
  • The account must include the full IIS APPPOOL\ prefix
  • If running remotely, you may need to use the computer name (e.g., SERVER01\IIS APPPOOL\MyAppPool)
  • Always test with the least privileged permissions first

For those who prefer command-line tools, icacls provides another option:

icacls "C:\Websites\MySite" /grant "IIS APPPOOL\MyAppPool:(OI)(CI)M"

This grants Modify (M) permissions with Object Inherit (OI) and Container Inherit (CI) flags.

When implementing this in production:

  • Consider using a dedicated application pool identity
  • Restrict permissions to only necessary directories
  • Document all permission changes
  • Include these commands in your deployment scripts

When automating permissions for IIS websites, many administrators encounter the same frustrating error:

Set-Acl : The trust relationship between this workstation and the primary domain failed

This occurs because IIS application pool identities aren't traditional domain accounts. They're virtual accounts with a special naming convention that Windows manages differently.

IIS application pool identities follow this pattern:

IIS APPPOOL\AppPoolName

The key insight: IIS APPPOOL isn't a domain but rather a special virtual account namespace. PowerShell's security provider needs to handle these differently than regular domain accounts.

Here's the proper way to modify your function:

function Set-AppPoolPermission {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Directory,
        
        [Parameter(Mandatory=$true)]
        [string]$AppPoolName
    )

    $inherit = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
    $propagation = [System.Security.AccessControl.PropagationFlags]"None"
    $acl = Get-Acl $Directory
    
    # The critical change is using the full account name format
    $accountName = "IIS APPPOOL\$AppPoolName"
    $user = New-Object System.Security.Principal.NTAccount($accountName)
    
    $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
        $user,
        "Modify",
        $inherit,
        $propagation,
        "Allow"
    )
    
    $acl.AddAccessRule($accessRule)
    Set-Acl -Path $Directory -AclObject $acl
}

Grant modify permissions to DefaultAppPool:

Set-AppPoolPermission -Directory "C:\WebSites\MySite" -AppPoolName "DefaultAppPool"

For multiple directories:

$directories = @("C:\WebSites\Site1", "C:\WebSites\Site2", "D:\WebApps\Store")
foreach ($dir in $directories) {
    Set-AppPoolPermission -Directory $dir -AppPoolName "ECommerceAppPool"
}

For environments with strict security requirements, you might need to:
1. First verify the application pool exists
2. Handle potential permission inheritance issues
3. Add logging for audit trails

Here's an enhanced version with error handling:

function Set-AppPoolPermissionAdvanced {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Directory,
        
        [Parameter(Mandatory=$true)]
        [string]$AppPoolName,
        
        [Parameter(Mandatory=$false)]
        [string]$LogPath = "C:\Logs\PermissionChanges.log"
    )

    try {
        if (-not (Test-Path $Directory)) {
            throw "Directory $Directory does not exist"
        }

        $acl = Get-Acl $Directory
        $accountName = "IIS APPPOOL\$AppPoolName"
        
        $user = New-Object System.Security.Principal.NTAccount($accountName)
        $sid = $user.Translate([System.Security.Principal.SecurityIdentifier])
        
        $inherit = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
        $propagation = [System.Security.AccessControl.PropagationFlags]"None"
        
        $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
            $user,
            "Modify",
            $inherit,
            $propagation,
            "Allow"
        )
        
        $acl.AddAccessRule($accessRule)
        Set-Acl -Path $Directory -AclObject $acl
        
        "$(Get-Date) - Successfully granted modify permissions to $accountName on $Directory" | Out-File $LogPath -Append
    }
    catch {
        "$(Get-Date) - ERROR: $_" | Out-File $LogPath -Append
        throw
    }
}