Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate test certificates in pipeline #4747

Merged
merged 4 commits into from
Aug 22, 2024
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
3 changes: 0 additions & 3 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ appname
appshutdown
APPTERMINATION
archs
argumentlist
ARMNT
arp
arphelper
Expand Down Expand Up @@ -390,7 +389,6 @@ Peet
peetdev
PEGI
pfn
pfxpath
pgp
Pherson
pid
Expand Down Expand Up @@ -469,7 +467,6 @@ savepoint
schematab
Scm
sddl
SECUREFILEPATH
secureobject
securestring
seof
Expand Down
45 changes: 17 additions & 28 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ jobs:
- template: templates/e2e-setup.yml
parameters:
sourceDir: $(Build.SourcesDirectory)
localhostWebServerArgs: '-BuildRoot $(artifactsDir)\E2ETests\LocalhostWebServer -StaticFileRoot $(Agent.TempDirectory)\TestLocalIndex -LocalSourceJson $(Build.SourcesDirectory)\src\AppInstallerCLIE2ETests\TestData\localsource.json -TestDataPath $(Build.SourcesDirectory)\src\AppInstallerCLIE2ETests\TestData -SourceCert $(Build.SourcesDirectory)\src\AppInstallerCLIE2ETests\TestData\AppInstallerTest.cer -ExitBeforeRun'
localhostWebServerArgs: '-BuildRoot $(artifactsDir)\E2ETests\LocalhostWebServer -StaticFileRoot $(Agent.TempDirectory)\TestLocalIndex -LocalSourceJson $(Build.SourcesDirectory)\src\AppInstallerCLIE2ETests\TestData\localsource.json -TestDataPath $(Build.SourcesDirectory)\src\AppInstallerCLIE2ETests\TestData -ExitBeforeRun'
signingCertOutDir: $(artifactsDir)\E2ETests

- task: CopyFiles@2
displayName: 'Copy TestLocalIndex'
florelis marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -302,28 +303,6 @@ jobs:
verbosity: 'Verbose'
alertWarningLevel: 'High'

# Run BimSkim for all the binaries
- task: BinSkim@4
displayName: 'Run BinSkim '
inputs:
arguments: 'analyze
"$(buildOutDir)\AppInstallerCLI\winget.exe"
"$(buildOutDir)\WinGetUtil\WinGetUtil.dll"
"$(buildOutDir)\WindowsPackageManager\WindowsPackageManager.dll"
"$(buildOutDir)\Microsoft.Management.Deployment.InProc\Microsoft.Management.Deployment.InProc.dll"
"$(Build.SourcesDirectory)\src\WinGetUtilInterop\bin\WinGetUtil*Interop.dll"
"$(buildOutDir)\UndockedRegFreeWinRT\winrtact.dll"
"$(buildOutDir)\Microsoft.WinGet.Client.Cmdlets\Microsoft.WinGet.Client*.dll"
"$(buildOutDir)\ConfigurationRemotingServer\ConfigurationRemoting*Server.dll"
"$(buildOutDir)\ConfigurationRemotingServer\ConfigurationRemoting*Server.exe"
"$(buildOutDir)\ConfigurationRemotingServer\Microsoft.Management.Configuration*.dll"
"$(buildOutDir)\Microsoft.Management.Configuration\Microsoft.Management.Configuration*.dll"
"$(buildOutDir)\Microsoft.Management.Configuration.OutOfProc\Microsoft.Management.Configuration*.dll"
--config default --recurse'

- task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@3
displayName: 'Publish Security Analysis Logs'

# Test job runs tests using build artifacts

- job: 'Test'
Expand Down Expand Up @@ -431,7 +410,7 @@ jobs:
- template: templates/e2e-setup.yml
parameters:
sourceDir: $(Build.SourcesDirectory)
localhostWebServerArgs: '-BuildRoot $(buildOutDir)\E2ETests\LocalhostWebServer -StaticFileRoot $(buildOutDir)\E2ETests\TestLocalIndex -SourceCert $(Build.SourcesDirectory)\src\AppInstallerCLIE2ETests\TestData\AppInstallerTest.cer'
localhostWebServerArgs: '-BuildRoot $(buildOutDir)\E2ETests\LocalhostWebServer -StaticFileRoot $(buildOutDir)\E2ETests\TestLocalIndex -SourceCert $(buildOutDir)\E2ETests\TestSigningCert.cer'

