# Constrained PowerShell endpoints - Visible cmdlets, session types, and language modes

In my last post, I discussed the basics of constrained endpoints. Today, we dive a little deeper and examine the three major ways to restrict the features of a PowerShell session: visible cmdlets, session types, and languages modes.

### Michael Pietroforte

Michael Pietroforte is the founder and editor of 4sysops. He is a Microsoft Most Valuable Professional (MVP) with more than 30 years of experience in IT management and system administration.

#### Latest posts by Michael Pietroforte (see all)

These different options correspond to the three parameters -VisibleCmdlets, -SessionType, and -LanguageMode of the New-PSSessionConfigurationFile cmdlet.

## VisibleCmdlets ^

Restricting the visible cmdlets in sessions is the most straightforward way to restrict what users can do with PowerShell. In my previous post, I demonstrated how you can ensure that only cmdlets that begin with the Get verb are available. Even though this limits users to only retrieve information from the corresponding computer, you usually want to prevent standard users from being able to gather data that they don’t really need for their work.

Thus, a better practice is to exactly define what cmdlets are visible for a user or a group. This might cost a little more time. However, in many cases, it is pretty obvious what cmdlets a user needs.

To add a specific list of cmdlets to the session configuration that the user can work with, you can use these commands:

The -VisibleCmdlets parameter expects an array as input. So don’t set the value you pass in quotes. You can then try your session configuration this way:

If you try to run a cmdlet that is not in your list, you will receive an error message telling you that the cmdlet was not recognized.

The Get-ChildItem cmdlet is not available in the session.

If you have help desk staff that just needs to run a script, you can quickly determine all cmdlets used in the script with this command:

This lists all strings in the script text that contain a hyphen. If you want it a bit more reliable, you can run the code below. It will generate an array of the cmdlet names used in the script, which you can then pass to the -VisibleCmdlets parameter directly.

This little program compares all strings in your script that contain a hyphen with the cmdlets that the Get-Command cmdlet finds in your current session. Of course, this can only work if you didn’t use cmdlet aliases in your script. This gives you a good example of why following best practices makes sense.

It is important to note that, despite its name, the -VisibleCmdlets parameter can’t be used to make cmdlets visible that you excluded by the other methods described below. Perhaps a better name for the parameter would have been “-SoleCmdlets.” However, you can use the -VisibleCmdlets parameter to further restrict the visible cmdlets in session configurations that you constrained by other means.

## SessionType ^

Another way to restrict the available cmdlets in a session is through the -SessionType parameter. The New-PSSessionConfigurationFile cmdlet knows three session types: Default, Empty, and RestrictedRemoteServer.

An empty session is literally empty. It doesn’t contain any cmdlets or language elements. You have to add anything you need in the session configuration yourself. Unfortunately, you can’t add single cmdlets through a session configuration file to an empty session. You have to first add a PowerShell module or snap-in and then remove unwanted cmdlets with the help of the -VisibleCmdlets parameter:

The only available cmdlet session in the session would be Get-ADUser:

This commands works, whereas the next one will produce an error message:

To test whether language elements such as operators are available, you can try the following example:

This command will produce the error message: The syntax is not supported by this runspace. However, if you replace line one in the example with this next one, you can use the -match operator:

Of course, the examples only work if the ActiveDirectory module is available on the computer.

The session type RestrictedRemoteServer is for sessions where a user has to interactively enter a remote session. Thus far, most of our examples only support PowerShell Remoting through Invoke-Command.

This session type contains seven so-called proxy functions that are required for interactive sessions: Get-Command, Get-FormatData, Select-Object, Get-Help, Measure-Object, Exit-PSSession, and Out-Default. A proxy function is a wrapper function around the original cmdlet that modifies the capabilities of the cmdlet, for example, by adding or removing parameters.

