Skip to content

Add Extensibility to Plaster's Constrained Runspace #333

@bwright86

Description

@bwright86

Plaster is a good platform to scaffold content, and I have used it for building module templates. But recently I have been using it to scaffold application configuration data.

One shortcoming I have found is that Plaster uses constrained runspaces to perform the scaffolding. Correct me if I'm wrong, but this was to provide safety around what is essentially Invoke-Expression. The difficulty comes from trying to write clean code and turn comma separated strings into properly formatted output.

Example template files:

Test.json.txt
(This is the simplest way I could think to join comma separated strings into a JSON array.)

{
    "Key":  "Value",
    "Array":  [
        ""
<%
if ($PLASTER_PARAM_Param1) {
    $PLASTER_PARAM_Param1.split(",").trim().foreach({",`"$_`""})
}
%>
               ]
}

The resulting file is not well formatted, and has a blank element in the first position of the array:
Test.json

{
    "Key":  "Value",
    "Array":  [
        ""
,"Test"
,"Testing"
               ]
}

Another option is to use .Replace, and replace commas with newlines(`n) and double quotes ("). But newlines are not interpolated in the constrained runspace. So this doesn't work:

"`"$($PLASTER_PARAM_Param1.replace(",", "`"`n,`""))`""

Possible Solutions

One solution that I would like to see, is a configuration file that can be placed in a user directory (like $PROFILE), or in the module folder itself. This file contains a list of allowable cmdlets in the scaffolding process, and Invoke-Plaster adds these cmdlets to the runspace. This would provide the extensibility, without having to rebuild the module with a custom list of cmdlets. It also puts the security onus on the user that adds the commands. Either the installing user can add a config file, or only the current user's config file is used during scaffolding.

Another solution, is adding a parameter to the Invoke-Plaster function, like -AllowedCmdlets to add a list of cmdlets to be used during scaffolding. This makes it a little easier for the user to scaffold with the cmdlets they need, but on the flip-side it makes it easier to pass cmdlets required for command injection. So this provides a little less control when scaffolding content.

Either of these solutions would allow the code to be cleaner, like so:

{
    "Key":  "Value",
    "Array":  [
<%
if ($PLASTER_PARAM_Param1) {
    $output = $PLASTER_PARAM_Param1 -split ",") -join "`",`n`""
    "`"$output`""
} else {
    "`"`""
}
%>
               ]
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions