Replace test certificates with self-signed certificate generating command (#7875)

This commit is contained in:
Robert Holt 2018-10-01 14:40:48 -07:00 committed by Aditya Patwardhan
parent 3b9f75865e
commit 649d342a07
11 changed files with 138 additions and 10 deletions

View file

@ -5,6 +5,10 @@
# On Windows paths is separated by semicolon
$script:TestModulePathSeparator = [System.IO.Path]::PathSeparator
# Path to a directory to store modules we temporarily need to test PowerShell
$script:TestModuleDirPath = Join-Path ([System.IO.Path]::GetTempPath()) 'PwshTestModules'
$null = New-Item -Force -ItemType Directory -Path $script:TestModuleDirPath
$dotnetCLIChannel = "release"
$dotnetCLIRequiredVersion = $(Get-Content $PSScriptRoot/global.json | ConvertFrom-Json).Sdk.Version
@ -1035,6 +1039,9 @@ function Publish-PSTestTools {
Pop-Location
}
}
# Get the SelfSignedCertificate module so the web listener can use it
Save-Module -Name SelfSignedCertificate -Path $script:TestModuleDirPath -Repository "PSGallery" -MinimumVersion '0.0.2' -Force -Confirm:$false
}
function Get-ExperimentalFeatureTests {
@ -1139,7 +1146,8 @@ function Start-PSPester {
}
# Autoload (in subprocess) temporary modules used in our tests
$command += '$env:PSModulePath = '+"'$TestModulePath$TestModulePathSeparator'" + '+$($env:PSModulePath);'
$newPathFragment = $TestModulePath + $TestModulePathSeparator + $script:TestModuleDirPath + $TestModulePathSeparator
$command += '$env:PSModulePath = '+"'$newPathFragment'" + '+$env:PSModulePath;'
# Windows needs the execution policy adjusted
if ($Environment.IsWindows) {

View file

@ -28,9 +28,8 @@ Describe "CmsMessage cmdlets and Get-PfxCertificate basic tests" -Tags "CI" {
}
It "Verify Get-PfxCertificate right password" {
#[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Test secret.")]
$pass = ConvertTo-SecureString "password" -AsPlainText -Force
$cert = Get-PfxCertificate $protectedCertLocation -Password $pass
$password = Get-CertificatePassword
$cert = Get-PfxCertificate $protectedCertLocation -Password $password
$cert.Subject | Should -Be "CN=localhost"
}

View file

@ -68,6 +68,21 @@ OksttXT1kXf+aez9EzDlsgQU4ck78h0WTy01zHLwSKNWK4wFFQM=
return $certLocation
}
Function New-CertificatePassword
{
$script:protectedCertPassword = ConvertTo-SecureString -Force -AsPlainText (New-RandomHexString)
return $script:protectedCertPassword
}
Function Get-CertificatePassword
{
if ($null -eq $script:protectedCertPassword)
{
throw [System.InvalidOperationException] "`$script:protectedCertPassword is not defined. Call New-CertificatePassword first."
}
return $script:protectedCertPassword
}
Function New-ProtectedCertificate
{
<#
@ -78,7 +93,15 @@ Function New-ProtectedCertificate
Password: "password"
#>
$certLocation = ".\test\tools\Modules\WebListener\ServerCert.pfx"
$certLocation = Join-Path ([System.IO.Path]::GetTempPath()) 'protectedCert.pfx'
$password = New-CertificatePassword
$null = SelfSignedCertificate\New-SelfSignedCertificate `
-CommonName 'localhost' `
-OutCertPath $certLocation `
-Passphrase $password `
-Force
return $certLocation
}

View file

@ -21,6 +21,7 @@ FunctionsToExport = @(
'Disable-Testhook'
'Enable-Testhook'
'Get-RandomFileName'
'New-RandomHexString'
'Send-VstsLogFile'
'Set-TesthookResult'
'Start-NativeExecution'

View file

@ -313,3 +313,13 @@ function Start-NativeExecution
$script:ErrorActionPreference = $backupEAP
}
}
# Creates a new random hex string for use with things like test certificate passwords
function New-RandomHexString
{
param([int]$Length = 10)
$random = [Random]::new()
return ((1..$Length).ForEach{ '{0:x}' -f $random.Next(0xf) }) -join ''
}

View file

@ -1,6 +1,19 @@
# WebListener Module
A PowerShell module for managing the WebListener App. The included SelF-Signed Certificate `ServerCert.pfx` has the password set to `password` and is issued for the Client and Server Authentication key usages. This certificate is used by the WebListener App for SSL/TLS. The included SelF-Signed Certificate `ClientCert.pfx` has the password set to `password` and has not been issued for any specific key usage. This Certificate is used for Client Certificate Authentication with the WebListener App. The port used for `-HttpsPort` will use TLS 1.2.
A PowerShell module for managing the WebListener App.
When the WebListener is started from this module,
it will automatically generate two fresh certificates,
`ClientCert.pfx` and `ServerCert.pfx` using the `SelfSignedCertificate` module.
The generated Self-Signed Certificate `ServerCert.pfx` has a randomly generated password
and is issued for the Client and Server Authentication key usages.
This certificate is used by the WebListener App for SSL/TLS.
The generated Self-Signed Certificate `ClientCert.pfx` has a randomly generated password
and is not issued for any specific key usage.
This Certificate is used for Client Certificate Authentication with the WebListener App.
The port used for `-HttpsPort` will use TLS 1.2.
# Running WebListener

