diff --git a/azure-pipelines-publish.yml b/azure-pipelines-publish.yml new file mode 100644 index 000000000..5a782ded2 --- /dev/null +++ b/azure-pipelines-publish.yml @@ -0,0 +1,21 @@ +trigger: none + +variables: + - group: signing + +jobs: + - job: build + workspace: + clean: all + pool: + vmImage: windows-2022 + timeoutInMinutes: 60 + steps: + - task: AzureCLI@2 + displayName: Publish + inputs: + azureSubscription: CodeSigner + scriptType: ps + scriptLocation: inlineScript + inlineScript: | + .\publish\release.ps1 -PsGalleryApiKey '$(PsGalleryApiKey)' -NugetApiKey '$(NugetApiKey)' -ChocolateyApiKey '$(ChocolateyApiKey)' -TenantId '$(TenantId)' -VaultUrl '$(SigningVaultURL)' -CertificateName '$(SigningCertName)' diff --git a/publish/release.ps1 b/publish/release.ps1 index 05249a9a1..5a1e6837c 100644 --- a/publish/release.ps1 +++ b/publish/release.ps1 @@ -4,7 +4,9 @@ param ( [String] $PsGalleryApiKey, [String] $NugetApiKey, [String] $ChocolateyApiKey, - [String] $CertificateThumbprint = '2FCC9148EC2C9AB951C6F9654C0D2ED16AF27738', + [String] $TenantId, + [String] $VaultUrl, + [String] $CertificateName, [Switch] $Force ) @@ -52,7 +54,7 @@ if ((Get-Item $bin/Pester.psm1).Length -lt 50KB) { throw "Module is too small, are you publishing non-inlined module?" } -& "$PSScriptRoot/signModule.ps1" -Thumbprint $CertificateThumbprint -Path $bin +& "$PSScriptRoot/signModule.ps1" -VaultUrl $VaultUrl -TenantId $TenantId -CertificateName $CertificateName -Path $bin $files = @( 'Pester.ps1' @@ -128,8 +130,23 @@ Get-ChildItem -Path $bin -Filter *.dll -Recurse | ForEach-Object { } & nuget pack "$PSScriptRoot/Pester.nuspec" -OutputDirectory $nugetDir -NoPackageAnalysis -version $version -$nupkg = (Join-Path $nugetDir "Pester.$version.nupkg") -& nuget sign $nupkg -CertificateFingerprint $CertificateThumbprint -Timestamper "http://timestamp.digicert.com" +[string] $nupkg = (Join-Path $nugetDir "Pester.$version.nupkg") + +dotnet tool install --global NuGetKeyVaultSignTool +if (0 -ne $LASTEXITCODE) { + throw "Failed to install NuGetKeyVaultSignTool" +} + +Write-Host "Nuget path: $nupkg" +NuGetKeyVaultSignTool sign -kvu $VaultUrl -kvm -kvc $CertificateName -kvt $TenantId -own "nohwnd,fflaten" -tr "http://timestamp.digicert.com" $nupkg +if (0 -ne $LASTEXITCODE) { + throw "Failed to sign nupkg" +} + +NuGetKeyVaultSignTool verify $nupkg +if (0 -ne $LASTEXITCODE) { + throw "Failed to verify nupkg" +} Publish-Module -Path $psGalleryDir -NuGetApiKey $PsGalleryApiKey -Verbose -Force diff --git a/publish/signModule.ps1 b/publish/signModule.ps1 index 8d1c66e50..64ef98479 100644 --- a/publish/signModule.ps1 +++ b/publish/signModule.ps1 @@ -1,17 +1,11 @@ -param($Thumbprint, $Path) +param( + [String] $TenantId, + [String] $VaultUrl, + [String] $CertificateName, + [String] $Path +) $ErrorActionPreference = 'Stop' -$cert = Get-ChildItem Cert:\CurrentUser\My | - Where-Object Thumbprint -eq $Thumbprint - -if ($null -eq $cert) { - throw "No certificate was found." -} - -if (@($cert).Length -gt 1) { - throw "More than one cerfificate with the given thumbprint was found." -} - "Signing Files" $files = Get-ChildItem -Recurse -ErrorAction SilentlyContinue $Path | Where-Object { $_.Extension -in ".ps1", ".psm1", ".psd1", ".ps1xml", ".dll" } | @@ -28,14 +22,16 @@ if (-not @($filesToSign)) { return "There are no files to sign, all the files in the repository are already signed." } -$results = $filesToSign | - ForEach-Object { - $r = Set-AuthenticodeSignature $_ -Certificate $cert -TimestampServer 'http://timestamp.digicert.com' -ErrorAction Stop - $r | Out-String | Write-Host - $r - } +dotnet tool install --global AzureSignTool +if (0 -ne $LASTEXITCODE) { + throw "Failed to install AzureSignTool" +} +azuresigntool sign -kvu $VaultUrl -kvm -kvc $CertificateName -kvt $TenantId -du "https://pester.dev" -tr "http://timestamp.digicert.com" -v $filesToSign +if (0 -ne $LASTEXITCODE) { + throw "Failed to sign files" +} -$failed = $results | Where-Object { $_.Status -ne "Valid" } +$failed = $filesToSign | Get-AuthenticodeSignature | Where-Object { $_.Status -ne "Valid" } if ($failed) { throw "Failed signing $($failed.Path -join "`n")"