TrustedSigning.psm1
using namespace System.Collections.Generic using namespace System.IO function Invoke-TrustedSigning { param ( [Parameter(Mandatory)] [string]$Endpoint, [Parameter(Mandatory)] [string]$CodeSigningAccountName, [Parameter(Mandatory)] [string]$CertificateProfileName, [Parameter()] [AllowEmptyString()] [string]$Files, [Parameter()] [AllowEmptyString()] [string]$FilesFolder, [Parameter()] [AllowEmptyString()] [string]$FilesFolderFilter, [Parameter()] [switch]$FilesFolderRecurse = $false, [Parameter()] [AllowNull()] [int]$FilesFolderDepth, [Parameter()] [AllowEmptyString()] [string]$FilesCatalog, [Parameter(Mandatory)] [string]$FileDigest, [Parameter()] [AllowEmptyString()] [string]$TimestampRfc3161, [Parameter()] [AllowEmptyString()] [string]$TimestampDigest, [Parameter()] [switch]$AppendSignature = $false, [Parameter()] [AllowEmptyString()] [string]$Description, [Parameter()] [AllowEmptyString()] [string]$DescriptionUrl, [Parameter()] [AllowEmptyString()] [string]$GenerateDigestPath, [Parameter()] [switch]$GenerateDigestXml = $false, [Parameter()] [AllowEmptyString()] [string]$IngestDigestPath, [Parameter()] [switch]$SignDigest = $false, [Parameter()] [switch]$GeneratePageHashes = $false, [Parameter()] [switch]$SuppressPageHashes = $false, [Parameter()] [switch]$GeneratePkcs7 = $false, [Parameter()] [AllowEmptyString()] [string]$Pkcs7Options, [Parameter()] [AllowEmptyString()] [string]$Pkcs7Oid, [Parameter()] [AllowEmptyString()] [string]$EnhancedKeyUsage, [Parameter()] [switch]$ExcludeEnvironmentCredential = $false, [Parameter()] [switch]$ExcludeWorkloadIdentityCredential = $false, [Parameter()] [switch]$ExcludeManagedIdentityCredential = $false, [Parameter()] [switch]$ExcludeSharedTokenCacheCredential = $false, [Parameter()] [switch]$ExcludeVisualStudioCredential = $false, [Parameter()] [switch]$ExcludeVisualStudioCodeCredential = $false, [Parameter()] [switch]$ExcludeAzureCliCredential = $false, [Parameter()] [switch]$ExcludeAzurePowerShellCredential = $false, [Parameter()] [switch]$ExcludeAzureDeveloperCliCredential = $false, [Parameter()] [switch]$ExcludeInteractiveBrowserCredential = $false, [Parameter()] [int]$Timeout = 300, [Parameter()] [ValidateRange(0, 30000)] [int]$BatchSize = 10000 ) # Install required packages unless they already exist. Write-Information -MessageData "Checking for required dependencies." -InformationAction Continue $dependencies = Get-EveryDependency -Verbose $dlibFolderPath = $dependencies.DlibFolderPath $signToolFolderPath = $dependencies.SignToolFolderPath # Create the Trusted Signing metadata.json file that is passed to signtool.exe. $metadataFilePath = Join-Path -Path $dlibFolderPath -ChildPath "metadata.json" Write-Information -MessageData "`nCreating metadata file: $metadataFilePath" -InformationAction Continue $convertToMetadataJsonParams = @{ Endpoint = $Endpoint CodeSigningAccountName = $CodeSigningAccountName CertificateProfileName = $CertificateProfileName ExcludeEnvironmentCredential = $ExcludeEnvironmentCredential ExcludeWorkloadIdentityCredential = $ExcludeWorkloadIdentityCredential ExcludeManagedIdentityCredential = $ExcludeManagedIdentityCredential ExcludeSharedTokenCacheCredential = $ExcludeSharedTokenCacheCredential ExcludeVisualStudioCredential = $ExcludeVisualStudioCredential ExcludeVisualStudioCodeCredential = $ExcludeVisualStudioCodeCredential ExcludeAzureCliCredential = $ExcludeAzureCliCredential ExcludeAzurePowerShellCredential = $ExcludeAzurePowerShellCredential ExcludeAzureDeveloperCliCredential = $ExcludeAzureDeveloperCliCredential ExcludeInteractiveBrowserCredential = $ExcludeInteractiveBrowserCredential } $metadataJson = ConvertTo-MetadataJson @convertToMetadataJsonParams [File]::WriteAllLines($metadataFilePath, $metadataJson) # Get the list of files to be signed from the files list, files folder and the # catalog file. # Files list. Write-Information -MessageData "`nGetting the list of files to be signed." -InformationAction Continue if ([string]::IsNullOrWhiteSpace($Files)) { Write-Information -MessageData "`tNo files list was provided." -InformationAction Continue $listedFiles = [List[string]]::new() } else { Write-Information -MessageData "`tGetting files from list." -InformationAction Continue $listedFiles = Get-FileList -Files $Files } Write-Information -MessageData "`tListed files: $($listedFiles.Count)" -InformationAction Continue foreach ($file in $listedFiles) { Write-Information -MessageData "`t`t$file" -InformationAction Continue } # Files folder. if ([string]::IsNullOrWhiteSpace($FilesFolder)) { Write-Information -MessageData "`n`tNo files folder was provided." -InformationAction Continue $filteredFiles = [List[string]]::new() } else { Write-Information -MessageData "`n`tGetting files from folder: $FilesFolder" -InformationAction Continue Write-Information -MessageData "`tFilter: $FilesFolderFilter" -InformationAction Continue $getFilteredFileListParams = @{ Path = $FilesFolder Filter = $FilesFolderFilter Recurse = $FilesFolderRecurse Depth = $FilesFolderDepth } $filteredFiles = Get-FilteredFileList @getFilteredFileListParams } Write-Information -MessageData "`tFiltered files: $($filteredFiles.Count)" -InformationAction Continue foreach ($file in $filteredFiles) { Write-Information -MessageData "`t`t$file" -InformationAction Continue } # Catalog file. if ([string]::IsNullOrWhiteSpace($FilesCatalog)) { Write-Information -MessageData "`n`tNo catalog file was provided." -InformationAction Continue $catalogFiles = [List[string]]::new() } else { Write-Information -MessageData "`n`tGetting files from catalog file: $FilesCatalog" -InformationAction Continue $catalogFiles = Get-CatalogFileList -Path $FilesCatalog } Write-Information -MessageData "`tCatalog files: $($catalogFiles.Count)" -InformationAction Continue foreach ($file in $catalogFiles) { Write-Information -MessageData "`t`t$file" -InformationAction Continue } # Combine the list of files to be signed. Write-Information -MessageData "`nFormatting the list of files to be signed." -InformationAction Continue $formatFileListParams = @{ ListedFiles = $listedFiles FilteredFiles = $filteredFiles CatalogFiles = $catalogFiles } $formattedFileList = Format-FileList @formatFileListParams # Batch the list of files to be signed. Write-Information -MessageData "`nBatching the list of files to be signed." -InformationAction Continue $batchedFileLists = Split-FileList -FormattedFiles $formattedFileList -BatchSize $BatchSize if ($batchedFileLists.Count -eq 0) { throw "No files were found to sign" } # Sign the files in each batch. $batchCounter = 1 foreach ($batchedFileList in $batchedFileLists) { Write-Information -MessageData "`nSigning file batch $($batchCounter) of $($batchedFileLists.Count)." -InformationAction Continue # Format the arguments that will be passed to signtool.exe. $dlibFilePath = Join-Path -Path $dlibFolderPath -ChildPath "Azure.CodeSigning.Dlib.dll" $formatSignToolArgumentListParams = @{ FileList = $batchedFileList FileDigest = $FileDigest TimestampRfc3161 = $TimestampRfc3161 TimestampDigest = $TimestampDigest DlibFilePath = $dlibFilePath MetadataFilePath = $metadataFilePath AppendSignature = $AppendSignature Description = $Description DescriptionUrl = $DescriptionUrl GenerateDigestPath = $GenerateDigestPath GenerateDigestXml = $GenerateDigestXml IngestDigestPath = $IngestDigestPath SignDigest = $SignDigest GeneratePageHashes = $GeneratePageHashes SuppressPageHashes = $SuppressPageHashes GeneratePkcs7 = $GeneratePkcs7 Pkcs7Options = $Pkcs7Options Pkcs7Oid = $Pkcs7Oid EnhancedKeyUsage = $EnhancedKeyUsage } $signToolArguments = Format-SignToolArgumentList @formatSignToolArgumentListParams # Run signtool.exe. $invokeSignToolParams = @{ SignToolFolderPath = $signToolFolderPath SignToolArguments = $signToolArguments Timeout = $Timeout } $result = Invoke-SignTool @invokeSignToolParams # Throw an error if signtool.exe failed. # Exit code 0 means that signtool.exe completed successfully. # Exit code 2 means that signtool.exe completed with warnings. if ($result -ne 0 -and $result -ne 2) { throw "SignTool failed with exit code $($result)" } $batchCounter++ } Write-Information -MessageData "`nTrusted Signing completed successfully" -InformationAction Continue return "Trusted Signing completed successfully" } |