It requires privileged access to machines for a user to perform certain actions that are required to manage the machines via PowerShell. This is an inevitable security risk and you must, inevitably, trust the system administrators. To minimize the risk, Microsoft recommends that you implement the “Just Enough Administration” (JEA) infrastructure.
What is JEA?
PowerShell, with its numerous cmdlets, has made System administration very simple, but there are two problems still to solve before we can take advantage of this simplicity to allow a wider group of users to perform system management. The first problem is to prevent a user from accidentally harming another part of the system, and the other problem is security.
The whole problem of managing access rights via PowerShell is sometimes forgotten or set aside in order to simplify the administration task. When you allow someone to access your system, you increase the risk of a user accidentally damaging part of the system, or the risk of a security breach. You can imagine what would happen if the administrator’s credentials were stolen while a sysadmin was performing actions as administrator. Once that happens, your entire system is vulnerable.
Basically, you need to assign just the sufficient rights to the user to achieve the particular admin task, and no wider rights than that. This is where “Just Enough Administration” intervenes – also known as “JEA”. You certainly know “Role-based access control” (RBAC)? RBAC is an approach to restricting system access to authorized users of a particular role. JEA provides a RBAC platform for Windows PowerShell that authorizes users to perform the rights to perform specific actions on your machines without giving them blanket administrative rights.
JEA works as a whitelist and not as a blacklist. This means that you must explicitly allow the actions that your users will be able to perform.
I have thus summarized this in a diagram of the JEA concept. Take the example of a helpdesk operator who needs to reset the Active Directory account of a blocked user. Our operator will use PowerShell and its numerous cmdlets in order to resolve this incident. But this means that he can also delete the user account or restart the domain controller through ignorance or by a simple error.
So, to avoid this kind of damage, we will use JEA to limit the actions of our operator by allowing him to use some pre-defined cmdlets.
The main advantages of JEA:
- Reduce the number of “administrator” accounts in your environment
- Easily limit access to the machines
- Check the actions made by your users
Note: Some of you who use WMF 5.0 may know JEA as a DSC resource named “xJEA”: this is now fully implemented in Windows PowerShell.
Prerequisites
Before implementing JEA infrastructure, certain prerequisites are needed. For machines whose operating system is “Windows Server”, you must have either Windows Server 2016 Technical Preview 4 and later versions, or Windows Server 2012 R2, 2012 et 2008 R2 with Windows Management Framework 5.0 installed.
For the Windows client operating systems, you must have Windows 10 with the update of November (1511) installed or a previous version of Windows with Windows Management Framework 5.0 installed
Finally, you must have administrator rights on the machine and this machine must be a member of an Active Directory domain.
JEA occurs through PowerShell Remoting. The first step is to run the following command to verify that remote access is enabled on the machine:
1 |
PS > Enable-PSRemoting |
How JEA works
JEA is implemented as a Windows PowerShell session endpoint and is based on two items:
- PowerShell Session Configuration file: This file specifies who can connect to an endpoint. It is possible to use Windows users or groups. A PowerShell Session Configuration file is specific to each machine. It is therefore possible to configure these machines in a very fine-grained manner. These files are followed by their extension “.pssc”.
- Role Capability file: There may be one or more Role Capability files. They allow the administrator to specify what actions can be done by each role. These files are recognized by their extension “.psrc”.
On each machine, there is a default PowerShell Session Configuration. Each session can be restricted to give PowerShell just a limited set of functionality. To list them, use the Get-PSSessionConfiguration cmdlet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
PS C:\> Get-PSSessionConfiguration Name : microsoft.powershell PSVersion : 5.0 StartupScript : RunAsUser : Permission : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed Name : microsoft.powershell.workflow PSVersion : 5.0 StartupScript : RunAsUser : Permission : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed Name : microsoft.powershell32 PSVersion : 5.0 StartupScript : RunAsUser : Permission : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed Name : microsoft.windows.servermanagerworkflows PSVersion : 3.0 StartupScript : RunAsUser : Permission : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators AccessAllowed |
We will add to this list a new session. So the next step is to create our own session file. These files use the “.pssc” extension and can be created via the New-PSSessionConfigurationFile cmdlet:
1 2 |
PS > New-Item -Path "C:\JEAConfig" -ItemType Directory PS > New-PSSessionConfigurationFile -Path C:\JEAConfig\JEADemo.pssc" |
Running this command provides the skeleton of a “.pssc” file containing the most common settings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
@{ # Version number of the schema used for this document SchemaVersion = '2.0.0.0' # ID used to uniquely identify this document GUID = '9fa70c54-5cfd-4d2d-88ca-5842b6de5353' # Author of this document Author = 'Admin' # Description of the functionality provided by these settings # Description = '' # Session type defaults to apply for this session configuration. Can be 'RestrictedRemoteServer' (recommended), 'Empty', or 'Default' SessionType = 'Default' # Directory to place session transcripts for this session configuration # TranscriptDirectory = 'C:\Transcripts\' # Whether to run this session configuration as the machine's (virtual) administrator account # RunAsVirtualAccount = $true # Groups associated with machine's (virtual) administrator account # RunAsVirtualAccountGroups = 'Remote Desktop Users', 'Remote Management Users' # Scripts to run when applied to a session # ScriptsToProcess = 'C:\ConfigData\InitScript1.ps1','C:\ConfigData\InitScript2.ps1' # User roles (security groups), and the role capabilities that should be applied to them when applied to a session # RoleDefinitions = @{ 'CONTOSO\SqlAdmins' = @{ RoleCapabilities = 'SqlAdministration' }; 'CONTOSO\ServerMonitors' = @{ VisibleCmdlets ='Get-Process' } } } |
By executing the following command, we can obtain the skeleton of a “.pssc” file containing all the settings:
1 |
PS > New-PSSessionConfigurationFile -Path "C:\JEAConfig\JEADemoFull.pssc" -Full |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
@{ # Version number of the schema used for this document SchemaVersion = '2.0.0.0' # ID used to uniquely identify this document GUID = '27df58a4-6150-412e-92f6-587f36617a34' # Author of this document Author = 'Admin' # Description of the functionality provided by these settings # Description = '' # Company associated with this document CompanyName = 'Unknown' # Copyright statement for this document Copyright = '(c) 2016 Admin. All rights reserved.' # Session type defaults to apply for this session configuration. Can be 'RestrictedRemoteServer' (recommended), 'Empty', or 'Default' SessionType = 'Default' # Directory to place session transcripts for this session configuration # TranscriptDirectory = 'C:\Transcripts\' # Whether to run this session configuration as the machine's (virtual) administrator account # RunAsVirtualAccount = $true # Groups associated with machine's (virtual) administrator account # RunAsVirtualAccountGroups = 'Remote Desktop Users', 'Remote Management Users' # Scripts to run when applied to a session # ScriptsToProcess = 'C:\ConfigData\InitScript1.ps1','C:\ConfigData\InitScript2.ps1' # User roles (security groups), and the role capabilities that should be applied to them when applied to a session # RoleDefinitions = @{ 'CONTOSO\SqlAdmins' = @{ RoleCapabilities = 'SqlAdministration' }; 'CONTOSO\ServerMonitors' = @{ VisibleCmdlets = 'Get-Process' } } # Language mode to apply when applied to a session. Can be 'NoLanguage' (recommended), 'RestrictedLanguage','ConstrainedLanguage', or 'FullLanguage' LanguageMode = 'FullLanguage' # Execution policy to apply when applied to a session ExecutionPolicy = 'Restricted' # Version of the Windows PowerShell engine to use when applied to a session # PowerShellVersion = '5.0.10586.117' # Modules to import when applied to a session # ModulesToImport = 'MyCustomModule', @{ ModuleName = 'MyCustomModule'; ModuleVersion = '1.0.0.0'; GUID ='4d30d5f0-cb16-4898-812d-f20a6c596bdf' } # Aliases to make visible when applied to a session # VisibleAliases = 'Item1', 'Item2' # Cmdlets to make visible when applied to a session # VisibleCmdlets = 'Invoke-Cmdlet1', @{ Name = 'Invoke-Cmdlet2';Parameters = @{ Name = 'Parameter1'; ValidateSet = 'Item1', 'Item2' },@{ Name = 'Parameter2'; ValidatePattern = 'L*' } } # Functions to make visible when applied to a session # VisibleFunctions = 'Invoke-Function1', @{ Name = 'Invoke-Function2';Parameters = @{ Name = 'Parameter1'; ValidateSet = 'Item1', 'Item2' },@{ Name = 'Parameter2'; ValidatePattern = 'L*' } } # External commands (scripts and applications) to make visible when applied to a session # VisibleExternalCommands = 'Item1', 'Item2' # Providers to make visible when applied to a session # VisibleProviders = 'Item1', 'Item2' # Aliases to be defined when applied to a session # AliasDefinitions = @{ Name = 'Alias1'; Value = 'Invoke-Alias1'}, @{Name = 'Alias2'; Value = 'Invoke-Alias2'} # Functions to define when applied to a session # FunctionDefinitions = @{ Name = 'MyFunction'; ScriptBlock = {param($MyInput) $MyInput } } # Variables to define when applied to a session # VariableDefinitions = @{ Name = 'Variable1'; Value = { 'Dynamic' +'InitialValue' } }, @{ Name = 'Variable2'; Value ='StaticInitialValue' } # Environment variables to define when applied to a session # EnvironmentVariables = @{ Variable1 = 'Value1'; Variable2 = 'Value2' } # Type files (.ps1xml) to load when applied to a session # TypesToProcess = 'C:\ConfigData\MyTypes.ps1xml','C:\ConfigData\OtherTypes.ps1xml' # Format files (.ps1xml) to load when applied to a session # FormatsToProcess = 'C:\ConfigData\MyFormats.ps1xml','C:\ConfigData\OtherFormats.ps1xml' # Assemblies to load when applied to a session # AssembliesToLoad = 'System.Web', 'System.OtherAssembly,Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' } |
In our example, we will rename the first file to “HelpdeskOperator.pssc” and modify the following lines:
1 2 3 4 |
SessionType = 'RestrictedRemoteServer' TranscriptDirectory = "C:\JEAConfig\Transcripts" RunAsVirtualAccount = $true RoleDefinitions = @{'Domain\HelpdeskOperator' = @{ VisibleCmdlets = 'Get-Service',’Get-Process’ }} |
Here is the description of these four parameters:
- SessionType: sets predefined parameters by default to be used. The “RestrictedRemoteServer” value allows minimum cmdlets for remote management. This mode defines the execution policy equal to “RemoteSigned” and contains the following cmdlets:
- Get-Command,
- Get-FormatData,
- Select-Object,
- Get-Help,
- Measure-Object,
- Exit-PSSession,
- Clear-Host,
- Out-Default.
- TranscriptDirectory: defines the location in which the PowerShell transcripts are saved after each remote session.
- RunAsVirtualAccount: indicates that PowerShell must “run as” virtual account. By default, the virtual account is a member of the Administrators group.
- RoleDefinitions: defines actions available to any user attempting to establish a connection based on their group membership.
Now we just have to register the configuration via the “Register-PSSessionConfiguration” cmdlet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
PS > Register-PSSessionConfiguration -Name 'HelpdeskOperator' -Path "C:\JEAConfig\HelpdeskOperator.pssc" WARNING: Register-PSSessionConfiguration may need to restart the WinRM service if a configuration using this name has recently been unregistered, certain system data structures may still be cached. In that case, a restart of WinRM may be required. All WinRM sessions connected to Windows PowerShell session configurations, such as Microsoft.PowerShell and session configurations that are created with the Register-PSSessionConfiguration cmdlet, are disconnected. WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Plugin Type Keys Name ---- ---- ---- Container {Name=HelpdeskOperator} HelpdeskOperator WARNING: Set-PSSessionConfiguration may need to restart the WinRM service if a configuration using this name has recently been unregistered, certain system data structures may still be cached. In that case, a restart of WinRM may be required. All WinRM sessions connected to Windows PowerShell session configurations, such as Microsoft.PowerShell and session configurations that are created with the Register-PSSessionConfiguration cmdlet, are disconnected. WARNING: Register-PSSessionConfiguration may need to restart the WinRM service if a configuration using this name has recently been unregistered, certain system data structures may still be cached. In that case, a restart of WinRM may be required. All WinRM sessions connected to Windows PowerShell session configurations, such as Microsoft.PowerShell and session configurations that are created with the Register-PSSessionConfiguration cmdlet, are disconnected. |
The -Name parameter is used by users when connecting to this configuration. At this time, the session is configured. Let us view the available sessions on our machine to note that a new session is clearly visible:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
PS C:\> Get-PSSessionConfiguration Name : HelpdeskOperator PSVersion : 5.0 StartupScript : RunAsUser : Permission : Domain\HelpdeskOperator AccessAllowed Name : microsoft.powershell PSVersion : 5.0 StartupScript : RunAsUser : Permission : NT AUTHORITY\INTERACTIVE AccessAllowed,BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed Name : microsoft.powershell.workflow PSVersion : 5.0 StartupScript : RunAsUser : Permission : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed Name : microsoft.powershell32 PSVersion : 5.0 StartupScript : RunAsUser : Permission : NT AUTHORITY\INTERACTIVE AccessAllowed,BUILTIN\Administrators AccessAllowed, BUILTIN\Remote Management Users AccessAllowed Name : microsoft.windows.servermanagerworkflows PSVersion : 3.0 StartupScript : RunAsUser : Permission : NT AUTHORITY\INTERACTIVE AccessAllowed,BUILTIN\Administrators AccessAllowed |
Your users can now connect via the Enter-PSSession cmdlet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
PS > $HelpdeskOperatorCred = Get-Credential PS > Enter-PSSession -ComputerName . -ConfigurationName HelpdeskOperator -Credential $HelpdeskOperatorCred [localhost]: PS>Get-Command CommandType Name Version Source ----------- ---- ------- ------ Function Clear-Host Function Exit-PSSession Function Get-Command Function Get-FormatData Function Get-Help Function Measure-Object Function Out-Default Function Select-Object Cmdlet Get-Process 3.0.0.0 Microsoft.PowerShell.Management Cmdlet Get-Service 3.0.0.0 Microsoft.PowerShell.Management [localhost]: PS>Get-Date The term 'Get-Date' 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 pathis correct and try again. + CategoryInfo : ObjectNotFound: (Get-Date:String) [],CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException [localhost]: PS>Get-Service Status Name DisplayName ------ ---- ----------- Stopped AeLookupSvc Application Experience Stopped ALG Application Layer Gateway Service Running AppHostSvc Application Host Helper Service Stopped AppIDSvc Application Identity Stopped Appinfo Application Information Running AppMgmt Application Management [localhost]: PS> Exit-PSSession |
Excellent! Only few cmdlets are visible: Get-Service and Get-Process correspond with the cmdlets that we have authorized. For the other cmdlets, these are minimal cmdlets authorized in JEA via the “RestrictedRemoteServer” mode.
Navigate to the following directory C:\JEAConfig\Transcripts and open the file named “PowerShell_Transcript_xxxx.txt”. This contains all the commands entered by your user.
Note that a modification in a “.pssc” file does not take effect until the session exists. So you have to destroy the session and recreate it:
1 |
PS > Unregister-PSSessionConfiguration -Name JEADemo2 -ErrorAction Stop |
To go further with RoleCapabilities
Why do we need to work with roles? Because it’s easier! The management will be simplified. Indeed, a role defines what a user can do. This may involve, at the least, the use of some cmdlets and some applications.
We thus speak of RBAC functionality!
For PowerShell to detect roles, simply place them in a “RoleCapabilities” folder in a valid PowerShell module. This module will be loaded automatically when the PowerShell console is opened. This is a real advantage because when editing a “.psrc” file, it will be analyzed each time you open the PowerShell console. No need to destroy and recreate the session. Let’s start with:
- Create our module
- Create the manifest
- Create the “RoleCapabilities” folder
- And finally create our “.psrc” file
1 2 3 4 5 6 7 8 9 |
PS > New-Item -Path 'C:\Program Files\WindowsPowerShell\Modules\JEAHelpdeskOperator' -ItemType Directory PS > New-ModuleManifest -Path 'C:\Program Files\WindowsPowerShell\Modules\JEAHelpdeskOperator\JEAHelpdeskOperator.psd1' -RootModule JEAHelpdeskOperator.psm1 PS > New-Item -Path 'C:\Program Files\WindowsPowerShell\Modules\JEAHelpdeskOperator\JEAHelpdeskOperator.psm1' -ItemType File PS > New-Item -Path 'C:\Program Files\WindowsPowerShell\Modules\JEAHelpdeskOperator\RoleCapabilities' -ItemType Directory PS > New-PSRoleCapabilityFile -Path 'C:\Program Files\WindowsPowerShell\Modules\JEAHelpdeskOperator \RoleCapabilities\JEAHelpdeskOperator.psrc' |
Now, we will adapt this “psrc” file in our environment. I allow the operator:
- To use all the cmdlets starting with “Get-“,
- To restart the machine,
- To restart a single Windows service whose name is “Spooler”,
- To use the external command “Cmd.exe”,
- To use the following aliases “Dir” and “Ls”
- And finally to use the “FileSystem” provider otherwise aliases and the Get-ChildItem cmdlet will not work.
1 2 3 4 5 6 7 8 9 10 11 12 |
VisibleCmdlets = 'Restart-Computer', 'Get-*' @{ Name = 'Restart-Service' Parameters = @{ Name = 'Name'; ValidateSet = 'Spooler' } } VisibleExternalCommands = 'C:\Windows\system32\cmd.exe' VisibleAliases = 'Dir',’ls’ VisibleProviders = 'FileSystem’ |
I will not detail all of these options because it is relatively intuitive.
The last thing to do is to indicate in the “pssc” file the next line that will combine this role with our user (or group):
1 |
RoleDefinitions = @{'Domain\HelpdeskOperator' = @{ RoleCapabilities = 'JEAHelpdeskOperator' }} |
Note: Think of destroying the previous session that was used for our test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
[localhost]: PS>get-command CommandType Name Version Source ----------- ---- ------- ------ Function Clear-Host Function Exit-PSSession Function Get-Command Function Get-FormatData Function Get-Help Function Get-Verb Function Measure-Object Function Out-Default Function Restart-Service Function Select-Object Cmdlet Get-Acl 3.0.0.0 Microsoft.PowerShell.Security Cmdlet Get-Alias 3.0.0.0 Microsoft.PowerShell.Utility Cmdlet Get-AuthenticodeSignature 3.0.0.0 Microsoft.PowerShell.Security Cmdlet Get-ChildItem 3.0.0.0 Microsoft.PowerShell.Management [localhost]: PS>cmd Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. C:\Windows\system32> [localhost]: PS> |
JEA Helper Tool
If you have any difficulties with “pssc” and “psrc” files, you will be relieved to hear that there is a tool to make it easy to start with JEA. This tool is called “JEA Helper Tool” and let you create, in graphical mode, the Session Configuration File and the Role Capability File.
This tool can be downloaded from this address: JEA Helper Tool
In this tab, I load my “psrc” file in the “JEA Helper Tool” that shows me the cmdlets that I have authorized. You can also use the following command to get this information:
1 |
PS > Get-PSSessionCapability -Username 'Domain\HelpdeskOperator' -ConfigurationName JEAHelpdeskOperator |
Finally in this tab, the tool detects my “HelpdeskOperator” session associated with the “JEAHelpdeskOperator” role.
Reporting on JEA
As with any system, it is important to monitor and trace every action performed on your machines. JEA equally backs-up the actions made by your users into the Windows Event Logs. Activation can be done manually on each machine or by “Group Policy Object” (GPO).
Open the Group Policy Editor MMC and navigate to:
- Computer Configuration
- Administrative Templates
- Windows Components
- Windows PowerShell
Now, double click on “Turn on Logging Module” and select “Enabled“. Click on “Show” next to module names and if you want to log commands from all PowerShell modules then type “*” in the pop up window.
In addition, it will be very easy to see the actions performed on your machines by a user with the Transcript Directory. PowerShell will automatically record a transcript of all actions taken in a given session. This parameter is configured via the following line:
1 |
TranscriptDirectory = "C:\JEAConfig\Transcripts" |
I use a basic script to display the available sessions on the machine in HTML format:
You can download my script on the technet gallery.
Conclusion
We have seen, in this article, a new concept for PowerShell users called JEA – Just Enough Administration. This allows you to implement a RBAC infrastructure via PowerShell to limit administrators’ accesses to your environment.
JEA is extremely powerful and very useful to not only secure and control your environment but also, equally, to limit the actions that can performed by the users. Keep in mind that PowerShell is also very powerful and an error is quickly made. To err is human so it pays to be preventive and secure your environment.
JEA allows limited access to certain cmdlets, applications, environment variables and so on. Managing JEA is relatively simple, but you should allow plenty of time to implement it as you will have to precisely list the actions that your users will be able to perform on the systems.
It requires privileged access to machines for a user to perform certain actions that are required to manage the machines via PowerShell. This is an inevitable security risk and you must, inevitably, trust the system administrators. To minimize the risk, Microsoft recommends that you implement the “Just Enough Administration” (JEA) infrastructure.
Load comments