For instance, the Get-Command cmdlet supports the -Verb parameter that allows you to search for cmdlets that begin with a certain verb. The corresponding proxy function in sessions of the type RestrictedRemoteServer doesn’t support this parameter. You also have to know that aliases of the cmdlets are not available. Thus, you can’t exit an interactive session with Exit; only Exit-PSSession will work.

The proxy function Get-Command lacks the -Verb parameter.

As with a session configuration of the type Empty, you have to add all cmdlets you need and also take into account that, by default, no language elements are available. For some reason, you can’t add the PowerShell core modules to those two session types. (At least I didn’t figure out how to do it. Please let me know if you know how.) Thus, the core cmdlets, such as Get-Process or Add-Content, won’t be available in the corresponding sessions.

If you want your users to be able to enter an interactive session where all the core PowerShell cmdlets are available, you have to work with the default session type and use the -VisibleCmdlets parameter to add the above-mentioned seven cmdlets to the session configuration.

The value Default for the -SessionType parameter is somewhat superfluous as it has the same effect as if you omit the parameter altogether. The corresponding session configuration will create full-blown PowerShell sessions.

## LanguageMode ^

The -LanguageMode parameter allows you to determine which PowerShell language elements, such as operators and variables, will be available in a session. The parameter accepts the values FullLanguage, ConstrainedLanguage, NoLanguage, and RestrictedLanguage.

The reason we couldn’t use the -match operator in the session types Empty and RestrictedRemoteServer is because the default value of the -LanguageMode parameter is NoLangugage for these session types. In addition to operators, you also can’t use script blocks and variables in this language mode.

Operators and variables – unavailable in NoLanguage mode

The RestrictedLanguage language mode allows the comparison operators -eq (equal), -gt (greater than) and -lt (less than) and the variables $PSCulture,$PSUICulture, $True,$False, and $Null. The ConstrainedLanguage language mode is only supported on Windows RT, which is more or less dead so I’ll spare you the details. ## Conclusion ^ I only scratched the surface of session configurations in my three posts. Before you implement your own session configurations, you have to carefully test if the users will be able to perform all their tasks. I am afraid that the complexity of PowerShell endpoints will scare off many admins. The result could be that, in many organizations, standard users who need to do tasks in PowerShell are unnecessarily promoted to administrators. Perhaps a simpler solution, such as the sudoers file in Linux, would improve PowerShell’s security. More information about PowerShell session configurations is available here and here. Take part in our competition and win$100!

Articles in series
1. John Thayer Jensen 8 months ago

Michael - I much appreciated your articles.  I am really having trouble enabling non-local-administrators to access the session.  When I try remoting to the machine with the remote session configuration as a local administrator on that machine, it works fine.  When I try as a user in a group to which I have given access (including execute permissions), I get:

New-PSSession : The following error occurred while loading the extended type data file:

Microsoft.PowerShell.Core, C:WindowsSystem32WindowsPowerShellv1.0typesv3.ps1xml: The file was skipped because of

the following validation exception: AuthorizationManager check failed..

that user can't even open the session.

Any ideas??

John Jensen

Applications Specialist

0
2. John Thayer Jensen 8 months ago

What I have done for permissions is to include an Active Directory group called 'BE-Users'.  Here are the permissions on the configuration:

NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, UOA\BE-Users AccessAllowed

And the 'server' (actually a Windows 10 workstation) is itself a member of the same AD domain.

I had read that other article - indeed, all 8 of the articles in that series which helped me a great deal.

May help to explain what this is about, and why I am trying to give them access to a (my!) workstation:

-   I have a WakeOnLAN app - our central ITS networking people won't give us a server that can send WOL packets through the switches but my machine can, of course, wake up other machines on the same VLAN

-   the PSSession configuration has a simple little function in it which takes a MAC address and sends the packet.

-   We have a Microsoft gateway machine that our staff can use to connect to their desktops from outside the University.  However, we are under pressure by Property Services to save power so we want to shut down machines and let staff wake them up remotely if they want to work from home (about 600 staff I think)

