Manage IIS as a non admin user

16 December 2019

I always try to do as many things as possible as a normal user, but fully managing IIS was always restricted to administrators. Calling any Web-Administration APIs requires your user to be a member of the administrators group.

One workaround was to change the NTFS permissions on ApplicationHost.config file and edit it directly, but I wouldn't recommend this, especially not on a production server.


If you like to use the IIS GUI managment tools, you are still out of luck. But if you are happy to use PowerShell cmdlets to manage IIS, I will describe here how to do that as a non-administrator.

To pull off this trick we are gonna use JEA, or PowerShell Just Enough Administration, you need PowerShell 5.0 or higher which is available for all supported Windows versions (Server 2008 R2 and higher, but also Windows 7+).

If you don't know what JEA is, in a nutshell it uses PowerShell Remoting and a set of rules to allow normal users to perform actions that are normally limited to administrators. In the background, a virtual administrator account is executing those actions, but the rules define very precisely what these actions are.

We are going through all the steps needed to make this work. I assume a single local machine with Windows 10.

For all the setup work here, you need a PowerShell console started as an elevated administrator.

WARNING: If you are following the instructions in this post, not only are you giving a normal user full access to IIS management, you also allow a smart user to completely take over your machine. Read the follow up post: Too much administration via JEA and IIS on how this is possible and the last section of this post.

Installing IIS

For our purpose we need a basic IIS install, but we need the PowerShell IIS cmdlets. You can learn more about different ways for installing Windows features on the command line.

Enable-WindowsOptionalFeature -Online -FeatureName "IIS-WebServerRole"
Enable-WindowsOptionalFeature -Online -FeatureName "IIS-ManagementScriptingTools"

Enable Remoting

On server, PowerShell Remoting is usually enabled by default, on a workstation OS run:


Creating a Windows group and user

To test our setup, we are creating a new Windows group and a normal user who is a member of this group.

New-LocalGroup -Name "IIS-Webmasters"
$Password = Read-Host -AsSecureString -Prompt "Enter a password for the user"
New-LocalUser "iisManager" -Password $Password -FullName "IIS Manager" -Description "User to manage IIS"
Add-LocalGroupMember -Group "users" -Member "iisManager"
Add-LocalGroupMember -Group "IIS-Webmasters" -Member "iisManager"

Creating a PowerShell Module with rules

This part is the meat of this task. To define rules for JEA, we need to create a PowerShell module.

We create a PowerShell module and related files. The location has to be under a directory listed in $env:PsModulePath, and should also not be write-able to any normal users, otherwise they could change the rules.

Run the following commands:

$moduleName = "IISJea"
$groupName = "IIS-Webmasters"

$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\$moduleName" $manifestFile = Join-Path -Path $modulePath -ChildPath "$moduleName.psd1" $roleDir = Join-Path -Path $modulePath -ChildPath "RoleCapabilities" $roleFile = "$roleDir\$($moduleName).psrc" $SessionFile = Join-Path -Path $modulePath -ChildPath "$moduleName.pssc"

$cmdlets = 'WebAdministration*','Get-IISSite','Start-IISSite','Stop-IISSite','Get-IISAppPool','Get-ChildItem','Set-Location' $aliases = "ls","cd" $providers = 'WebAdministration','Variable'

New-Item -ItemType Directory -Path $modulePath New-Item -ItemType Directory -Path $roleDir New-Item -ItemType File -Path (Join-Path $modulePath -ChildPath "$moduleName.psm1") New-ModuleManifest -Path "$manifestFile" -RootModule "$moduleName.psm1" New-PSRoleCapabilityFile -VisibleCmdlets $cmdlets -VisibleAliases $aliases -VisibleProviders $providers -Path "$roleFile" New-PSSessionConfigurationFile -SessionType RestrictedRemoteServer -RunAsVirtualAccount -RoleDefinitions @{"$groupName" = @{ RoleCapabilities ="$moduleName"}} -Path $SessionFile Register-PSSessionConfiguration -Path $SessionFile -Name $moduleName -Force

We created all required configuration files and registered an JEA endpoint.


Now we can test our configuration, this should be done from a non-admin PowerShell session:

$cred = Get-Credential -Credential iisManager
Enter-PSSession -ComputerName localhost -Credential $cred -ConfigurationName IISJea

if everything works, a new prompt should appear and we can manage IIS:

[localhost]: PS> Get-ChildItem -Path iis:\sites
[localhost]: PS> Stop-WebSite -Name "Default Web Site"
[localhost]: PS> Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/Default Web Site'  -filter "system.webServer/defaultDocument/files" -name "." -value @{value='foo.html'}

but we can only manage IIS, nothing else, not even things we could normally do:

[localhost]: PS> cd C:
[localhost]: PS> Get-Process

all fail because the provider or the command is not allowed in this session.

Changing things

When we want to make changes to our configuration, we first need to unregister the JEA endpoint:

Unregister-PSSessionConfiguration IISJea

Now we can edit the configuration files, all related files are in:

C:\Program Files\WindowsPowerShell\Modules\IISJea

Edit IISJea.pssc to change who can use the endpoint, you need to change the RoleDefinitions.

Edit RoleCapabilities\IISJea.psrc to change what the user can do.

For example, what if your user should not only be able to restart ApplicationPools but the whole IIS service.

You need to edit the VisibleCmdlets value in IISJea.psrc, at the end of the line add:

, @{Name = "Restart-Service"; Parameters = @{Name="Name"; ValidateSet="WAS"},@{Name="Force"}}

Here we are telling JEA to allow the user to restart a service, but only one, in this case the Windows Process Activation Service which is part of IIS and the one we want to restart. We also need to allow the -force parameter, because WAS has depending services that need to restart as well. No other services can be changed by the user.

When done with editing, we need to register the endpoint again:

Register-PSSessionConfiguration -Name IISJea -Force -Path "$($env:ProgramFiles)\WindowsPowerShell\Modules\IISJea\IISJea.pssc"

For more details check the Microsoft documentation

Removing the whole thing

After the test you should clean up, we unregister the endpoint and delete all files:

Unregister-PSSessionConfiguration -Name IISJea 
Get-ChildItem -Path "$($env:ProgramFiles)\WindowsPowerShell\Modules\" -Filter "IISJea" -Recurse | Remove-Item -Force -Recurse

Be very, very careful!

As mentioned in the warning above, using $cmdlets = 'WebAdministration\*' is very dangerous, as it allows an experienced user to completely take over your machine. So never use it.

Instead determine what exactly it is your non-admin user has to do with IIS. Ideally only grant access to Read-only (Get-*) cmdlets.

Set-WebConfigurationProperty is very dangerous because it allows users to change any settings and therefor use the same hack described in Too much administration via JEA and IIS.

If you really need to allow changes, be very specific about what a user can do: like this:

$cmdlets += @{
    Parameters = @{Name='pspath'; ValidatePattern="MACHINE\/WEBROOT\/APPHOST\/MySite"},
                 @{Name='filter'; ValidatePattern="system.webServer\/urlCompression"},
                 @{Name='Name'; ValidatePattern="doStaticCompression"},
                 @{Name='Value'; ValidatePattern="True|False"},

Tags: IIS | IT Pro | Web | Windows

Pages in this section


ASP.Net | Community | Development | IIS | IT Pro | Security | SQL (Server) | Tools | Web | Work on the road | Windows