Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpawlowski/06ebbddccead1a446fd42886730c9d0d to your computer and use it in GitHub Desktop.
Save jpawlowski/06ebbddccead1a446fd42886730c9d0d to your computer and use it in GitHub Desktop.
PowerShell modules, digital signatures, NuGet nuspec and packages

PowerShell modules, digital signatures, NuGet nuspec and packages

d-fens GmbH General-Guisan-Strasse 6 CH-6300 Zug Switzerland

d-fens PowerShell modules, digital signatures, NuGet nuspec and packages
Copyright 2014 d-fens GmbH
This product includes software developed at
d-fens GmbH (http://d-fens.ch/).
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>biz.dfch.PS.System.Utilities</id>
<version>1.0.4</version>
<title>biz.dfch.PS.System.Utilities</title>
<authors>d-fens GmbH</authors>
<owners>Ronald Rink</owners>
<licenseUrl>https://github.com/dfch/biz.dfch.PS.System.Utilities/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/dfch/biz.dfch.PS.System.Utilities</projectUrl>
<iconUrl>https://raw.githubusercontent.com/dfch/fragments/master/logo-32x32.png</iconUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<description>biz.dfch.PS.System.Utilities
============================
Modules: biz.dfch.PS.System.Utilities
d-fens GmbH, General-Guisan-Strasse 6, CH-6300 Zug, Switzerland
This Microsoft PowerShell module contains Cmdlets to perform various actions and utilties/convenience functions such as string conversion and formatting.
You can download this module via [NuGet](http://nuget.org) with [Install-Package biz.dfch.PS.System.Utilities](https://www.nuget.org/packages/biz.dfch.PS.System.Utilities/).
See [d-fens WebSite](http://d-fens.ch/2014/10/15/module-biz-dfch-ps-system-utilities/) or check the [Wiki](https://github.com/dfch/biz.dfch.PS.System.Utilities/wiki) for further description and examples on how to use the module.
</description>
<summary>This Microsoft PowerShell module contains Cmdlets to perform various actions and utilties/convenience functions such as string conversion and formatting.</summary>
<releaseNotes>20141130</releaseNotes>
<copyright>(c) 2014 d-fens GmbH</copyright>
<language>en-US</language>
<tags>PowerShell dfch</tags>
<dependencies>
<dependency id="biz.dfch.PS.System.Logging" version="1.0.3" />
</dependencies>
</metadata>
<files xmlns="">
<file src="biz.dfch.PS.System.Utilities.psm1" target="biz.dfch.PS.System.Utilities.psm1" />
<file src="biz.dfch.PS.System.Utilities.psd1" target="biz.dfch.PS.System.Utilities.psd1" />
<file src="biz.dfch.PS.System.Utilities.xml" target="biz.dfch.PS.System.Utilities.xml" />
<file src="LICENSE" target="LICENSE" />
<file src="NOTICE" target="NOTICE" />
<file src="README.md" target="README.md" />
<file src="biz.dfch.PS.System.Utilities_aaab9f3e-e544-4827-9db8-44bade441fc5_en-US_HelpContent.cab" target="biz.dfch.PS.System.Utilities_aaab9f3e-e544-4827-9db8-44bade441fc5_en-US_HelpContent.cab" />
<file src="biz.dfch.PS.System.Utilities_aaab9f3e-e544-4827-9db8-44bade441fc5_HelpInfo.xml" target="biz.dfch.PS.System.Utilities_aaab9f3e-e544-4827-9db8-44bade441fc5_HelpInfo.xml" />
<file src="New-CustomErrorRecord.ps1" target="New-CustomErrorRecord.ps1" />
<file src="Format-Xml.ps1" target="Format-Xml.ps1" />
<file src="ConvertFrom-UnicodeHexEncoding.ps1" target="ConvertFrom-UnicodeHexEncoding.ps1" />
<file src="ConvertFrom-SecureStringDF.ps1" target="ConvertFrom-SecureStringDF.ps1" />
<file src="New-SecurePassword.ps1" target="New-SecurePassword.ps1" />
<file src="ConvertTo-UrlEncoded.ps1" target="ConvertTo-UrlEncoded.ps1" />
<file src="ConvertFrom-UrlEncoded.ps1" target="ConvertFrom-UrlEncoded.ps1" />
<file src="ConvertTo-Base64.ps1" target="ConvertTo-Base64.ps1" />
<file src="ConvertFrom-Base64.ps1" target="ConvertFrom-Base64.ps1" />
<file src="Get-ComObjectType.ps1" target="Get-ComObjectType.ps1" />
<file src="Test-StringPattern.ps1" target="Test-StringPattern.ps1" />
<file src="Import-Credential.ps1" target="Import-Credential.ps1" />
<file src="Export-Credential.ps1" target="Export-Credential.ps1" />
<file src="Get-Constructor.ps1" target="Get-Constructor.ps1" />
<file src="Set-SslSecurityPolicy.ps1" target="Set-SslSecurityPolicy.ps1" />
<file src="New-ActivityProgress.ps1" target="New-ActivityProgress.ps1" />
<file src="Set-ActivityProgress.ps1" target="Set-ActivityProgress.ps1" />
<file src="Remove-ActivityProgress.ps1" target="Remove-ActivityProgress.ps1" />
<file src="ConvertFrom-CmdletHelp.ps1" target="ConvertFrom-CmdletHelp.ps1" />
<file src="Expand-CompressedItem.ps1" target="Expand-CompressedItem.ps1" />
<file src="Format-IpAddress.ps1" target="Format-IpAddress.ps1" />
<file src="ConvertFrom-PSCustomObject.ps1" target="ConvertFrom-PSCustomObject.ps1" />
<file src="ConvertFrom-Hashtable.ps1" target="ConvertFrom-Hashtable.ps1" />
<file src="Test-CmdletDocumentation.ps1" target="Test-CmdletDocumentation.ps1" />
<file src="Assert-CmdletDocumentation.ps1" target="Assert-CmdletDocumentation.ps1" />
</files>
</package>
function Update-Manifest {
<#
.SYNOPSIS
Updates the revision number of a PowerShell manifest.
.DESCRIPTION
Updates the revision number of a PowerShell manifest.
The revision of the specified manifest is checked against the files in the module folder. If the revision is older than the last write time the revision is updated.
.EXAMPLE
Update-Signature C:\scripts\myScript.ps1
Checks the specified manifest.
.EXAMPLE
Update-Signature C:\scripts
Checks all manifest in the specified folder recursively.
#>
[CmdletBinding(
SupportsShouldProcess = $true
,
ConfirmImpact = "Low"
,
DefaultParameterSetName = 'path'
)]
PARAM
(
# Specifies a path to search for manifest files
[ValidateScript( { Test-Path($_) -PathType Container; } )]
[Parameter(Mandatory = $false, ParameterSetName = 'path')]
[System.IO.DirectoryInfo] $Path = 'C:\Github'
,
# Specifies one or more manifest files to check
[ValidateScript( { if($_) { foreach($item in $_) {Test-Path($item) -PathType Leaf -Include "*.psd1"; } } else { $true } } )]
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = 'file')]
[AllowNull()]
[Alias('File')]
$InputObject
,
[Parameter(Mandatory = $false)]
[switch] $IncrementVersionMajor = $false
,
[Parameter(Mandatory = $false)]
[switch] $IncrementVersionMinor = $false
,
[Parameter(Mandatory = $false)]
[switch] $IncrementVersionBuild = $false
,
[Parameter(Mandatory = $false)]
[switch] $UpdateRevision = $true
)
BEGIN
{
if($PSCmdlet.ParameterSetName -eq 'path')
{
$InputObjectTemp = (Get-ChildItem $Path -Include "*.psd1" -Recurse);
if($InputObjectTemp)
{
$InputObject = $InputObjectTemp;
Remove-Variable InputObjectTemp;
}
}
}
# BEGIN
PROCESS
{
foreach($Object in $InputObject)
{
try
{
$Version = (Get-Content -Raw $Object | iex).ModuleVersion -as [Version];
}
catch
{
$Version = (Get-Content -Raw $Object | iex).ModuleVersion -as [Version];
}
$VersionNew = $Version;
$Object = Get-Item $Object;
if($UpdateRevision)
{
Write-Host ("{0}: Comparing against Version.Revision '{1}'" -f $Object.FullName, $Version.Revision);
$LastWriteTimes = (Get-ChildItem (Split-Path $Object)).LastWriteTime;
foreach($LastWriteTime in $LastWriteTimes)
{
if( ($LastWriteTime.ToString('yyyyMMdd') -as [int]) -gt $Version.Revision)
{
$VersionNew = New-Object Version($VersionNew.Major, $VersionNew.Minor, $VersionNew.Build, ($LastWriteTime.ToString('yyyyMMdd') -as [int]));
}
}
}
if($IncrementVersionMajor)
{
Write-Host ("{0}: Incrementing Version.Major '{1}'" -f $Object.FullName, $Version.Major);
$VersionNew = New-Object Version(($VersionNew.Major +1), $VersionNew.Minor, $VersionNew.Build, $VersionNew.Revision);
}
if($IncrementVersionMinor)
{
Write-Host ("{0}: Incrementing Version.Minor '{1}'" -f $Object.FullName, $Version.Minor);
$VersionNew = New-Object Version($VersionNew.Major, ($VersionNew.Minor +1), $VersionNew.Build, $VersionNew.Revision);
}
if($IncrementVersionBuild)
{
Write-Host ("{0}: Incrementing Version.Build '{1}'" -f $Object.FullName, $Version.Build);
$VersionNew = New-Object Version($VersionNew.Major, $VersionNew.Minor, ($VersionNew.Build +1), $VersionNew.Revision);
}
if($Version.ToString() -ne $VersionNew.ToString())
{
if(!$PSCmdlet.ShouldProcess($Object))
{
continue;
}
Write-Host ("{0}: Updating manifest revision from '{1}' to '{2}' ..." -f $Object, $Version.ToString(), $VersionNew.ToString());
(Get-Content -Raw $Object).Replace($Version.ToString(), $VersionNew.ToString()) | Out-File -Encoding default $Object -Confirm:$false;
$null = Update-Signature $Object.FullName -Confirm:$false;
$Object.FullName;
}
}
}
# PROCESS
END
{
}
# END
} # function
if($MyInvocation.ScriptName -And ('.' -ne $MyInvocation.InvocationName)) { Export-ModuleMember -Function Update-Manifest; }
#
# Copyright 2014-2015 Ronald Rink, d-fens GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
function Update-Nuspec {
<#
.SYNOPSIS
Updates the nuspec file of a PowerShell module.
.DESCRIPTION
Updates the nuspec file of a PowerShell module.
Checks the version and revision number of a PowerShell module manifest and
create a new nuspec file if necessary. The new nuspec file will be built from
a previous existing nuspec (with the highest available version number).
All files referenced in the manifest will be inserted into the nusepc file.
Optionally a nupkg will be created as well.
.EXAMPLE
Update-Nuspec C:\scripts\biz.dfch.PS.Module\biz.dfch.PS.Module.psd1
Updates the given module manifest with a new nuspec file and also creates a package from it.
.EXAMPLE
Update-Nuspec C:\scripts
Updates all module manifests in the specified path with a new nuspec file and also creates a package from it.
#>
[CmdletBinding(
SupportsShouldProcess = $true
,
ConfirmImpact = "Low"
,
DefaultParameterSetName = 'path'
)]
PARAM
(
# Specifies a path to nuspec files to update
[ValidateScript( { Test-Path($_) -PathType Container; } )]
[Parameter(Mandatory = $false, ParameterSetName = 'path')]
[System.IO.DirectoryInfo] $Path = 'C:\Github'
,
# Specifies one ore more nuspec files to update
[ValidateScript( { if($_) { foreach($item in $_) {Test-Path($item) -PathType Leaf; } } else { $true } } )]
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = 'file')]
[AllowNull()]
[Alias('File')]
$InputObject
,
# Specify whether to also create a package from the nuspec file
[Parameter(Mandatory = $false)]
[Alias('CreatePackage')]
[switch] $Pack = $true
,
# Specify whether to update an existing package
[Parameter(Mandatory = $false)]
[switch] $Force = $false
,
# Specifies the path to the NuGet.exe
[ValidateScript( { Test-Path($_); } )]
[Parameter(Mandatory = $false)]
[string] $NuGetExe = 'C:\SOFTWARE\NuGet.exe'
)
if($PSCmdlet.ParameterSetName -eq 'path')
{
$InputObjectTemp = (Get-ChildItem $Path -Include "*.psd1" -Recurse);
if($InputObjectTemp)
{
$InputObject = $InputObjectTemp;
Remove-Variable InputObjectTemp;
}
}
foreach($Object in $InputObject)
{
$Object = Get-Item $Object;
$Manifest = (Get-Content -Raw $Object) | iex;
$Version = (($Manifest).ModuleVersion -as [Version]);
$NuspecVersion = '{0}.{1}.{2}' -f $Version.Major, $Version.Minor, $Version.Build;
$Revision = $Version.Revision;
$NuspecPathAndFile = Join-Path -Path (Split-Path $Object -Parent) -ChildPath ('{0}.{1}.nuspec' -f $Object.BaseName, $NuspecVersion);
if(Test-Path $NuspecPathAndFile)
{
[xml] $NuGetXml = Get-Content -Raw $NuspecPathAndFile;
if($NuGetXml.package.metadata.releaseNotes -notmatch $Version.Revision)
{
Write-Warning ("{0}: NuGet package already exists, but does not contain correct Revision '{1}'." -f $NuspecPathAndFile, $Revision);
if(!$Force)
{
continue;
}
}
Write-Host ("{0}: NuGet package already exists." -f $NuspecPathAndFile);
if(!$Force)
{
continue;
}
}
$NuspecPrevious = Get-ChildItem -Path (Split-Path $Object -Parent) -Include "*.nuspec" -Recurse | sort -Property Name, LastWriteTime -Descending | Select -First 1;
if(!$NuspecPrevious)
{
Write-Warning ("{0}: No previous NuGet package exists. Skipping ..." -f $NuspecPathAndFile);
continue;
}
[xml] $NuGetXml = Get-Content -Raw $NuspecPrevious;
# set version
$NuGetXml.package.metadata.version = $NuspecVersion;
# set revision
$NuGetXml.package.metadata.releaseNotes = $Revision.ToString();
# set the description
$NuGetXml.package.metadata.description = (Get-Content -Raw (Join-Path -Path (Split-Path $Object -Parent) -ChildPath 'README.md')).ToString();
# set the files to be included
try
{
$NuGetXml.package.files.RemoveAll();
$xmlFiles = $NuGetXml.package.SelectSingleNode('files');
}
catch
{
$xmlFiles = $NuGetXml.CreateElement('files');
}
foreach($item in $Manifest.RootModule,$Object.Name)
{
$xmlFile = $NuGetXml.CreateElement('file');
$xmlSrc = $NuGetXml.CreateAttribute('src');
$xmlSrc.Value = $item;
$xmlTarget = $NuGetXml.CreateAttribute('target');
$xmlTarget.Value = $item;
$null = $xmlFile.Attributes.Append($xmlSrc);
$null = $xmlFile.Attributes.Append($xmlTarget);
$null = $xmlFiles.AppendChild($xmlFile);
}
foreach($item in $Manifest.FileList)
{
$xmlFile = $NuGetXml.CreateElement('file');
$xmlSrc = $NuGetXml.CreateAttribute('src');
$xmlSrc.Value = $item;
$xmlTarget = $NuGetXml.CreateAttribute('target');
$xmlTarget.Value = $item;
$null = $xmlFile.Attributes.Append($xmlSrc);
$null = $xmlFile.Attributes.Append($xmlTarget);
$null = $xmlFiles.AppendChild($xmlFile);
}
foreach($item in $Manifest.NestedModules)
{
$xmlFile = $NuGetXml.CreateElement('file');
$xmlSrc = $NuGetXml.CreateAttribute('src');
$xmlSrc.Value = $item;
$xmlTarget = $NuGetXml.CreateAttribute('target');
$xmlTarget.Value = $item;
$null = $xmlFile.Attributes.Append($xmlSrc);
$null = $xmlFile.Attributes.Append($xmlTarget);
$null = $xmlFiles.AppendChild($xmlFile);
}
$null = $NuGetXml.package.AppendChild($xmlFiles);
if(!$PSCmdlet.ShouldProcess($Object))
{
continue;
}
Write-Host ("{0}: Creating NuSpec file ..." -f $NuspecPathAndFile);
$NuGetXml.OuterXml | fx | Out-File -Encoding default $NuspecPathAndFile;
if($Pack)
{
Push-Location (Split-Path $Object -Parent);
Write-Host ("{0}: Creating NuPkg file ..." -f $NuspecPathAndFile);
Start-Process $NuGetExe -ArgumentList @( ("pack {0}" -f $NuspecPathAndFile),"-NonInteractive",'-Verbosity quiet') -NoNewWindow -Wait;
Pop-Location;
}
}
} # function
if($MyInvocation.ScriptName -And ('.' -ne $MyInvocation.InvocationName)) { Export-ModuleMember -Function Update-Nuspec; }
#
# Copyright 2014-2015 Ronald Rink, d-fens GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#Requires -Modules Microsoft.PowerShell.Security
function Update-Signature {
<#
.SYNOPSIS
Updates the digital signature of PowerShell scripts.
.DESCRIPTION
Updates the digital signature of PowerShell scripts.
You can either sign all scripts in a given folder or only individual files.
.EXAMPLE
Update-Signature C:\scripts\myScript.ps1
Signs the specified script with the default certificate and timestamps it.
.EXAMPLE
Update-Signature C:\scripts
Signs the all scripts in the specified folder with the default certificate and timestamps it.
#>
[CmdletBinding(
SupportsShouldProcess = $true
,
ConfirmImpact = "Low"
,
DefaultParameterSetName = 'path'
)]
PARAM
(
# The path to script files to sign
[ValidateScript( { Test-Path($_) -PathType Container; } )]
[Parameter(Mandatory = $false, ParameterSetName = 'path')]
[System.IO.DirectoryInfo] $Path = 'C:\Github'
,
# A script file or array of script files to sign
[ValidateScript( { if($_) { foreach($item in $_) {Test-Path($item) -PathType Leaf -Include $IncludeExtensions; } } else { $true } } )]
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = 'file')]
[AllowNull()]
[Alias('File')]
$InputObject
,
# The certificate to use for signing the specified scripts
[Parameter(Mandatory = $false, Position = 1)]
$Cert = (Select-Object -First 1 -InputObject (Get-ChildItem -Path cert:\CurrentUser\my -CodeSigningCert))
,
# Specify wheter to timestamp (countersign) the script files
[Parameter(Mandatory = $false)]
[Alias('TimeStamp')]
[switch] $CounterSign = $true
,
# The timestamp server url
[Parameter(Mandatory = $false, Position = 2)]
[Uri] $TimestampServer = 'http://timestamp.globalsign.com/scripts/timstamp.dll'
,
# File extensions of the script files to sign
[Parameter(Mandatory = $false)]
$IncludeExtensions = @('*.ps1','*.psm1','*.psd1','*.dll','*.exe')
)
if($PSCmdlet.ParameterSetName -eq 'path')
{
$InputObjectTemp = (Get-ChildItem $Path -Include $IncludeExtensions -Recurse | Get-AuthenticodeSignature |? { ($_.Status -eq 'HashMismatch') -Or (($_.TimeStamperCertificate -eq $null) -And ($_.Status -eq 'Valid')) }).Path;
if($InputObjectTemp)
{
$InputObject = $InputObjectTemp;
Remove-Variable InputObjectTemp;
}
}
foreach($Object in $InputObject)
{
if(!$PSCmdlet.ShouldProcess($Object))
{
continue;
}
if($CounterSign)
{
Set-AuthenticodeSignature $Object -Certificate $cert -TimestampServer $TimestampServer -Confirm:$false;
}
else
{
Set-AuthenticodeSignature $Object -Certificate $cert -Confirm:$false;
}
}
} # function
if($MyInvocation.ScriptName -And ('.' -ne $MyInvocation.InvocationName)) { Export-ModuleMember -Function Update-Signature; }
#
# Copyright 2014-2015 Ronald Rink, d-fens GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment