Replace test certificates with self-signed certificate generating command (#7875)
This commit is contained in:
parent
3b9f75865e
commit
649d342a07
10
build.psm1
10
build.psm1
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ FunctionsToExport = @(
|
|||
'Disable-Testhook'
|
||||
'Enable-Testhook'
|
||||
'Get-RandomFileName'
|
||||
'New-RandomHexString'
|
||||
'Send-VstsLogFile'
|
||||
'Set-TesthookResult'
|
||||
'Start-NativeExecution'
|
||||
|
|
|
@ -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 ''
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
|
@ -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
|
||||
|
||||
|
|
Binary file not shown.
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue