Announcing PowerShell Crescendo Preview.2

Jason Helmick

Jason

We are pleased to announce the second preview of PowerShell Crescendo, a framework to rapidly develop PowerShell cmdlets for native commands, regardless of platform.

The updated preview releases are now available for download on the PowerShell Gallery:

To install Microsoft.PowerShell.Crescendo:

Install-Module Microsoft.PowerShell.Crescendo -AllowPrerelease

For more information on Microsoft.PowerShell.Crescendo, check out these previous blog posts:

Crescendo Preview 2 Updates

This update to Crescendo adds elevation support for native commands, and generation of a module manifest when exporting a Crescendo module. Read the full list of changes below:

  • Added support for native command elevation on Windows and Linux platforms. (Issue #50)
  • Export-CrescendoModule now exports a module manifest (psd1) along with the module file (psm1). (Issue #51)
  • Added support for generating aliases for Crescendo cmdlets (Issue #52)
  • Added support for SupportsShouldProcess. Thanks jdhitsolutions! (Issue #59)

Native Command elevation

Native commands may require administrative elevation to perform the requested operation. The Crescendo schema has been extended to support elevation on Windows and Linux/macOS platforms. The schema supports the new keyword Elevation that has two properties Command and Arguments.

  • Command: Defines the elevation mechanism to be used to elevate the native command. The function Invoke-WindowsNativeAppWithElevation has been included to aid with elevation on Windows. sudo has been tested as well.
  • Arguments: These are the parameters to be used in conjunction with the elevation command. This can be a collection of parameters.

    • OriginalName: This is the parameter to be used with the elevation command.
    • DefaultValue: The default parameter value.

Windows Native Command Elevation

Elevation on Windows is supported using the built-in function Invoke-WindowsNativeAppWithElevation. Invoke-WindowsNativeAppWithElevation uses Start-Process with a PSCredential to invoke the native command and captures the output and errors of the native command which are returned to the user. This function is inserted into the Crescendo module you export. In the example below, the PowerShell cmdlet Get-Credential will prompt for credentials necessary to elevate the native command when the exported Crescendo function is executed.

"Elevation": {
        "Command": "Invoke-WindowsNativeAppWithElevation",
        "Arguments": [
            {
                "OriginalName" : "-Credential",
                "DefaultValue": "(get-credential)"
            }
        ]
    },

In automation scenarios that require elevation without user interaction, Crescendo supports retrieving credentials from secured vaults. In the example below, credentials for elevation are retrieved from SecretManagement and SecretStore.

For more information about storing and managing secrets, see [SecretManagement Announcement](https://devblogs.microsoft.com/powershell/secretmanagement-and-secretstore-are-generally-available/

"Elevation": {
        "Command": "Invoke-WindowsNativeAppWithElevation",
        "Arguments": [
            {
                "OriginalName" : "-Credential",
                "DefaultValue": "(get-secret admin)"
            }
        ]
    },

Elevation can be defined for each cmdlet. When authoring a Crescendo json configuration, include the elevation definition before the parameters are defined. In the example below, the native command netsh.exe requires elevation to enable and disable the Windows Firewall.

{
    "$schema": "./Microsoft.PowerShell.Crescendo.Schema.json",
    "Verb": "Set",
    "Noun": "WinFirewall",
    "Platform": ["Windows"],
    "OriginalCommandElements": ["advfirewall", "set", "allprofiles", "state"],
    "OriginalName": "$env:Windir/system32/netsh.exe",
    "Elevation": {
        "Command": "Invoke-WindowsNativeAppWithElevation",
        "Arguments": [
            {
                "OriginalName" : "-Credential",
                "DefaultValue": "(get-credential)"
            }
        ]
    },
    "DefaultParameterSetName": "Enable",
    "Parameters": [
        {
            "OriginalName": "on",
            "Name": "On",
            "ParameterType": "switch",
            "ParameterSetName": ["Enable"]
        },
        {
            "OriginalName": "off",
            "Name": "Off",
            "ParameterType": "switch",
            "ParameterSetName": ["Disable"]
        }
    ]
}

Linux Native Command Elevation

Native command elevation for Linux and macOS is handled through the command sudo. To enable elevation for Crescendo, include sudo as the Command value. In the example below, when the function Get-TimeServer is executed, the user is prompted for the sudo password. The native command is elevated with sudo privileges. In automation scenarios that require elevation without user interaction, configure the sudoers file.

{
    "$schema": "../src/Microsoft.PowerShell.Crescendo.Schema.json",
    "Verb": "Get",
    "Noun": "TimeServer",
    "Elevation": {
        "Command": "sudo"
    },
    "OriginalCommandElements": ["-getnetworktimeserver"],
    "OriginalName": "/usr/sbin/systemsetup",
    "Platform": ["MacOS"],
    "OutputHandlers": [
        {
            "ParameterSetName": "Default",
            "Handler": "$args|%{[pscustomobject]@{ TimeServer = $_.Split(':')[1].Trim()}}"
        }
    ]
}

SupportsShouldProcess

Cmdlets that cause change to the system, such as files and service configurations, create a risk that could negatively impact operations. To help mitigate risk, cmdlets support common parameters -WhatIf and -Confirm. These parameters provide greater detail about the target of each change, and provides a confirmation mechanism allowing the user to approve each change. Crescendo supports this functionality when wrapping native commands though the schema keyword SupportsShouldProcess.

In the example below, The keyword SupportsShouldProcess accepts a boolean to enable the common parameters -WhatIf and -Confirm.

{
    "$schema": "../src/Microsoft.PowerShell.Crescendo.Schema.json",
    "Verb": "Remove",
    "Noun": "DockerImage",
    "OriginalName": "docker",
    "SupportsShouldProcess": true,
    "OriginalCommandElements": [
        "image",
        "rm"
    ],
    "Parameters": [
        {
            "Name": "ID",
            "OriginalName": "",
            "Mandatory": true,
            "ValueFromPipelineByPropertyName": true
        }
    ]
}

Executing Remove-DockerImage with the -WhatIf parameter supported by SupportsShouldProcess.

Get-DockerImage | Where-Object {$_.id -match "d70eaf7277ea"} | Remove-DockerImage -WhatIf

When SupportsShouldProcess is set True, the following expected output will result.

What if: Performing the operation "Remove-DockerImage" on target "docker image rm d70eaf7277ea".

Aliases

Aliases for Crecendo wrapped native commands are now supported in the Crescendo schema with the keyword Aliases. In the snippet below, the cmdlet definition Set-WinFirewall includes the alias definition SFW. When exported, the Crescendo created module will include the Set-WinFirewall function and SFW alias.

{
    "$schema": "./Microsoft.PowerShell.Crescendo.Schema.json",
    "Verb": "Set",
    "Noun": "WinFirewall",
    "Platform": ["Windows"],
    "OriginalCommandElements": ["advfirewall", "set", "allprofiles", "state"],
    "OriginalName": "$env:Windir/system32/netsh.exe",
    "Aliases": ["SFW"],
    "Elevation": {
        "Command": "Invoke-WindowsNativeAppWithElevation",
        "Arguments": [
            {
                "OriginalName" : "-Credential",
                "DefaultValue": "(get-credential)"
            }
        ]
    },

Future plans

Next/Future plans for preview.3 will be based on feedback and include a few items under investigation:

  • Improved OutputHandler support for building objects from native command string output.
  • Support for multiple cmdlet definitions in a single json configuration.

Our goal is to make it easier to convert your native commands to PowerShell cmdlets and receive the benefits that PowerShell provides. We value your ideas and feedback and hope you will give Crescendo a try, then stop by our GitHub repository and let us know of any issues or features you would like added.

For more information about PowerShell Crescendo issues and features, see: Crescendo on GitHub

Jason Helmick

Program Manager, PowerShell

1 comment

Leave a comment

  • Avatar
    kvprasoon

    Awesome. This should cover more use cases.

    I think Crescendo should be providing option to have -Credential to the cmdlets it creates using the same Parameter attributes via json,
    which can utilize the Invoke-WindowsNativeAppWithElevation. Otherwise its either using a secret store or purely interactive(correct me if I’m wrong).

    Is there any reason why the elevation function looks like a cmdlet (Invoke-WindowsNativeAppWithElevation) than a simple usage like sudo for linux. If that cmdlet is always used internally, then can’t we make it simple in name ?