Chapter 8: Using custom session configurations
“With great power comes great responsibility”, said Uncle Ben.
But some people don’t just understand that. That is when you have to rip-off their powers. Similarly, the default PS Session configuration allows full access to PowerShell language, cmdlets, scripts and everything available to PowerShell. Of course, you need to authenticate as a local administrator or should have execute permission to invoke the session. Running a few cmdlets such as Stop-Service or Restart-Computer can be quite dangerous on a production server. This is where a custom session configuration can help provide role based access to remote host using PowerShell remoting.
We touched upon creating custom session configuration in the previous chapter of this PowerShell remoting guide. In this chapter, we look at how we can extend the concept of custom session configuration to restrict available commands and PowerShell language in a remote session. I will go straight in to the startup script used to implement this since we already looked at how to create custom session configuration and assign permissions to a specific user.
$RequiredCommands = @("Get-Command",
"Get-FormatData",
"Out-Default",
"Select-Object",
"Out-file",
"Measure-Object",
"Exit-PSSession"
)
$ExecutionContext.SessionState.Applications.Clear()
$ExecutionContext.SessionState.Scripts.Clear()
Get-Command -CommandType Cmdlet, alias, function | ?{$RequiredCommands -notcontains $_.Name}
| %{$_.Visibility="Private"}
$ExecutionContext.SessionState.LanguageMode="RestrictedLanguage"
As you see here, we have only a few required commands. We don’t want the remote user to execute commands other than this set. BTW, this set is the absolute minimum required even to start remoting session. So, consider this as a standard required commands list. Towards the end, we set the language mode to restrict to make sure the remote user cannot execute infinite loops, etc that could potentially bring the system down. This script, when used as the startup script for a session, will result in something as shown here.
Figure 10 inside a restricted Session
As you see above, get-Command lists only the commands we have in the Required Commands list. However, if you have a large list of required commands, the method you have seen in the above code is not scalable. Instead, you can use a denied list of commands that is relatively small. For example, if you don’t want your users to execute Stop-Process or Restart-Computer, your code will look like
$DeniedCommands = @("Stop-Process",
"Restart-Computer"
)
$ExecutionContext.SessionState.Applications.Clear()
$ExecutionContext.SessionState.Scripts.Clear()
Get-Command -CommandType Cmdlet, alias, function | ?{$DeniedCommands -contains $_.Name}
| %{$_.Visibility="Private"}
$ExecutionContext.SessionState.LanguageMode="RestrictedLanguage"
So, if you use this code for your startup script, you will see something like this
Figure 11 Inside a restricted session
I prefer the second method.
If you need to extend or modify the behavior of commands in a remote session, you need to create command proxies. You can read more about it @ http://blogs.msdn.com/powershell/archive/2009/01/04/extending-and-or-modifing-commands-withproxies.aspx
What I have shown here is just one way of achieving control in the remote sessions. However, based on your organization needs there could be a better way of doing this. These methods include user role based restrictions, etc as discussed at a PDC’09 session. Do refer to that for more information.