- template: templates/e2e-test.template.yml
parameters:
Expand Down Expand Up @@ -511,6 +490,10 @@ jobs:
arguments: '-TargetLocation $(artifactsDir)\ConfigOOPTestsLog'
condition: succeededOrFailed()

- powershell: Get-Process LocalhostWebServer | Stop-Process
displayName: Stop LocalhostWebServer
condition: succeededOrFailed()

- task: PublishPipelineArtifact@1
displayName: Publish Pipeline Artifacts
inputs:
Expand All @@ -524,6 +507,8 @@ jobs:
timeoutInMinutes: 120
dependsOn: 'Build'
condition: succeeded('Build')
variables:
buildOutDir: $(Pipeline.Workspace)\Build.x64Release

steps:
- task: DownloadPipelineArtifact@2
Expand All @@ -532,7 +517,7 @@ jobs:
- task: CopyFiles@2
displayName: 'Copy x64 PowerShell Binaries to Output'
inputs:
SourceFolder: '$(Pipeline.Workspace)\Build.x64release\PowerShell'
SourceFolder: '$(buildOutDir)\PowerShell'
Contents: '**\*'
TargetFolder: '$(Build.ArtifactStagingDirectory)'

Expand Down Expand Up @@ -566,14 +551,14 @@ jobs:
targetType: 'inline'
script: |
Get-ChildItem AppxPackages\AppInstallerCLIPackage_0.0.2.0_Test\Dependencies\x64 -Filter *.appx | %{ Add-AppxPackage $_.FullName }
workingDirectory: $(Pipeline.Workspace)\Build.x64release\
workingDirectory: $(buildOutDir)

- template: templates/e2e-setup.yml
parameters:
sourceDir: $(Build.SourcesDirectory)
localhostWebServerArgs: '-BuildRoot $(Pipeline.Workspace)\Build.x64release\E2ETests\LocalhostWebServer -StaticFileRoot $(Pipeline.Workspace)\Build.x64release\E2ETests\TestLocalIndex -SourceCert $(Build.SourcesDirectory)\src\AppInstallerCLIE2ETests\TestData\AppInstallerTest.cer'
localhostWebServerArgs: '-BuildRoot $(buildOutDir)\E2ETests\LocalhostWebServer -StaticFileRoot $(buildOutDir)\E2ETests\TestLocalIndex -SourceCert $(buildOutDir)\E2ETests\TestSigningCert.cer'

- pwsh: .\RunTests.ps1 -testModulesPath $(Build.ArtifactStagingDirectory) -outputPath $(Pipeline.Workspace)\PesterTest -packageLayoutPath $(Pipeline.Workspace)\Build.x64release\DevPackage
- pwsh: .\RunTests.ps1 -testModulesPath $(Build.ArtifactStagingDirectory) -outputPath $(Pipeline.Workspace)\PesterTest -packageLayoutPath $(buildOutDir)\DevPackage
workingDirectory: $(Build.SourcesDirectory)\src\PowerShell\tests\
displayName: Run PowerShell 7 Tests

Expand All @@ -582,6 +567,10 @@ jobs:
displayName: Run Windows PowerShell Tests
condition: succeededOrFailed()

- powershell: Get-Process LocalhostWebServer | Stop-Process
displayName: Stop LocalhostWebServer
condition: succeededOrFailed()

- task: PublishTestResults@2
displayName: Publish Pester Test Results PowerShell 7
inputs:
Expand Down
3 changes: 0 additions & 3 deletions src/AppInstallerCLIE2ETests/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ public class Constants
public const string TestSourceType = "Microsoft.PreIndexed.Package";
public const string TestSourceIdentifier = @"WingetE2E.Tests_8wekyb3d8bbwe";

public const string AppInstallerTestCert = "AppInstallerTest.cer";
public const string AppInstallerTestCertThumbprint = "d03e7a688b388b1edde8476a627531c49db88017";

