Quick Links
Have you ever wanted to delegate a task, but found that the permissions needed can be too risky to hand out? Or, have you wanted to lock down things like group creation in AD to enforce naming conventions of groups?
JEA can help you with just that and a lot more. In this article, we're going to walk through how you can delegate your already created scripts with PowerShell 5.1.
What Is JEA?
JEA is a PowerShell solution from Microsoft that can restrict users (and administrators) to only be able to perform specified tasks in a specific PowerShell session, even if they require local admin on the said resource. In addition, you can be extremely specific. Only the commands you specify can be executed, you can enable only specific parameter values and parameter values that match a specific pattern.
For example, you can enable Servicedesk to only restart a specific service with
Restart-Service
, or only add groups to AD according to a specific naming convention. You can do all of this without giving them explicit permissions on a server or in AD. It's a tool that can save you a tremendous amount of time and secure your environment. Let's get started by wrapping our script into a function.
Step 1: Creating a Function Out of Your Script
The first step if you've not already done so is to make a function out of your script. This is quite easy, assuming that you already have your
parameters
set up. Below, I've wrapped my simple script "New-FolderAndShare" into a function:
Function New-FolderAndShare {
[cmdletbinding()]
param(
# Name of the share
[parameter(Mandatory)]
[ValidatePattern("^(Project d{5}|Team (Finance|HR|IT|Multi) [a-z ]+)$")]
[string]$ShareName,
# Directory of the new share folder locally
[parameter(Mandatory)]
[ValidatePattern("^(D|E|F):\Shares\$")]
[string]$Path,
# Who to have full access
[parameter(Mandatory)]
[ValidateSet("^CONTOSO\")]
[string]$FullAccess
)
$FullPath = Join-Path $Path $ShareName
New-Item -ItemType Directory -Path $FullPath
New-SmbShare -Path $FullPath -Name $ShareName -FullAccess $FullAccess
}
You validate the parameters with ValidatePattern in the function, but if this were a part of a module you could to that in the RoleCapabilities file instead with VisibleFunctions.
Making the script a function gives us greater control of what parameters are allowed in JEA, and makes it easier to export.
Step 2: Creating RoleCapabilities
The RoleCapabilities file decides what a specified role (defined in the next step) is allowed to do. This includes what commands they are allowed to run, what parameters they can use, and what modules to import.
While RoleCapabilities can be created manually, it's recommended to use the New-PSRoleCapabilityFile
command built into PowerShell 5.1. It's also in this file that you'll load in the function that we created in the previous step.
The follwing script creates a file called FileShareCreator.psrc and adds the New-FolderAndShare
function (that needs to be loaded into the current session):
# RUN THIS IN THE SERVER THAT WILL BE THE JEA ENDPOINT
$RoleCapabilitiesParam = @{
# Define a function that will be available in the cmdlet
FunctionDefinitions = @{
Name = 'New-FolderAndShare'
# Import the code of the function
ScriptBlock = [ScriptBlock]::Create(
(Get-Command New-FolderAndShare).Definition
)
}
# Modules used in the function needs to be explicity imported
ModulesToImport = @(
"SmbShare",
"Microsoft.PowerShell.Management"
)
Path = ".FileShareCreator.psrc"
}
New-PSRoleCapabilityFile @RoleCapabilitiesParam
Utilize Get-Command
to fetch the function in the FunctionDefinitions
-parameter. You can also add the raw script with parameters.
You also specify how you are allowed to use the function in the VisibleCmdlet
parameter. You do this by specifying the name of the function and its parameters together with a regular expression.
With this, you can create an extremely granular control of what a user can and can't do. But there's one caveat to making this work---you need to add the psrc-file into a module.
Step 3: Creating a Module for the RoleCapability File
It's time to create a module that you can put your role capabilities into. JEA finds the RoleCapabilities by the psrc files name without its extension, so avoid duplicates if you're going to create more role capabilities later on.
The following script is a modified version of what you find in the Official JEA documentation. It creates a new module in the module directory, creates the necessary files and folders needed, and copies the psrc file that you created in Step 2 into it:
# RUN THIS IN THE SERVER THAT WILL BE THE JEA ENDPOINT
# Create a folder for the module
$modulePath = Join-Path $env:ProgramFiles "WindowsPowerShellModulesFileShareJEA"
New-Item -ItemType Directory -Path $modulePath
# Create an empty script module and module manifest.
# At least one file in the module folder must have the same name as the folder itself.
New-Item -ItemType File -Path (Join-Path $modulePath "FileShareJEA.psm1")
New-ModuleManifest -Path (Join-Path $modulePath "FileShareJEA.psd1") -RootModule "FileShareJEA.psm1"
# Create the RoleCapabilities folder and copy in the PSRC file
$rcFolder = Join-Path $modulePath "RoleCapabilities"
New-Item -ItemType Directory $rcFolder
Copy-Item -Path .FileShareCreator.psrc -Destination $rcFolder
You have now created a role capability and a function so that you can use it in JEA. What's left do now is to create a PowerShell Session Configuration to map AD groups to the roles you just created.
Step 4: Defining Roles
In this step, you're going to create a PowerShell Session Configuration file that defines what roles are going to be assigned what Capabilities (from the .psrc file we created in Step 2).
You're going to create the AD group and transcript directory here as well.
# Create directory to store logs
New-Item -ItemType Directory -Path 'C:ProgramDataJEAConfigurationTranscripts' -Force
# Create AD group (you might need to do it on another server)
New-ADGroup -Path "OU=Groups,DC=contoso,DC=com" -Name 'JEA_FILESHARE_CREATOR' -GroupScope DomainLocal
# RUN THIS IN THE SERVER THAT WILL BE THE JEA ENDPOINT
# Define parameters for New-PSSessionConfigurationFile
$PSSessionConfigurationParams = @{
# Run as a temporary account
RunAsVirtualAccount = $True
# That is a local administrator
RunAsVirtualAccountGroups = @(
"administrators"
)
# Path where to save log files of what connected users are doing
TranscriptDirectory = 'C:ProgramDataJEAConfigurationTranscripts'
# Map an active directory group to the capability we created
RoleDefinitions = @{
'CONTOSOJEA_FILESHARE_CREATOR' = @{
RoleCapabilities = 'FileShareCreator'
}
}
# Path of the PSSC file
Path = ".SessionConfiguration.pssc"
}
# Create the PSSC file
New-PSSessionConfigurationFile @PSSessionConfigurationParams
Step 5: Creating a PowerShell Session
In this step, you will read in the SessionConfiguration.pssc file that you created in the previous step. This enables the members of JEA_FILESHARE_CREATOR to connect via PowerShell to the server:
PS51> Register-PSSessionConfiguration -Path .SessionConfiguration.pssc -Name 'JEAFileShare' -Force
PSPath : Microsoft.WSMan.ManagementWSMan::localhostPluginJEAFileShare
PSParentPath : Microsoft.WSMan.ManagementWSMan::localhostPlugin
PSChildName : JEAFileShare
PSDrive : WSMan
PSProvider : Microsoft.WSMan.ManagementWSMan
PSIsContainer : True
Keys : {Name=JEAFileShare}
Name : JEAFileShare
TypeNameOfElement : Container
Type : Container
You're done! Add a user to JEA_FILESHARE_CREATOR that does not have access to the server through normal means and try it out as that user by typing:
PS51> Enter-PSSession -ComputerName fs02.contoso.com -ConfigurationName JEAFileShare
PS51> New-FolderAndShare -ShareName "Project 12345" -Path D:Share
You can now run the command as a temporary local administrator that's locked down and only enabled to run a few default commands (visible with Get-Command
while in session) and the New-FolderAndShare
function that added in the Role Capabilities file.
If you want to see the account that's created temporarily, add VisibleExternalCommands @('c:windowssystem32whoami.exe')
to your RoleCapabilities parameters in Step 2. You can run whoami and see the local administrator name:
PS51 >whoami
winrm virtual userswinrm va_1_contoso_joe_helpdesk
Summary
Using JEA can be an awesome and easy way to delegate out tasks and secure your environment. This does not only include your own scripts but built-in modules and installed modules as well. Even though JEA can be a great value-add, be careful! You can create a great risk to your environment if you delegate the wrong commands or specify the wrong parameters to unexpected individuals.