Replies: 8 comments
-
I also hear the question a lot about how to find templates. Having find/install/publish wrappers might also help with that issue as well. I wrote a few examples last night. function Find-PlasterTemplate {
[CmdletBinding(DefaultParameterSetName='Default')]
[OutputType("PSCustomObject[]")]
param(
[Parameter(HelpMessage="Specifies the Name of the Plaster template to find",
ValueFromPipelineByPropertyName=$true,
Position=0)]
[ValidateNotNullOrEmpty()]
[string[]]
$Name,
[Parameter(HelpMessage="Specifies the minimum version of a single Template Version. The MaximumVersion and the RequiredVersion parameters are mutually exclusive; you cannot use both parameters in the same command.",
ValueFromPipelineByPropertyName=$true,
ParameterSetName='MinimumVersion')]
[ValidateNotNull()]
[Version]
$MinimumVersion,
[Parameter(HelpMessage="Specifies the maximum version of a single Template Version. The MaximumVersion and the RequiredVersion parameters are mutually exclusive; you cannot use both parameters in the same command.",
ValueFromPipelineByPropertyName=$true,
ParameterSetName='MaximumVersion')]
[ValidateNotNull()]
[Version]
$MaximumVersion,
[Parameter(HelpMessage="Specifies the exact version number of the Template to install",
ValueFromPipelineByPropertyName=$true,
ParameterSetName='RequiredVersion')]
[ValidateNotNull()]
[Version]
$RequiredVersion,
[Parameter(HelpMessage="Specifies to include all versions of a template in the results. You cannot use the AllVersions parameter with the MinimumVersion, MaximumVersion, or RequiredVersion parameters.",
ParameterSetName='RequiredVersion')]
[switch]
$AllVersions,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[Uri]
$Proxy,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[PSCredential]
$ProxyCredential,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[PSCredential]
$Credential
)
Process
{
Try {
$Module = Find-Module @PSBoundParameters -Tag PlasterTemplate -ErrorAction SilentlyContinue
if (!$Module) {
Throw "No match was found for the specified search criteria and template name '${Name}'. Templates must have the tag 'PlasterTemplate'"
}
$Module
}
Catch {
Throw
}
}
}
function Install-PlasterTemplate {
[CmdletBinding(DefaultParameterSetName='Default',
SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true,
HelpMessage="Specifies the Name of the Plaster template to be installed",
ValueFromPipelineByPropertyName=$true,
Position=0)]
[ValidateNotNullOrEmpty()]
[string]
$Name,
[Parameter(HelpMessage="Specifies the minimum version of a single Template Version.",
ValueFromPipelineByPropertyName=$true,
ParameterSetName='MinimumVersion')]
[ValidateNotNull()]
[Version]
$MinimumVersion,
[Parameter(HelpMessage="Specifies the maximum version of a single Template Version.",
ValueFromPipelineByPropertyName=$true,
ParameterSetName='MaximumVersion')]
[ValidateNotNull()]
[Version]
$MaximumVersion,
[Parameter(HelpMessage="Specifies the exact version number of the Template to install",
ValueFromPipelineByPropertyName=$true,
ParameterSetName='RequiredVersion')]
[ValidateNotNull()]
[Version]
$RequiredVersion,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[Uri]
$Proxy,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[PSCredential]
$ProxyCredential,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[PSCredential]
$Credential,
[Parameter(HelpMessage="Forces the installation of the Template")]
[switch]
$Force
)
Begin
{
$YesToAll = $false
$NoToAll = $false
}
Process
{
$PSBoundParameters['Repository'] = 'PSGallery'
$PSBoundParameters['Tag'] = 'PlasterTemplate'
$FindParams = $PSBoundParameters
$Null = $FindParams.Remove('Force')
$Null = $FindParams.Remove('Confirm')
$Null = $FindParams.Remove('Whatif')
Try {
$TemplatesPath = "$Env:APPDATA\Plaster\Templates"
$Module = PowerShellGet\Find-Module @PSBoundParameters
if (! (Test-Path -Path $TemplatesPath)) {
$Null = New-Item -Path $TemplatesPath -ItemType Directory
}
if (!$Module) {
Throw "No match was found for the specified search criteria and template name '${Name}'. Templates must have the tag 'PlasterTemplate'"
}
else {
$Destination = "$TemplatesPath\$($Module.Name)\$($Module.Version)"
}
if ($psCmdlet.ShouldProcess($Name, "Install Plaster template")) {
if (!(Test-Path -Path $Destination)) {
$InstallTemplate = $true
}
elseif (!($YesToAll -OR $NoToAll -OR $Force)) {
$Message = "$Name already Exists"
$Message2 = "Do you want to install anyway?"
$InstallTemplate = $psCmdlet.ShouldContinue($Message2, $Message, [ref]$YesToAll, [ref]$NoToAll)
}
if ($InstallTemplate -or $YesToAll -or $Force) {
$PSBoundParameters["Force"] = $true
PowerShellGet\Save-Module -LiteralPath $TemplatesPath @PSBoundParameters
}
}
}
Catch {
Throw
}
}
} I began working on publish, but that one likely requires a little more input. A lot of questions about how to handle the psd1 for example. Since these aren't necessarily modules, if a psd1 doesn't exist should plaster create it for them and things like that. You could also bypass the publish-Module and use the Nuget publish Package directly for some more flexibility. I was playing around with these and really liked this sort of idea. Only finds modules Tagged PlasterTemplate (or whatever tag preferred) and only installs if that tag is present as well. I just quickly chose appdata\plaster\templates, but could easily be something like $home.Plaster\templates etc. I knew a wrapper around powershellget would allow using the psgallery backend, and be pretty easy to implement. I wanted to try it out so I the these together last night to try it out. Very interested to see what others think or any ideas others might have. |
Beta Was this translation helpful? Give feedback.
-
I think a lot of people expect a scaffolding framework to be secure and trust that it won't execute code. Plaster has gone to great lengths to prevent code execution, and storing these in the path could potentially lead to some unwanted code being executed. This seemed like an easy way to get around this and be able to use the existing psgallery infrastructure. Using save-module to a custom path instead of install-module should remove most risks of the user uses the commands built in. Then plaster can just search for the templates in the default template location. |
Beta Was this translation helpful? Give feedback.
-
Unfortunately, as long as we use the PSGallery there is nothing to stop someone from executing |
Beta Was this translation helpful? Give feedback.
-
The "problem" isn't that someone might I agree with @gerane -- it should literally be as simple as putting the templates in a location that's not part of the To be honest, I strongly dislike "Modules" being used as the shipping mechanism for stuff that isn't PowerShell commands (everything from PackageManagement Providers to DSC Resources and PSScriptAnalyzer Rules and Pester tests, and now Plaster Templates). It pollutes the search results and confuses everyone. |
Beta Was this translation helpful? Give feedback.
-
One alternative I've considered is having a centralized GitHub repo which merely contains an index of Plaster template metadata pointing to other GitHub repos. That would allow us to write a OneGet provider which can pull tagged template releases straight from GitHub. What other means could we use for template distribution? |
Beta Was this translation helpful? Give feedback.
-
@daviwil I was thinking about that as well. There would need to be a lot more code written up front to really get that off the ground, but might be better in the long run. The other question is how would people publish new templates and who is going to manage adding the new Templates to the Repository. When I was looking at this before, I was also thinking about what you would need to write to manage the versioning. You could just piggy back off of the powershellget module's with the wrappers. You could just keep the metadata in package.json type configs. This is the metadata that the VSCode Gallery has for the PowerShell extension if you pull from their API. {
"publisher": {
"publisherId": "5f5636e7-69ed-4afe-b5d6-8d231fb3d3ee",
"publisherName": "ms-vscode",
"displayName": "Microsoft",
"flags": "verified"
},
"extensionId": "40d39ce9-c381-47a0-80c8-a6661f731eab",
"extensionName": "PowerShell",
"displayName": "PowerShell",
"flags": "validated, public",
"lastUpdated": "2016-12-16T22:25:52.523Z",
"publishedDate": "2015-11-18T00:50:38.583Z",
"releaseDate": "2015-11-18T00:50:38.583Z",
"shortDescription": "Develop PowerShell scripts in Visual Studio Code!",
"versions": [
{
"version": "0.8.0",
"flags": "validated",
"lastUpdated": "2016-12-16T22:25:52.58Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.8.0/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallerycdn.vsassets.io/extensions/ms-vscode/powershell/0.8.0/1481927151646"
},
{
"version": "0.7.2",
"flags": "validated",
"lastUpdated": "2016-09-02T22:03:02.847Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.7.2/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallerycdn.vsassets.io/extensions/ms-vscode/powershell/0.7.2/1474455550053"
},
{
"version": "0.7.1",
"flags": "validated",
"lastUpdated": "2016-08-24T22:52:34.017Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.7.1/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.7.1/assetbyname"
},
{
"version": "0.7.0",
"flags": "validated",
"lastUpdated": "2016-08-18T15:33:50.793Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.7.0/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.7.0/assetbyname"
},
{
"version": "0.6.2",
"flags": "validated",
"lastUpdated": "2016-08-12T18:47:03.013Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.6.2/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.6.2/assetbyname"
},
{
"version": "0.6.1",
"flags": "validated",
"lastUpdated": "2016-05-16T23:46:24.013Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.6.1/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.6.1/assetbyname"
},
{
"version": "0.6.0",
"flags": "validated",
"lastUpdated": "2016-05-12T19:28:21.337Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.6.0/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.6.0/assetbyname"
},
{
"version": "0.5.0",
"flags": "validated",
"lastUpdated": "2016-03-10T22:20:22Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.5.0/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.5.0/assetbyname"
},
{
"version": "0.4.1",
"flags": "validated",
"lastUpdated": "2016-02-17T21:05:41.647Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.4.1/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.4.1/assetbyname"
},
{
"version": "0.4.0",
"flags": "validated",
"lastUpdated": "2016-02-10T00:04:12.257Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.4.0/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.4.0/assetbyname"
},
{
"version": "0.3.1",
"flags": "validated",
"lastUpdated": "2015-12-17T20:55:10.433Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.3.1/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.3.1/assetbyname"
},
{
"version": "0.3.0",
"flags": "validated",
"lastUpdated": "2015-12-16T15:11:46.633Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.3.0/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.3.0/assetbyname"
},
{
"version": "0.2.0",
"flags": "validated",
"lastUpdated": "2015-11-23T22:46:30.54Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.2.0/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.2.0/assetbyname"
},
{
"version": "0.1.0",
"flags": "validated",
"lastUpdated": "2015-11-18T01:23:49.91Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.1.0/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.1.0/assetbyname"
},
{
"version": "0.0.1",
"flags": "validated",
"lastUpdated": "2015-11-18T00:50:38.583Z",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.0.1/assetbyname",
"fallbackAssetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.0.1/assetbyname"
}
],
"categories": [
"Languages",
"Snippets",
"Linters",
"Debuggers"
],
"tags": [
"debuggers",
"keybindings",
"powershell",
"snippet"
],
"statistics": [
{
"statisticName": "install",
"value": 289899
},
{
"statisticName": "averagerating",
"value": 4.263157844543457
},
{
"statisticName": "ratingcount",
"value": 38
},
{
"statisticName": "trendingdaily",
"value": 1.156003125271291
},
{
"statisticName": "trendingmonthly",
"value": 9.982463755534335
},
{
"statisticName": "trendingweekly",
"value": 3.1155265871927273
}
],
"deploymentType": 0,
"Installs": 289899,
"publisherName": "ms-vscode",
"FullName": "ms-vscode.PowerShell",
"Version": "0.8.0",
"assetUri": "https://ms-vscode.gallery.vsassets.io/_apis/public/gallery/publisher/ms-vscode/extension/PowerShell/0.8.0/assetbyname"
} You could probably use a lot of their format and just remove the unneeded if that was the route we wanted to go, but the way to submit new extensions and manage those is a bit more up in the air. |
Beta Was this translation helpful? Give feedback.
-
I think @daviwil idea of a github repo and a Oneget provider is a sensible first step towards providing almost an approved collection of trusted templates. Code reviews as with all other PR's being required to get your template in to the repo. |
Beta Was this translation helpful? Give feedback.
-
I created a project for containing Plaster templates named PlasterPlethora. I thought I might as well kick-start the community with this. Hopefully it can be a starter for getting us going with a way to share Plaster templates. I hope people will find it useful. I'm all ears for comments and feedback. Kind regards. |
Beta Was this translation helpful? Give feedback.
-
@gerane was asking me yesterday if we are concerned about malicious code being executed if someone installs a Plaster template from the PSGallery. In our template distribution scheme we don't actually load the module to get the template metadata, we just use
Get-Module -ListAvailable
and pull the PSData out of the module object. The module itself could be loaded by the user in another way, though. The module which contains the template could have some malicious code which gets executed when auto-loaded in a PowerShell session.Is this possibility enough of a concern for us to go even further and write our own set of Install/Find commands which can leverage the PSGallery for distribution but don't require the installation of a module in the PSModulePath? We could just use Save-Module then pull out the template files and put them in a user-level template folder.
Beta Was this translation helpful? Give feedback.
All reactions