public const string AICLIPackageFamilyName = "WinGetDevCLI_8wekyb3d8bbwe";
public const string AICLIPackageName = "WinGetDevCLI";
public const string AICLIPackagePublisherHash = "8wekyb3d8bbwe";
Expand Down
8 changes: 4 additions & 4 deletions src/AppInstallerCLIE2ETests/HashCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public class HashCommand : BaseCommand
[Test]
public void HashFile()
{
var result = TestCommon.RunAICLICommand("hash", TestCommon.GetTestDataFile("AppInstallerTest.cer"));
var result = TestCommon.RunAICLICommand("hash", TestCommon.GetTestDataFile("AppInstallerTestMsiInstaller.msi"));
Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
Assert.True(result.StdOut.Contains("9b4c49ad7e47afd97d2e666e93347745e1647c55f1a7ebba6d31b7dd5f69ee68"));
Assert.True(result.StdOut.Contains("21d90ee9b3569590c624836ef50bf39791c7184869c227eedc00585e1f39b4de"));
JohnMcPMS marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
Expand All @@ -44,9 +44,9 @@ public void HashMSIX()
[Test]
public void HashInvalidMSIX()
{
var result = TestCommon.RunAICLICommand("hash", TestCommon.GetTestDataFile("AppInstallerTest.cer") + " -m");
var result = TestCommon.RunAICLICommand("hash", TestCommon.GetTestDataFile("AppInstallerTestMsiInstaller.msi") + " -m");
Assert.AreEqual(Constants.ErrorCode.OPC_E_ZIP_MISSING_END_OF_CENTRAL_DIRECTORY, result.ExitCode);
Assert.True(result.StdOut.Contains("9b4c49ad7e47afd97d2e666e93347745e1647c55f1a7ebba6d31b7dd5f69ee68"));
Assert.True(result.StdOut.Contains("21d90ee9b3569590c624836ef50bf39791c7184869c227eedc00585e1f39b4de"));
Assert.True(result.StdOut.Contains("Please verify that the input file is a valid, signed MSIX."));
}

Expand Down
4 changes: 0 additions & 4 deletions src/AppInstallerCLIE2ETests/SetUpFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ public void Setup()

shouldRevertDefaultFileTypeRiskOnExit = this.DecreaseFileTypeRisk(".exe;.msi", false);

Assert.True(TestCommon.RunCommand("certutil.exe", "-addstore -f \"TRUSTEDPEOPLE\" " + TestCommon.GetTestDataFile(Constants.AppInstallerTestCert)), "Add AppInstallerTestCert");

if (testParams.PackagedContext)
{
if (testParams.LooseFileRegistration)
Expand Down Expand Up @@ -83,8 +81,6 @@ public void TearDown()
this.DecreaseFileTypeRisk(defaultFileTypes, true);
}

TestCommon.RunCommand("certutil.exe", $"-delstore \"TRUSTEDPEOPLE\" {Constants.AppInstallerTestCertThumbprint}");

TestCommon.PublishE2ETestLogs();

if (TestSetup.Parameters.PackagedContext)
Expand Down
Binary file not shown.
Binary file not shown.
3 changes: 2 additions & 1 deletion src/AppInstallerCLIE2ETests/TestData/localsource.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
}
],
"Signature": {
"CertFile": "%APPINSTALLERTEST_SECUREFILEPATH%"
"CertFile": "%TestSigningCert_PfxPath%",
"Password": "%TestSigningCert_Password%"
}
}
15 changes: 0 additions & 15 deletions src/LocalhostWebServer/InstallDevCert.ps1

This file was deleted.

2 changes: 1 addition & 1 deletion src/LocalhostWebServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private static void CopyDirectoryRecursive(string sourceDir, string destDir)
foreach (string file in files)
{
string dest = Path.Combine(destDir, Path.GetFileName(file));
File.Copy(file, dest);
File.Copy(file, dest, overwrite: true);
}

string[] directories = Directory.GetDirectories(sourceDir);
Expand Down
13 changes: 12 additions & 1 deletion src/LocalhostWebServer/Run-LocalhostWebServer.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,19 @@ if (-not [System.String]::IsNullOrEmpty($sourceCert))

Push-Location $BuildRoot

$Local:process = Start-Process -FilePath "LocalhostWebServer.exe" -ArgumentList "StaticFileRoot=$StaticFileRoot CertPath=$CertPath CertPassword=$CertPassword OutCertFile=$OutCertFile LocalSourceJson=$LocalSourceJson TestDataPath=$TestDataPath ExitBeforeRun=$ExitBeforeRun" -PassThru
$startProcessArguments = @{
FilePath = Join-Path $BuildRoot "LocalhostWebServer.exe"
ArgumentList = "StaticFileRoot=$StaticFileRoot CertPath=$CertPath CertPassword=$CertPassword OutCertFile=$OutCertFile LocalSourceJson=$LocalSourceJson TestDataPath=$TestDataPath ExitBeforeRun=$ExitBeforeRun"
PassThru = $true
}