View file

@ -4,6 +4,9 @@
Author = 'Mark Kraus'
Description = 'An HTTP and HTTPS Listener for testing purposes'
RootModule = 'WebListener.psm1'
RequiredModules = @(
'SelfSignedCertificate'
)
FunctionsToExport = @(
'Get-WebListener'
'Get-WebListenerClientCertificate'

View file

@ -1,5 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
Class WebListener
{
[int]$HttpPort
@ -18,6 +19,67 @@ Class WebListener
[WebListener]$WebListener
function New-ClientCertificate
{
param([string]$CertificatePath, [string]$Password)
if ($Password)
{
$Passphrase = ConvertTo-SecureString -Force -AsPlainText $Password
}
$distinguishedName = @{
CN = 'adatum.com'
C = 'US'
S = 'Washington'
L = 'Redmond'
O = 'A. Datum Corporation'
OU = 'R&D'
E = 'randd@adatum.com'
}
$certificateParameters = @{
OutCertPath = $CertificatePath
StartDate = [datetime]::Now.Subtract([timespan]::FromDays(30))
Duration = [timespan]::FromDays(365)
Passphrase = $Passphrase
CertificateFormat = 'Pfx'
KeyLength = 4096
ForCertificateAuthority = $true
Force = $true
} + $distinguishedName
SelfSignedCertificate\New-SelfSignedCertificate @certificateParameters
}
function New-ServerCertificate
{
param([string]$CertificatePath, [string]$Password)
if ($Password)
{
$Passphrase = ConvertTo-SecureString -Force -AsPlainText $Password
}
$distinguishedName = @{
CN = 'localhost'
}
$certificateParameters = @{
OutCertPath = $CertificatePath
StartDate = [datetime]::Now.Subtract([timespan]::FromDays(30))
Duration = [timespan]::FromDays(1000)
Passphrase = $Passphrase
KeyUsage = 'DigitalSignature','KeyEncipherment'
EnhancedKeyUsage = 'ServerAuthentication','ClientAuthentication'
CertificateFormat = 'Pfx'
KeyLength = 2048
Force = $true
} + $distinguishedName
SelfSignedCertificate\New-SelfSignedCertificate @certificateParameters
}
function Get-WebListener
{
[CmdletBinding(ConfirmImpact = 'Low')]
@ -60,11 +122,17 @@ function Start-WebListener
$initTimeoutSeconds = 15
$appDll = 'WebListener.dll'
$serverPfx = 'ServerCert.pfx'
$serverPfxPassword = 'password'
$serverPfxPassword = New-RandomHexString
$clientPfx = 'ClientCert.pfx'
$initCompleteMessage = 'Now listening on'
$sleepMilliseconds = 100
$serverPfxPath = Join-Path $MyInvocation.MyCommand.Module.ModuleBase $serverPfx
$serverPfxPath = Join-Path ([System.IO.Path]::GetTempPath()) $serverPfx
$Script:ClientPfxPath = Join-Path ([System.IO.Path]::GetTempPath()) $clientPfx
$Script:ClientPfxPassword = New-RandomHexString
New-ServerCertificate -CertificatePath $serverPfxPath -Password $serverPfxPassword
New-ClientCertificate -CertificatePath $Script:ClientPfxPath -Password $Script:ClientPfxPassword
$Job = Start-Job {
$path = Split-Path -parent (get-command WebListener).Path -Verbose
Push-Location $path -Verbose
@ -130,8 +198,7 @@ function Get-WebListenerClientCertificate {
[OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])]
param()
process {
$pfxPath = Join-Path $MyInvocation.MyCommand.Module.ModuleBase 'ClientCert.pfx'
[System.Security.Cryptography.X509Certificates.X509Certificate2]::new($pfxPath,'password')
[System.Security.Cryptography.X509Certificates.X509Certificate2]::new($Script:ClientPfxPath, $Script:ClientPfxPassword)
}
}

View file

@ -11,6 +11,10 @@ cd bin
dotnet WebListener.dll ServerCert.pfx password 8083 8084 8085 8086
```
**NOTE**: `ServerCert.pfx` is no longer a static asset
and you will need to create your own certificate for this purpose.
The `SelfSignedCertificate` module in the PowerShell Gallery provides this functionality.
The test site can then be accessed via `http://localhost:8083/`, `https://localhost:8084/`, `https://localhost:8085/`, or `https://localhost:8086/`.
The `WebListener.dll` takes 6 arguments: