Windows Unprivileged - Dynamic JEA
Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!
Last night I had this sudden idea. If JEA configurations can be created without a text editor just using the New-PSSessionConfigurationFile and New-PSRoleCapabilityFile cmdleys with their parameters, then why not create the arguments for them dynamically, that is, create the JEA configuration based on existing groups rather than create groups for pre-defined JEA session configurations.
JEA configurations could be based on solely on group names (and automatically allow all cmdlets of a certain object target depending on group name) or based on metadata in the group (for example, the description).
What follows is an example of a dynamic JEA environment based on group names and group descriptions.
Imagine the following PowerShell script.
# some names and paths
$sJEAName = "WupsDynamic" # the name of the JEA session configuration for all of the dynamic capabilities
$sDynamicJEAGroupGlobPattern = "JEA_*" # pattern for group names to be considered for dynamic JEA registration
$pathJEA = "C:\Program Files\WindowsPowerShell\Modules\JEA" # the path to JEA configurations
# get the relevant groups
$aDynamicJEAGroup = Microsoft.PowerShell.LocalAccounts\Get-LocalGroup $sDynamicJEAGroupGlobPattern
# create role definitions for dynamic JEA session configuration
$htRoleDefinitions = @{}
# create role capability files for those groups
$aDynamicJEAGroup | ForEach-Object {
# determine group name and description
$group = $_
$sGroupName = $group.Name # will be a name conforming with the pattern defined above
$sGroupDescription = $group.Description # description must be in evaluable PowerShell format
# build hashtable based on description and create file
$htRoleCapability = Invoke-Expression $sGroupDescription
New-PSRoleCapabilityFile -Path "$pathJEA\RoleCapabilities\$sGroupName.psrc" @htRoleCapability
# and add to role definitions for JEA session configuration
$htRoleDefinitions.Add($sGroupName,@{'RoleCapabilities'=$sGroupName})
}#foreach
# create JEA session configuration file
New-PSSessionConfigurationFile -Path "$pathJEA\$sJEAName.pssc" -RunAsVirtualAccount -SessionType 1 -RoleDefinitions $htRoleDefinitions
# unregister and register session configuration
Unregister-PSSessionConfiguration $sJEAName 2>$null
Register-PSSessionConfiguration -Name $sJEAName -Path "$pathJEA\$sJEAName.pssc"
This will for each group JEA_* create a role capability based on the group’s description and a session configuration that will point to them all.
For this to make some sense we need at least one JEA_* group. (New-LocalGroup does not support long descriptions, hence the use of the net command.)
PS C:\Program Files\WindowsPowerShell\Modules\JEA> net localgroup JEA_SmbShare /comment:"@{ModulesToImport='SmbShare';VisibleCmdlets='*-SmbShare';VisibleProviders='FileSystem'}" /add
The command completed successfully.
This description will tell the dynamic JEA creator that the module SmbShare is to be imported and that all the *-SmbShare cmdlets shall be accessible.
After running the script above we can see the results.
PS C:\Program Files\WindowsPowerShell\Modules\JEA> .\RegisterDynamicJEA.ps1 # the first time run this will be relatively quiet
PS C:\Program Files\WindowsPowerShell\Modules\JEA> dir
Directory: C:\Program Files\WindowsPowerShell\Modules\JEA
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 9/8/2025 6:02 PM RoleCapabilities
-a---- 9/8/2025 6:04 PM 1676 RegisterDynamicJEA.ps1
-a---- 9/8/2025 6:04 PM 2188 WupsDynamic.pssc
PS C:\Program Files\WindowsPowerShell\Modules\JEA> dir .\RoleCapabilities\
Directory: C:\Program Files\WindowsPowerShell\Modules\JEA\RoleCapabilities
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 9/8/2025 6:04 PM 4804 JEA_SmbShare.psrc
The created files will be quite boring, simply allowing JEA_SmbShare.psrc for group JEA_SmbShare and allowing *-SmbShare cmdlets in JEA_SmbShare.psrc.
Add a user to the JEA_SmbShare group.
PS C:\Program Files\WindowsPowerShell\Modules\JEA> net localgroup JEA_SmbShare /add benoit
The command completed successfully.
And let the user test it out.
PS C:\WINDOWS\system32> whoami
champignac\benoit
PS C:\WINDOWS\system32> whoami /groups GROUP INFORMATION -----------------
Group Name Type SID Attributes
====================================== ================ ============================================= ==================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
CHAMPIGNAC\JEA_SmbShare Alias S-1-5-21-344341352-2539047333-2300305637-1037 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\INTERACTIVE Well-known group S-1-5-4 Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON Well-known group S-1-2-1 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account Well-known group S-1-5-113 Mandatory group, Enabled by default, Enabled group
LOCAL Well-known group S-1-2-0 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication Well-known group S-1-5-64-10 Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level Label S-1-16-8192
PS C:\WINDOWS\system32> Import-PSSession(New-PSSession -ConfigurationName WupsDynamic)-AllowClobber
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 1.0 tmp_tnw3j5t5.o0s {Clear-Host, Exit-PSSession, Get-Command, Get-SmbShare...}
PS C:\WINDOWS\system32> New-SmbShare -Path C:\Temp\ -Name Foo
Name ScopeName Path Description
---- --------- ---- -----------
Foo * C:\Temp
PS C:\WINDOWS\system32>
Yes, it works. Benoit will be assigned all role capabilities for which he is in the corresponding group.
Useful groups:
Name | Description | What it does |
JEA_SmbShare | @{ModulesToImport='SmbShare'; VisibleCmdlets='*-SmbShare'; VisibleProviders='FileSystem'} | Allows users to manage shares |
JEA_Process | @{VisibleCmdLets='Get-Process','Stop-Process'} | Allows users to stop any process |
JEA_Service | @{VisibleCmdLets='Get-Service','Stop-Service','Start-Service','Restart-Service'} | Allows users to start and stop any service |
JEA_IIS | @{ModulesToImport='IISAdministration','WebAdministration'; VisibleCmdlets='*-IIS*','*-Web*'; VisibleExternalCommands='C:\Windows\System32\iisreset.exe'; VisibleProviders='Variable'} | Allows users to manage IIS |
I am hoping that the description field is big enough for this. If not, I will come up with a new and improved idea of where to store this data.
Too add or remove JEA role capabilities just add or remove users to the groups or add or remove groups. Modify the script to add a set of standard cmdlets if there is no description if you like.
Hope this helps.
Next: TBD