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.
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:
Enable-PSRemoting
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.
Testing
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 += @{ Name="Set-WebConfigurationProperty"; Parameters = @{Name='pspath'; ValidatePattern="MACHINE\/WEBROOT\/APPHOST\/MySite"}, @{Name='filter'; ValidatePattern="system.webServer\/urlCompression"}, @{Name='Name'; ValidatePattern="doStaticCompression"}, @{Name='Value'; ValidatePattern="True|False"}, }