if (-not [System.string]::IsNullOrEmpty($env:artifactsDir))
{
$startProcessArguments.RedirectStandardOutput = Join-Path $env:artifactsDir "LocalhostWebServer.out"
$startProcessArguments.RedirectStandardError = Join-Path $env:artifactsDir "LocalhostWebServer.err"
}

$Local:process = Start-Process @startProcessArguments

if ($ExitBeforeRun)
{
Expand Down
55 changes: 36 additions & 19 deletions templates/e2e-setup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,48 @@ parameters:
type: string
- name: localhostWebServerArgs
type: string
- name: signingCertOutDir
type: string
default: $(Agent.TempDirectory)

steps:
- task: DownloadSecureFile@1
name: AppInstallerTest
displayName: 'Download Source Package Certificate'
inputs:
secureFile: 'AppInstallerTest.pfx'
- pwsh: |
$newCertArguments = @{
Type = "Custom"
Subject = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
KeyUsage = "DigitalSignature"
TextExtension = @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}")
CertStoreLocation = "Cert:\CurrentUser\My"
}
$cert = New-SelfSignedCertificate @newCertArguments

- task: DownloadSecureFile@1
name: HTTPSDevCert
displayName: 'Download Kestrel Certificate'
inputs:
secureFile: 'HTTPSDevCertV2.pfx'
$certPfxPath = Join-Path $(Agent.TempDirectory) TestSigningCert.pfx
$certCerPath = Join-Path ${{ parameters.signingCertOutDir }} TestSigningCert.cer
$certPassword = (New-Guid).ToString()
$certSecurePassword = ConvertTo-SecureString $certPassword -AsPlainText

- task: PowerShell@2
displayName: Install Root Certificate
inputs:
filePath: '${{ parameters.sourceDir }}\src\LocalhostWebServer\InstallDevCert.ps1'
arguments: '-pfxpath $(HTTPSDevCert.secureFilePath) -password microsoft'
Export-PfxCertificate -Cert $cert -FilePath $certPfxPath -Password $certSecurePassword
Export-Certificate -Cert $cert -FilePath $certCerPath

- task: PowerShell@2
Write-Host "##vso[task.setvariable variable=TestSigningCert.PfxPath;]$certPfxPath"
Write-Host "##vso[task.setvariable variable=TestSigningCert.CerPath;]$certCerPath"
Write-Host "##vso[task.setvariable variable=TestSigningCert.Password;]$certPassword"
displayName: Create test codesigning cert

- pwsh: |
$httpsCertPath = Join-Path $(Agent.TempDirectory) HttpsCert.pfx
$httpsCertPassword = (New-Guid).ToString()
dotnet dev-certs https --export-path $httpsCertPath --password $httpsCertPassword

$securePassword = ConvertTo-SecureString $httpsCertPassword -AsPlainText
Import-PfxCertificate -FilePath $httpsCertPath -Password $securePassword -CertStoreLocation Cert:\LocalMachine\Root

Write-Host "##vso[task.setvariable variable=HttpsCert.Path;]$httpsCertPath"
Write-Host "##vso[task.setvariable variable=HttpsCert.Password;]$httpsCertPassword"
displayName: Create and install localhost HTTPS cert

- pwsh: ${{ parameters.sourceDir }}\src\LocalhostWebServer\Run-LocalhostWebServer.ps1 -CertPath $(HttpsCert.Path) -CertPassword $(HttpsCert.Password) -OutCertFile $(Agent.TempDirectory)\servercert.cer ${{ parameters.localhostWebServerArgs }}
displayName: Launch LocalhostWebServer
inputs:
filePath: '${{ parameters.sourceDir }}\src\LocalhostWebServer\Run-LocalhostWebServer.ps1'
arguments: '-CertPath $(HTTPSDevCert.secureFilePath) -CertPassword microsoft -OutCertFile $(Agent.TempDirectory)\servercert.cer ${{ parameters.localhostWebServerArgs }}'

- task: PowerShell@2
displayName: Setup Local PS Repository
Expand Down
Loading