-   on a server that all our staff will have access to I have a little three-liner:

New-PSSession -ComputerName bef-4136-d02 -ConfigurationName 'Remote WOL'

Invoke-Command -Session $s -ScriptBlock {do-WOL$args[0]} -ArgumentList $args[0] Remove-PSSession -Session$s

-   this works fine if I connect as a local admin on my workstation.  But if I try to run it as an ordinary user, a member of UOA\BE-Users but not a local admin on the workstation, I get:

New-PSSession : The following error occurred while loading the extended type data file:

Microsoft.PowerShell.Core, C:\Windows\System32\WindowsPowerShell\v1.0\typesv3.ps1xml: The file was skipped because of

the following validation exception: AuthorizationManager check failed..

At C:\Remote WOL\Remote WOL.ps1:1 char:6

+ $s = New-PSSession -ComputerName bef-4136-d02 -ConfigurationName 'Remote WOL' # ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], RemoteExc eption + FullyQualifiedErrorId : PSSessionOpenFailed - If I can get it to start the session I will, no doubt, still have issues running the function - may have to pass in various assemblies (well, it just uses system.net and system.convert), etc. But I can't get it to allow the user to start the session! If you have time to wade through all that, thank you very much for your attention! jj 0 3. John Thayer Jensen 8 months ago Drat! Just saw that I forgot to include the assignment of the session to$s in my code above!  Full code is:

$s = New-PSSession -ComputerName bef-4136-d02 -ConfigurationName 'Remote WOL' Invoke-Command -Session$s -ScriptBlock {do-WOL $args[0]} -ArgumentList$args[0]

