Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions PowerShell/Devolutions.Psign/Devolutions.Psign.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@
'Unprotect-PsignSignature'
)
FunctionsToExport = @()
AliasesToExport = @(
'Get-PortableSignature',
'Set-PortableSignature'
)
AliasesToExport = @()
PrivateData = @{
PSData = @{
Tags = @('Authenticode', 'CodeSigning', 'Portable', 'psign')
Expand Down
14 changes: 7 additions & 7 deletions PowerShell/Devolutions.Psign/Devolutions.Psign.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Argument completers for common parameters

Register-ArgumentCompleter -CommandName Get-PsignSignature, Get-PortableSignature, Set-PsignSignature, Set-PortableSignature, Protect-PsignModule -ParameterName Thumbprint -ScriptBlock {
Register-ArgumentCompleter -CommandName Get-PsignSignature, Set-PsignSignature, Protect-PsignModule -ParameterName Thumbprint -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
$baseDir = if ($fakeBoundParameters.ContainsKey('CertStoreDirectory')) {
$fakeBoundParameters['CertStoreDirectory']
Expand All @@ -28,35 +28,35 @@ Register-ArgumentCompleter -CommandName Get-PsignSignature, Get-PortableSignatur
}
}

Register-ArgumentCompleter -CommandName Set-PsignSignature, Set-PortableSignature, Protect-PsignModule -ParameterName StoreName -ScriptBlock {
Register-ArgumentCompleter -CommandName Set-PsignSignature, Protect-PsignModule -ParameterName StoreName -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
@('MY', 'Root', 'CA', 'Trust', 'Disallowed') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
@('MY', 'Root', 'CA', 'Trust', 'TrustedPublisher', 'Disallowed') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}

Register-ArgumentCompleter -CommandName Set-PsignSignature, Set-PortableSignature, Protect-PsignModule -ParameterName HashAlgorithm -ScriptBlock {
Register-ArgumentCompleter -CommandName Set-PsignSignature, Protect-PsignModule -ParameterName HashAlgorithm -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
@('Sha256', 'Sha384', 'Sha512') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}

Register-ArgumentCompleter -CommandName Set-PsignSignature, Set-PortableSignature, Protect-PsignModule -ParameterName IncludeChain -ScriptBlock {
Register-ArgumentCompleter -CommandName Set-PsignSignature, Protect-PsignModule -ParameterName IncludeChain -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
@('Signer', 'NotRoot', 'All') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}

Register-ArgumentCompleter -CommandName Set-PsignSignature, Set-PortableSignature, Protect-PsignModule -ParameterName TimestampHashAlgorithm -ScriptBlock {
Register-ArgumentCompleter -CommandName Set-PsignSignature, Protect-PsignModule -ParameterName TimestampHashAlgorithm -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
@('Sha1', 'Sha256', 'Sha384', 'Sha512') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}

Register-ArgumentCompleter -CommandName Get-PsignSignature, Get-PortableSignature -ParameterName RevocationMode -ScriptBlock {
Register-ArgumentCompleter -CommandName Get-PsignSignature -ParameterName RevocationMode -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
@('Off', 'BestEffort', 'Require') | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
Expand Down
8 changes: 8 additions & 0 deletions PowerShell/tests/PortableCertStore.Provider.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Describe 'pcert:\ Provider - Navigation' {
$names | Should -Contain 'MY'
$names | Should -Contain 'Root'
$names | Should -Contain 'CA'
$names | Should -Contain 'TrustedPublisher'
}

It 'can cd into scope and store' {
Expand Down Expand Up @@ -119,6 +120,13 @@ Describe 'pcert:\ Provider - Certificate CRUD' {
$copied.Thumbprint | Should -Be $script:TestCert.Thumbprint
}

It 'can use TrustedPublisher as a well-known store' {
Copy-Item "pcert:\CurrentUser\MY\$($script:TestCert.Thumbprint)" pcert:\CurrentUser\TrustedPublisher
Test-Path "pcert:\CurrentUser\TrustedPublisher\$($script:TestCert.Thumbprint)" | Should -BeTrue
$copied = Get-Item "pcert:\CurrentUser\TrustedPublisher\$($script:TestCert.Thumbprint)"
$copied.Thumbprint | Should -Be $script:TestCert.Thumbprint
}

It 'can remove a certificate' {
# Remove from Root (the copy)
Remove-Item "pcert:\CurrentUser\Root\$($script:TestCert.Thumbprint)"
Expand Down
15 changes: 7 additions & 8 deletions PowerShell/tests/PortableSignature.Compatibility.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
Set-StrictMode -Version Latest

function script:Ensure-PortableSignatureModule {
if (-not (Get-Command Get-PsignSignature -ErrorAction SilentlyContinue)) {
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$modulePath = Join-Path (Join-Path $repoRoot 'PowerShell\Devolutions.Psign') 'Devolutions.Psign.psd1'
Import-Module $modulePath -Force
}
Remove-Module Devolutions.Psign -Force -ErrorAction SilentlyContinue
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$modulePath = Join-Path (Join-Path $repoRoot 'PowerShell\Devolutions.Psign') 'Devolutions.Psign.psd1'
Import-Module $modulePath -Force
}

Describe 'Portable PowerShell Authenticode compatibility' {
Expand Down Expand Up @@ -39,9 +38,9 @@ Describe 'Portable PowerShell Authenticode compatibility' {
}
}

It 'preserves backward-compatible aliases Get-PortableSignature and Set-PortableSignature' {
Get-Command Get-PortableSignature -ErrorAction Stop | Should -Not -BeNullOrEmpty
Get-Command Set-PortableSignature -ErrorAction Stop | Should -Not -BeNullOrEmpty
It 'does not export legacy PortableSignature aliases' {
Get-Command Get-PortableSignature -ErrorAction SilentlyContinue | Should -BeNullOrEmpty
Get-Command Set-PortableSignature -ErrorAction SilentlyContinue | Should -BeNullOrEmpty
}

It 'exposes built-in enum types on compatibility properties' {
Expand Down
58 changes: 55 additions & 3 deletions PowerShell/tests/ProtectPsignModule.Expanded.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,22 @@ BeforeAll {
[System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $script:PfxPassword))

function script:New-TestModule {
param([string]$Name, [switch]$WithManifest, [int]$ExtraFiles = 0)
$modDir = Join-Path $script:TestDir $Name
param(
[string]$Name,
[switch]$WithManifest,
[int]$ExtraFiles = 0,
[string]$ModuleVersion = '1.0.0',
[string]$Directory
)
$modDir = if ($Directory) { $Directory } else { Join-Path $script:TestDir $Name }
New-Item -ItemType Directory -Path $modDir -Force | Out-Null

Set-Content -LiteralPath (Join-Path $modDir "$Name.psm1") -Value "function Get-$Name { '$Name' }" -Encoding UTF8

if ($WithManifest) {
$psdContent = @"
@{
ModuleVersion = '1.0.0'
ModuleVersion = '$ModuleVersion'
RootModule = '$Name.psm1'
FunctionsToExport = @('Get-$Name')
}
Expand Down Expand Up @@ -131,6 +137,52 @@ Describe 'Protect-PsignModule -IncludeUnreferenced' {
}
}

Describe 'Protect-PsignModule pipeline input' {
It 'accepts Get-Module output and signs the piped module version' {
$moduleName = 'PipeProtect'
$modulePathRoot = Join-Path $script:TestDir 'psmodulepath-protect'
$moduleVersionRoot = Join-Path $modulePathRoot $moduleName
$oldModuleDir = Join-Path $moduleVersionRoot '1.0.0'
$newModuleDir = Join-Path $moduleVersionRoot '2.0.0'
$null = New-TestModule -Name $moduleName -WithManifest -Directory $oldModuleDir
$null = New-TestModule -Name $moduleName -WithManifest -ModuleVersion '2.0.0' -Directory $newModuleDir

$originalPSModulePath = $env:PSModulePath
try {
$env:PSModulePath = "$modulePathRoot$([System.IO.Path]::PathSeparator)$originalPSModulePath"

$module = Get-Module -ListAvailable -Name $moduleName |
Where-Object Version -eq ([version]'1.0.0')
$result = $module | Protect-PsignModule -CertificatePath $script:CertPath -PrivateKeyPath $script:KeyPath
$result.ModuleName | Should -Be $moduleName
$result.ModulePath | Should -Be $oldModuleDir
$result.Succeeded | Should -Be $result.TotalFiles

(Test-PsignModule -Path $oldModuleDir -Policy AllSigned -SkipTrust).Valid | Should -BeTrue
(Test-PsignModule -Path $newModuleDir -Policy AllSigned -SkipTrust).Valid | Should -BeFalse
} finally {
$env:PSModulePath = $originalPSModulePath
}
}

It 'accepts Get-InstalledModule-style output with InstalledLocation' {
$moduleName = 'InstalledProtect'
$modDir = New-TestModule -Name $moduleName -WithManifest -ModuleVersion '2.0.0'
$installedModule = [pscustomobject]@{
Name = $moduleName
Version = '2.0.0'
InstalledLocation = $modDir
Repository = 'TestRepository'
}

$result = $installedModule | Protect-PsignModule -CertificatePath $script:CertPath -PrivateKeyPath $script:KeyPath
$result.ModuleName | Should -Be $moduleName
$result.ModulePath | Should -Be $modDir
$result.Succeeded | Should -Be $result.TotalFiles
(Test-PsignModule -Path $modDir -Policy AllSigned -SkipTrust).Valid | Should -BeTrue
}
}

Describe 'Protect-PsignModule result properties' {
It 'returns PsignModuleSigningResult with per-file details' {
$modDir = New-TestModule -Name 'ResultProps' -WithManifest -ExtraFiles 1
Expand Down
Loading