Remote Administration With PowerShell 3.0 Sessions–Part 2: Limited User, Power User and Administrator Groups

In my last post we talked about PowerShell Session Configurations  and specifically about the new RunAs functionality in PowerShell 3.0.  But there’s some other incredibly cool and powerful functionality within session configurations – Session Configuration Files.  You can see the full beta documentation on Session Configuration Files on TechNet but I am going to focus on a few specific features.

ModulesToImport and VisibleCmdlets

When you create a new PSSessionConfiguration file you can specify what modules to import and more specifically what cmdlets, aliases, types etc… will be visible to the user.  Using this functionality we can create PSSessions that will only allow specific users to do very specific actions such as starting or stopping a VM.  In the example below I create a configuration that will only allow users to use the Get-VM* cmdlet along with Start-VM and Stop-VM.
New-PSSessionConfigurationFile -Path C:\psSessions\HyperVRemoteLimitedUser.pssc `
-SessionType RestrictedRemoteServer `
-LanguageMode RestrictedLanguage `
-ModulesToImport Hyper-V `
-VisibleCmdlets @("Get-VM*", "Start-VM", "Stop-VM") `

Register-PSSessionConfiguration -Name "HyperVRemoteLimitedUser" `
-Path C:\psSessions\HyperVRemoteLimitedUser.pssc `
-SessionType DefaultRemoteShell -AccessMode Remote

When a remote users connects to this session they will only be able to use cmdlet’s meting those specifications…
PS C:\> $session = New-PSSession -ComputerName 37-4611K2615L -ConfigurationName HyperVRemoteLimitedUser
PS C:\> Enter-PSSession $session
[37-4611K2615L]: PS>get-vm

Name State CPUUsage(%) MemoryAssigned(M) MemoryDemand(M) MemoryStatus Uptime Status ReplicationState
---- ----- ----------- ----------------- --------------- ------------ ------ ------ ----------------
Test Off 0 0 0 00:00:00 Operating normally Disabled
Test3 Off 0 0 0 00:00:00 Operating normally Disabled

[37-4611K2615L]: PS>new-vm
The term 'New-VM' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (New-VM:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

[37-4611K2615L]: PS>get-host
The term 'Get-Host' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (Get-Host:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

[37-4611K2615L]: PS>Get-VMSwitch
Name SwitchType NetAdapterInterfaceDescription
---- ---------- ------------------------------
External External Microsoft Network Adapter Multiplexor Driver

Creating Multiple Configurations For Different Users

In my last post I provided a handy script New-SSDLForAdGroup to use with Register-PSSessionConfiguration.  Combining that with PSSessionConfigurationFiles – I’m going to create three different session types depending on the user.

Function New-SSDLForADGroup
{
param(
[String]$GroupName = [String]::Empty
)
try {
#retreave the default SSDL as a base
$defaultSSDL = (Get-Item WsMan:\localhost\service\rootSDDL).Value
$isContainer = $false
$isDS = $false
$SecurityDescriptor = New-Object -TypeName `
Security.AccessControl.CommonSecurityDescriptor `
$isContainer, $isDS, $defaultSSDL

    #remove the default groups (Administrators and Interactive User)
while($SecurityDescriptor.DiscretionaryAcl.Count -gt 0)
{
$ssdl = $SecurityDescriptor.DiscretionaryAcl[0]
$SecurityDescriptor.DiscretionaryAcl.RemoveAccess(
[System.Security.AccessControl.AccessControlType]::Allow,
$ssdl.SecurityIdentifier,
$ssdl.AccessMask,
$ssdl.InheritanceFlags,
$ssdl.PropagationFlags) | Out-Null
}

    #get the SID for the specified Group and add it to the SSDL
$AdminGroup = New-Object Security.Principal.NTAccount $GroupName
$AdminGroupSid = $AdminGroup.Translate(`
[Security.Principal.SecurityIdentifier]).Value

    $SecurityDescriptor.DiscretionaryAcl.AddAccess(
[System.Security.AccessControl.AccessControlType]::Allow,
$AdminGroupSid,
268435456, #full control all operations
[System.Security.AccessControl.InheritanceFlags]::None,
[System.Security.AccessControl.PropagationFlags]::None) | Out-Null

    return $SecurityDescriptor.GetSddlForm("All")
}
catch [Exception] {
Write-Error -Message "Failed To Generate SSDL (review inner exception):`n $_.Message" `
-Exception $_.Exception
}
}

$HyperVRemoteAdminRunAs = Get-Credential "hyper-v\HyperVRemoteCommands"

#Limited Users
$ssdlForSession = New-SSDLForADGroup -GroupName "hyper-v\LimitedUsers"
New-PSSessionConfigurationFile -Path C:\psSessions\HyperVRemoteLimitedUser.pssc `
-SessionType RestrictedRemoteServer `
-LanguageMode RestrictedLanguage `
-ModulesToImport Hyper-V `
-VisibleCmdlets @("Get-VM*", "Start-VM", "Stop-VM") `

    Register-PSSessionConfiguration -Name "HyperVRemoteLimitedUser" `
-Path C:\psSessions\HyperVRemoteLimitedUser.pssc `
-SessionType DefaultRemoteShell -AccessMode Remote `
-NoServiceRestart -Force `
-SecurityDescriptorSddl $ssdlForSession `
-RunAsCredential $HyperVRemoteAdminRunAs

#PowerUsers
#Only use the cmdlet's in the allowed modules
$moduleList = @("Hyper-V")
$cmdLets = $null
foreach ($Module in $moduleList)
{
Import-Module $Module
$Mod = Get-Module $Module
$cmdLets += $Mod.ExportedCmdlets.Keys
}

    $ssdlForSession = New-SSDLForADGroup -GroupName "hyper-v\hv-PowerUsers"
New-PSSessionConfigurationFile -Path C:\psSessions\HyperVRemotePowerUser.pssc `
-SessionType RestrictedRemoteServer `
-LanguageMode RestrictedLanguage `
-ModulesToImport $moduleList `
-VisibleCmdlets ([Array]$cmdLets)

Register-PSSessionConfiguration -Name "HyperVRemotePowerUser" `
-Path C:\psSessions\HyperVRemotePowerUser.pssc `
-SessionType DefaultRemoteShell -AccessMode Remote `
-NoServiceRestart -Force `
-SecurityDescriptorSddl $ssdlForSession `
-RunAsCredential $HyperVRemoteAdminRunAs

#ServerAdmins
$ssdlForSession = New-SSDLForADGroup -GroupName "hyper-v\hv-admins"
Register-PSSessionConfiguration -Name "HyperVServerAdmin" `
-SessionType DefaultRemoteShell -AccessMode Remote `
-NoServiceRestart -Force `
-SecurityDescriptorSddl $ssdlForSession `
-RunAsCredential $HyperVRemoteAdminRunAs

Restart-Service -Name WinRM –Force

Taylor Brown
Hyper-V Enterprise Deployment Team
taylorb@microsoft.com
https://blogs.msdn.com/taylorb

WS08R2-HyperV_v_rgb