PowerShell script delegation with Just Enough Administration (JEA)

Contents

Powershell logo

Have you ever wanted to delegate a task, but found that the necessary permits may be too risky to hand out? Or have you wanted to block things like creating groups in AD to enforce naming conventions for groups?

JEA can help you with that and much more. In this post, we will see how you can delegate your already created scripts with PowerShell 5.1.

What is JEA?

JEA is a Microsoft PowerShell solution that can restrict users (and administrators) so they can only perform specific tasks in a specific PowerShell session, even if they require a local administrator on said resource. At the same time, can be extremely specific. Only the commands you specify can be run, you can enable only specific parameter values ​​and parameter values ​​that match a specific pattern.

As an example, you can enable Servicedesk to only restart a specific service with Restart-Service, or just 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 is a tool that can save you an enormous amount of time and protect your environment. Let's start by wrapping our script in a function.

Paso 1: creating a function from your script

The first step, if you haven't done it yet, is to create a function from your script. This is pretty straightforward, assuming you already have your parameters set up. Next, I have wrapped my simple script “New-FolderAndShare” in 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

}

Validate the parameters with ValidatePattern in function, but if this were part of a module, you could do it in the RoleCapabilities file instead with Visible functions.

Making the script a function gives us greater control of the parameters allowed in JEA and facilitates the export.

Paso 2: role-building capacity building

The RoleCapabilities file decides what a specific role is allowed to do (defined in the next step). This includes what commands they can run, what parameters can they use and what modules to import.

Although RoleCapabilities can be created manually, it is recommended to use the New-PSRoleCapabilityFile PowerShell built-in command 5.1. It is also in this file that it will load in the function that we created in the previous step.

The following script creates a file called FileShareCreator.psrc and add the New-FolderAndShare function (which should be loaded in the current session):

# RUN THIS IN THE SERVER THAT WILL BE THE JEA ENDPOINT

$RoleCapabilitiesParam = @{
    # Establece 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

To use Get-Command to find the function in the FunctionDefinitions-parameter. Additionally you can add the raw script with parameters.

It also specifies how you are enabled to use the function in the VisibleCmdlet parameter. For this, specify the name of the function and its parameters along with a regular expression.

With this, you can create extremely granular control of what a user can and cannot do. But there is a caveat to make this work: you need to add psrc file in a module.

Paso 3: creating a module for the RoleCapability file

Time to create a module in which you can put your role capabilities. JEA finds the role capabilities by the name of the psrc files without their extension, therefore avoid duplicates if you are creating more role capabilities later.

The following script is a modified version of what you find in the Official JEA documentation. Create a new module in the module directory, create the necessary files and folders and copy the psrc file you created in step 2 at:

# 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 role to be used in JEA. What remains to be done now is to create a PowerShell session configuration to allocate AD groups to the roles you just created.

Paso 4: Definition of roles

In this step, will create a PowerShell session configuration file that establishes which roles will be assigned which capabilities (from the.psrc file we created in step 2).

Here you will also create the AD group and the transcripts directory.

# 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

# Establece 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

Paso 5: create a PowerShell session

In this step, will read in the SessionConfiguration.pssc file you created in the previous step. This enables 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

Ready! Add a user to JEA_FILESHARE_CREATOR that you do not have access to the server by normal means and test it as that user by typing:

PS51> Enter-PSSession -ComputerName fs02.contoso.com -ConfigurationName JEAFileShare
PS51> New-FolderAndShare -ShareName "Project 12345" -Path D:Share

Now you can run the command as a temporary local administrator which is locked and only enabled to run some default commands (visible with Get-Command during the session) and the New-FolderAndShare function added in functions functions file.

If you want to see the account that was created temporarily, add VisibleExternalCommands @('c:windowssystem32whoami.exe') to your RoleCapabilities parameters in Step 2. You can run whoami and see the name of the local administrator:

PS51 >whoami
winrm virtual userswinrm va_1_contoso_joe_helpdesk

Summary

Using JEA can be an amazing and easy way to delegate tasks and protect your environment. This doesn't just include your own scripts, but also the integrated modules and the installed modules. Even though JEA can be a great added value, be careful! You can create great risk to your environment if you delegate the wrong commands or specify the wrong parameters to unexpected people.

Want to learn more?

Subscribe to our Newsletter

We will not send you SPAM mail. We hate it as much as you.