Remove-PSSession -Session $s In case you noticed it and said, "well, mate, you forgot to assign the session!!" 🙂 jj 0 4. Michael Pietroforte 8 months ago Did you try to add the AD group to a local group that is allowed to use PowerShell Remoting on the machine (for instance BUILTIN\Remote Management Users) . 0 5. John Thayer Jensen 8 months ago Yes, did try that - also tried creating a local group and adding the AD group to it. At the moment, I have removed UOA\BE-Users from any local group on my machine since it didn't seem to help. jj 0 6. John Thayer Jensen 8 months ago The alternative I have considered is having the remote script run as a service account that is a local admin on my machine. That would work - but it does mean I would have to put the password somewhere. Unfortunately, unlike VB, Powershell doesn't seem to have any way of including an encrypted password in the script. I have thought of a couple of ways, but have to work them out. Anyway, it seems to me as though I shouldn't have to do that. jj 0 7. Michael Pietroforte 8 months ago John, I just tried it now and it worked. I added the AD group Domain Users to the local group Remote Management Users on a Windows 10 machine and then I was able to establish a remote PowerShell session with a standard user from another Windows 10 machine in the domain. In your comment above it appears you removed the group Remote Management Users from the session configuration. With this command you can check which groups are allowed to establish remote PowerShell sessions: (Get-PSSessionConfiguration -Name Microsoft.PowerShell).Permission 0 8. John Thayer Jensen 8 months ago Michael - yes, I know that command. Remember that I am not trying to give them access to one of the standard endpoints. Your command above is for the Microsoft.PowerShell endpoint. I have created my own endpoint, called 'Remote WOL'. When I look at permissions for that, my AD group is claimed to have permission. I run: (Get-PSSessionConfiguration -Name 'Remote WOL').Permission The result is: NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, UOA\BE-Users AccessAllowed It is that group 'UOA\BE-Users' that is supposed to be able to connect to the session. I have been afraid of giving the group access to one of the standard endpoints, for fear of security issues, but I will try that to see if it works. If it does, then there must be something about the endpoint I created that is the problem. OK, I tried giving the group access to the standard 'Microsoft.Powershell' and it claims it has permissions but a user in that group cannot open a session. Permission shows it should: (Get-PSSessionConfiguration 'Microsoft.Powershell').Permission NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAll owed, UOA\BE-Users AccessAllowed This time, instead of the error about the types file, it just says access denied: By the way, I did restart WinRM on the target machine. If I put that user in as a local administrator on the target machine, it works fine. I don't understand what the problem could be. It can't be firewall, because local admins can access it. I do so appreciate your attention to this - alas, I am beginning to fear the problem may be insoluble! jj 0 9. Michael Pietroforte 8 months ago Your permission settings show that you directly added UOA\BE-Users to the endpoint. I wouldn't do that. Instead I would give BUILTIN\Remote Management Users access to the endpoint and then add UOA\BE-Users to BUILTIN\Remote Management Users. 0 10. John Thayer Jensen 8 months ago OK, trying that now. jj 0 11. John Thayer Jensen 8 months ago Still a problem, though with a difference. I put 'UOA\BE-Users' into the BUILTIN\Remote Management Users: net localgroup 'remote management users' Alias name remote management users Members UOA\BE-Users Permissions show as available for both endpoints: (Get-PSSessionConfiguration 'Microsoft.Powershell').Permission NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed (Get-PSSessionConfiguration -Name 'Remote WOL').Permission NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed The difference is now that for *both* endpoints it complains about the types file. I am a bit nervous about changing permissions for that file as when I try, the 'Add' button is greyed out. Users have access. Maybe I should add 'Remote Management Users' to the local Users group? jj 0 12. John Thayer Jensen 8 months ago Oh, of course, I can't add remote management users to users because I can't add a local group to a local group 🙂 And there seems little point in adding uoa\be-users since uoa\domain users is already a member. jj 0 13. John Thayer Jensen 8 months ago Tried giving my test user direct permissions (and adding to local remote management users) - same deal: NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed, UOA\jjen009test AccessAllowed The test user is jjen009test 0 14. John Thayer Jensen 8 months ago Grasping at straws time - I logged in directly to the target machine using the test account to see if it could, in fact, read those types files. It can 🙁 jj 0 15. Michael Pietroforte 8 months ago What is the exact error message you get with this new configuration when you try to establish a remote PowerShell connection? 0 16. John Thayer Jensen 8 months ago (after about a 30-second wait): New-PSSession : The following error occurred while loading the extended type data file: Microsoft.PowerShell.Core, C:\Windows\System32\WindowsPowerShell\v1.0\typesv3.ps1xml: The file was skipped because of the following validation exception: AuthorizationManager check failed.. At line:1 char:6 +$s = New-PSSession -ComputerName bef-4136-d02 -ConfigurationName 'Remote WOL' -C ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], RemoteExc
eption
+ FullyQualifiedErrorId : PSSessionOpenFailed

jj

0
17. Michael Pietroforte 8 months ago

The error message looks odd. Did you set the execution policy to unrestricted?

0
18. John Jensen 8 months ago

Yes, I tried unrestricted, remote signed, and restricted.  No difference.  It's never getting to the session, so I suppose the policy doesn't have a chance to affect it.

0
• Michael Pietroforte 8 months ago

Hard to say what your problem is. I suggest that you use a test computer with a freshly installed Windows without any third-party software installed, with the default configuration (don't apply any Group Policy) and try to give a standard user remote access to the the default PowerShell session as described in the article. If this works, do the same with your own session configuration. If this works too, you know that you configured PowerShell correctly and that it is a problem with your original computer. Then you have to remove every difference from the original computer step by step until it works.

0
19. John Thayer Jensen 8 months ago

Thanks so much for your attention, Michael.  I have, for now, at least, thrown in the towel - I am just going to do a -runas with a service account that is a local administrator.  That works.  I had hoped to avoid it because I just didn't like the idea of ordinary users running as administrators on my machine.  Not as bad as it could be, though, since they are only running on my machine, not on a server (or, Heaven forbid! a domain controller).

Sometime when I get time I'll try what you said because it has puzzled me - but I have to deal with another overriding factor: the length of the boss's patience 🙂

jj

0