Skip to content

Instantly share code, notes, and snippets.

@emilwojcik93
Last active March 17, 2025 13:51
Show Gist options
  • Save emilwojcik93/7eb1e172f8bb038e324c6e4a7f4ccaaa to your computer and use it in GitHub Desktop.
Save emilwojcik93/7eb1e172f8bb038e324c6e4a7f4ccaaa to your computer and use it in GitHub Desktop.
The script searches for certificates with a specific description pattern. It exports each certificate, installs them in WSL, and checks the response using curl. If the response is not correct, it tries the next certificate from the results. If the list is done and WSL still responds with an incorrect answer, it throws an error.
<#
.SYNOPSIS
This script searches for certificates with a specific description pattern, exports them, installs them in WSL, and checks the response using curl.
.DESCRIPTION
The script searches for certificates with a specific description pattern. It exports each certificate, installs them in WSL, and checks the response using curl. If the response is not correct, it tries the next certificate from the results. If the list is exhausted and WSL still responds with an incorrect answer, it throws an error.
.PARAMETER DescriptionPattern
The pattern to search for in the certificate description. Default is "CA".
.PARAMETER ExcludeIssuers
An array of issuer names to exclude from the results. Default is an array of common built-in certificate issuers.
.PARAMETER WSLDistro
The WSL distribution to install the certificate in. Default is "Ubuntu".
.PARAMETER UpdateCommand
The command to update the CA certificates. Default is the value from the $wslDistros array.
.PARAMETER Verbose
Enables verbose output.
.EXAMPLE
.\Auto-Install-CertificatesInWSL.ps1 -Verbose
.EXAMPLE
.\Auto-Install-CertificatesInWSL.ps1 -DescriptionPattern "CA" -ExcludeIssuers @("DigiCert", "thawte") -WSLDistro "Ubuntu" -Verbose
.LINK
Related topic: https://github.com/microsoft/WSL/issues/3161
.LINK
Source of "$wslDistros" array: https://stackoverflow.com/a/77672453
#>
param (
[string]$DescriptionPattern = "CA",
[string[]]$ExcludeIssuers = @(
"DigiCert",
"thawte",
"Digital Signature Trust Co.",
"GlobalSign",
"Microsoft",
"SSL.com",
"Entrust",
"COMODO",
"Starfield",
"VeriSign",
"Go Daddy",
"USERTrust",
"IdenTrust",
"QuoVadis",
"Certum",
"AAA Certificate Services",
"AddTrust",
"Sectigo",
"Symantec",
"Hotspot 2.0 Trust Root CA",
"WFA Hotspot 2.0"
),
[string]$WSLDistro,
[string]$UpdateCommand,
[switch]$Verbose
)
if ($Verbose) {
$VerbosePreference = "Continue"
}
$wslDistros = @{
"Alpine" = @{ Path = "/usr/local/share/ca-certificates/"; Command = "update-ca-certificates"; Install = "apk add ca-certificates" }
"Amazon Linux" = @{ Path = "/etc/pki/ca-trust/source/anchors/"; Command = "update-ca-trust extract"; Install = "yum install ca-certificates" }
"Arch" = @{ Path = "/etc/ca-certificates/trust-source/anchors/"; Command = "trust extract-compat"; Install = "pacman -Sy ca-certificates-utils" }
"CentOS" = @{ Path = "/etc/pki/ca-trust/source/anchors/"; Command = "update-ca-trust extract"; Install = "yum install ca-certificates" }
"CoreOS" = @{ Path = "/etc/pki/ca-trust/source/anchors/"; Command = "update-ca-certificates"; Install = "Built into the system" }
"Debian" = @{ Path = "/usr/local/share/ca-certificates/"; Command = "update-ca-certificates"; Install = "apt-get install -y ca-certificates" }
"Fedora" = @{ Path = "/etc/pki/ca-trust/source/anchors/"; Command = "update-ca-trust extract"; Install = "dnf install ca-certificates" }
"RedHat" = @{ Path = "/etc/pki/ca-trust/source/anchors/"; Command = "update-ca-trust extract"; Install = "yum install ca-certificates" }
"SUSE" = @{ Path = "/etc/pki/trust/anchors/"; Command = "update-ca-certificates"; Install = "zypper install ca-certificates" }
"Ubuntu" = @{ Path = "/usr/local/share/ca-certificates/"; Command = "update-ca-certificates"; Install = "apt-get install -y ca-certificates" }
"Ubuntu-18.04" = @{ Path = "/usr/local/share/ca-certificates/"; Command = "update-ca-certificates"; Install = "apt-get install -y ca-certificates" }
"Ubuntu-20.04" = @{ Path = "/usr/local/share/ca-certificates/"; Command = "update-ca-certificates"; Install = "apt-get install -y ca-certificates" }
"Ubuntu-22.04" = @{ Path = "/usr/local/share/ca-certificates/"; Command = "update-ca-certificates"; Install = "apt-get install -y ca-certificates" }
"Ubuntu-24.04" = @{ Path = "/usr/local/share/ca-certificates/"; Command = "update-ca-certificates"; Install = "apt-get install -y ca-certificates" }
"OracleLinux_7_9" = @{ Path = "/etc/pki/ca-trust/source/anchors/"; Command = "update-ca-trust extract"; Install = "yum install ca-certificates" }
"OracleLinux_8_7" = @{ Path = "/etc/pki/ca-trust/source/anchors/"; Command = "update-ca-trust extract"; Install = "yum install ca-certificates" }
"OracleLinux_9_1" = @{ Path = "/etc/pki/ca-trust/source/anchors/"; Command = "update-ca-trust extract"; Install = "yum install ca-certificates" }
"openSUSE-Leap-15.6" = @{ Path = "/etc/pki/trust/anchors/"; Command = "update-ca-certificates"; Install = "zypper install ca-certificates" }
"SUSE-Linux-Enterprise-15-SP5" = @{ Path = "/etc/pki/trust/anchors/"; Command = "update-ca-certificates"; Install = "zypper install ca-certificates" }
"SUSE-Linux-Enterprise-15-SP6" = @{ Path = "/etc/pki/trust/anchors/"; Command = "update-ca-certificates"; Install = "zypper install ca-certificates" }
"openSUSE-Tumbleweed" = @{ Path = "/etc/pki/trust/anchors/"; Command = "update-ca-certificates"; Install = "zypper install ca-certificates" }
"kali-linux" = @{ Path = "/usr/local/share/ca-certificates/"; Command = "update-ca-certificates"; Install = "apt-get install -y ca-certificates" }
}
$addresses = @(
"https://google.com/"
)
function Get-DefaultWSLDistro {
$registryPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss"
$defaultDistro = Get-ItemProperty -Path $registryPath -Name DefaultDistribution | Select-Object -ExpandProperty DefaultDistribution
$defaultDistro = (Get-ItemProperty -Path "$registryPath\$defaultDistro").DistributionName
return $defaultDistro
}
function Test-WSL {
if (-not (Get-Command wsl -ErrorAction SilentlyContinue)) {
return $false
}
try {
$wslOutput = wsl -l -q | Where-Object { $_ -ne "" }
if ($wslOutput) {
return $true
}
} catch {
return $false
}
}
function Test-CurlAvailability {
param (
[string]$WSLDistro
)
# Check if curl is available in the target WSL distribution
$commandCheck = "if command -v curl > /dev/null 2>&1; then echo true; else echo false; fi"
$commandAvailable = wsl -d $WSLDistro -u root -e bash -c $commandCheck
return $commandAvailable -eq "true"
}
function Search-Certificates {
param (
[string]$DescriptionPattern,
[string[]]$ExcludeIssuers
)
$storeLocations = @("LocalMachine", "CurrentUser")
$storeNames = @("My", "Root", "CA", "AuthRoot", "TrustedPublisher", "TrustedPeople", "Disallowed")
$results = @()
foreach ($storeLocation in $storeLocations) {
foreach ($storeName in $storeNames) {
$storePath = "Cert:\$storeLocation\$storeName"
Write-Verbose "Searching certificates in store: $storePath"
$certificates = Get-ChildItem -Path $storePath -Recurse
foreach ($cert in $certificates) {
if ($cert.Subject -like "*$DescriptionPattern*" -and $cert.Issuer -notmatch ($ExcludeIssuers -join "|")) {
Write-Verbose "Matched certificate: $($cert.PSPath)"
$results += $cert
}
}
}
}
return $results
}
function Export-CertificateToFile {
param (
[System.Security.Cryptography.X509Certificates.X509Certificate2]$Cert,
[string]$FilePath
)
Write-Verbose "Exporting certificate to file: $FilePath"
$certBytes = $Cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
$base64CertContent = [System.Convert]::ToBase64String($certBytes)
# Insert line breaks every 64 characters
$formattedCertContent = ($base64CertContent -split "(.{64})" | Where-Object { $_ -ne "" }) -join "`n"
$base64CertHeader = "-----BEGIN CERTIFICATE-----"
$base64CertFooter = "-----END CERTIFICATE-----"
$base64Cert = $base64CertHeader + "`n" + $formattedCertContent + "`n" + $base64CertFooter
Set-Content -Path $FilePath -Value $base64Cert -ErrorAction Stop
}
function Remove-OldCertificateFromWSL {
param (
[string]$CertFileName,
[string]$WSLDistro
)
try {
# Remove the old certificate from WSL
$removeCommand = "rm -f /usr/local/share/ca-certificates/$CertFileName"
$removeOutput = wsl -d $WSLDistro -u root -e bash -c $removeCommand
Write-Verbose ($removeOutput -join "`n")
} catch {
Write-Error "An error occurred while removing the old certificate from WSL: $($_ -join "`n")"
throw
}
}
function Install-CertificateInWSL {
param (
[string]$CertFilePath,
[string]$WSLDistro,
[string]$UpdateCommand,
[string]$CertPath
)
$certFileName = [System.IO.Path]::GetFileName($CertFilePath)
try {
# Copy the certificate to WSL using WSL commands
$copyCommand = "cp --verbose ./$certFileName $CertPath"
$copyOutput = wsl --cd "$(Split-Path -Path $CertFilePath)" -d $WSLDistro -u root -e bash -c $copyCommand
Write-Verbose ($copyOutput -join "`n")
# Check if the file exists in WSL
$checkCommand = "test -f $CertPath/$certFileName && echo 'File exists' || echo 'File does not exist'"
$checkOutput = wsl --cd "$(Split-Path -Path $CertFilePath)" -d $WSLDistro -u root -e bash -c $checkCommand
Write-Verbose ($checkOutput -join "`n")
if ($checkOutput -like "*File exists*") {
Write-Output "Certificate copied to ${CertPath}${certFileName}"
} else {
throw "Failed to copy certificate to $CertPath$certFileName"
}
# Check if the update command is available
$commandCheck = "if command -v $UpdateCommand > /dev/null 2>&1; then echo true; else echo false; fi"
$commandAvailable = wsl --cd "$(Split-Path -Path $CertFilePath)" -d $WSLDistro -u root -e bash -c $commandCheck
Write-Verbose "Command check output: $commandAvailable"
if ($commandAvailable -eq "true") {
Write-Output "Success: $UpdateCommand is available in WSL."
# Run the update command
$updateOutput = wsl --cd "$(Split-Path -Path $CertFilePath)" -d $WSLDistro -u root -e bash -c $UpdateCommand
Write-Verbose ($updateOutput -join "`n")
Write-Output "CA certificates updated in WSL."
} else {
Write-Output "Failed: $UpdateCommand is not available in WSL."
# Append the CA certificate directly to ca-certificates.crt
$appendCommand = "cat $CertPath/$certFileName | sudo tee -a /etc/ssl/certs/ca-certificates.crt > /dev/null"
$appendOutput = wsl --cd "$(Split-Path -Path $CertFilePath)" -d $WSLDistro -u root -e bash -c $appendCommand
Write-Verbose ($appendOutput -join "`n")
Write-Output "CA certificate appended directly to /etc/ssl/certs/ca-certificates.crt."
}
} catch {
Write-Error "An error occurred while installing the certificate in WSL: $($_ -join "`n")"
throw
}
}
function Test-CertificateInWSL {
param (
[string]$WSLDistro,
[string]$Address
)
# Run curl in WSL to check the response
$output = wsl -d $WSLDistro -- bash -c "curl -s -o /dev/null -w '%{http_code}' $Address"
return $output
}
function Main {
param (
[string]$DescriptionPattern,
[string[]]$ExcludeIssuers,
[string]$WSLDistro,
[string]$UpdateCommand,
[switch]$Verbose
)
if (-not (Test-WSL)) {
throw "WSL is not available or no distributions are installed."
}
if (-not $WSLDistro) {
$WSLDistro = Get-DefaultWSLDistro
if (-not $WSLDistro) {
throw "No default WSL distribution found. Please specify a WSL distribution using the -WSLDistro parameter."
}
}
if (-not $wslDistros.ContainsKey($WSLDistro)) {
throw "Unsupported WSL distribution: $WSLDistro"
}
if (-not (Test-CurlAvailability -WSLDistro $WSLDistro)) {
throw "curl is not available in the target WSL distribution: ${WSLDistro}"
}
if (-not $UpdateCommand) {
$UpdateCommand = $wslDistros[$WSLDistro].Command
}
$certPath = $wslDistros[$WSLDistro].Path
# Search for certificates
$certificates = Search-Certificates -DescriptionPattern $DescriptionPattern -ExcludeIssuers $ExcludeIssuers
foreach ($cert in $certificates) {
# Extract CN value from issuer and replace spaces with underscores
$issuerCN = ($cert.Issuer -match "CN=([^,]+)") | Out-Null; $issuerCN = $matches[1] -replace " ", "_"
$certFileName = "$issuerCN.crt"
$certFilePath = Join-Path -Path $env:TEMP -ChildPath $certFileName
# Export certificate to file
Export-CertificateToFile -Cert $cert -FilePath $certFilePath
# Remove old certificate from WSL
Remove-OldCertificateFromWSL -CertFileName $certFileName -WSLDistro $WSLDistro
# Install certificate in WSL
Install-CertificateInWSL -CertFilePath $certFilePath -WSLDistro $WSLDistro -UpdateCommand $UpdateCommand -CertPath $certPath
# Check certificate in WSL for each address
$success = $false
foreach ($address in $addresses) {
$response = Test-CertificateInWSL -WSLDistro $WSLDistro -Address $address
Write-Verbose "Response from Test-CertificateInWSL for ${address}: $response"
if ($response -ge 200 -and $response -lt 400) {
Write-Output "Certificate installed and verified successfully for ${address}."
$success = $true
break
} else {
Write-Warning "Certificate did not pass verification for ${address}."
}
}
if ($success) {
Write-Output "Certificate installed and verified successfully for at least one address."
return
} else {
Write-Warning "Certificate verification failed for all addresses. Trying next certificate."
Remove-OldCertificateFromWSL -CertFileName $certFileName -WSLDistro $WSLDistro
}
}
throw "No valid certificate found that passes verification."
}
# Call the main function with parameters
Main -DescriptionPattern $DescriptionPattern -ExcludeIssuers $ExcludeIssuers -WSLDistro $WSLDistro -UpdateCommand $UpdateCommand -Verbose:$Verbose
@emilwojcik93
Copy link
Author

emilwojcik93 commented Feb 16, 2025

Auto-Install-CertificatesInWSL.ps1

This script searches for certificates with a specific description pattern, exports them, installs them in WSL, and checks the response using curl.

Usage

.\Auto-Install-CertificatesInWSL.ps1 [options]

Options

  • -DescriptionPattern <String>: The pattern to search for in the certificate description. Default is "CA".
  • -ExcludeIssuers <String[]>: An array of issuer names to exclude from the results. Default is an array of common built-in certificate issuers.
  • -WSLDistro <String>: The WSL distribution to install the certificate in. Default is "Ubuntu".
  • -UpdateCommand <String>: The command to update the CA certificates. Default is the value from the $wslDistros array.
  • -Verbose: Enables verbose output.

Running the Script from the Internet:

Use Invoke-RestMethod to download and execute the script. Here is how you can do it:

# Using Invoke-RestMethod
irm https://gist.githubusercontent.com/emilwojcik93/7eb1e172f8bb038e324c6e4a7f4ccaaa/raw/Auto-Install-CertificatesInWSL.ps1 | iex

Note

If it doesn't work, then try to Set-ExecutionPolicy via PowerShell (Admin)

Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force; irm https://gist.githubusercontent.com/emilwojcik93/7eb1e172f8bb038e324c6e4a7f4ccaaa/raw/Auto-Install-CertificatesInWSL.ps1 | iex

Note

To execute the script from the Internet with additional parameters, please run

&([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/7eb1e172f8bb038e324c6e4a7f4ccaaa/raw/Auto-Install-CertificatesInWSL.ps1))) -Verbose

Example of issue

$ curl https://ipchicken.com/
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Example of execution

PS > &([ScriptBlock]::Create((irm https://gist.githubusercontent.com/emilwojcik93/7eb1e172f8bb038e324c6e4a7f4ccaaa/raw/Auto-Install-CertificatesInWSL.ps1))) -Verbose
VERBOSE: Searching certificates in store: Cert:\LocalMachine\My
VERBOSE: Searching certificates in store: Cert:\LocalMachine\Root
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root\<THUMBPRINT_VALUE_1>
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root\<THUMBPRINT_VALUE_2>
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root\<THUMBPRINT_VALUE_3>
VERBOSE: Searching certificates in store: Cert:\LocalMachine\CA
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\CA\<THUMBPRINT_VALUE_4>
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\CA\<THUMBPRINT_VALUE_5>
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\CA\<THUMBPRINT_VALUE_6>
VERBOSE: Searching certificates in store: Cert:\LocalMachine\AuthRoot
VERBOSE: Searching certificates in store: Cert:\LocalMachine\TrustedPublisher
VERBOSE: Searching certificates in store: Cert:\LocalMachine\TrustedPeople
VERBOSE: Searching certificates in store: Cert:\LocalMachine\Disallowed
VERBOSE: Searching certificates in store: Cert:\CurrentUser\My
VERBOSE: Searching certificates in store: Cert:\CurrentUser\Root
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\Root\<THUMBPRINT_VALUE_1>
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\Root\<THUMBPRINT_VALUE_2>
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\Root\<THUMBPRINT_VALUE_3>
VERBOSE: Searching certificates in store: Cert:\CurrentUser\CA
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\CA\<THUMBPRINT_VALUE_4>
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\CA\<THUMBPRINT_VALUE_5>
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\CA\<THUMBPRINT_VALUE_6>
VERBOSE: Searching certificates in store: Cert:\CurrentUser\AuthRoot
VERBOSE: Searching certificates in store: Cert:\CurrentUser\TrustedPublisher
VERBOSE: Searching certificates in store: Cert:\CurrentUser\TrustedPeople
VERBOSE: Searching certificates in store: Cert:\CurrentUser\Disallowed
VERBOSE: Exporting certificate to file: C:\Users\YourUser\AppData\Local\Temp\Cert_Root_CA.crt
VERBOSE: 
VERBOSE: './Cert_Root_CA.crt' -> '/usr/local/share/ca-certificates/Cert_Root_CA.crt'
VERBOSE: File exists
Certificate copied to /usr/local/share/ca-certificates/Cert_Root_CA.crt
VERBOSE: Command check output: true
Success: update-ca-certificates is available in WSL.
VERBOSE: Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
CA certificates updated in WSL.
VERBOSE: Response from Test-CertificateInWSL for https://www.whatismyip.com/: 000
WARNING: Certificate did not pass verification for https://www.whatismyip.com/.
VERBOSE: Response from Test-CertificateInWSL for https://www.showmyip.com/: 000
WARNING: Certificate did not pass verification for https://www.showmyip.com/.
VERBOSE: Response from Test-CertificateInWSL for https://ipchicken.com/: 000
WARNING: Certificate did not pass verification for https://ipchicken.com/.
VERBOSE: Response from Test-CertificateInWSL for https://ifconfig.co/: 000
WARNING: Certificate did not pass verification for https://ifconfig.co/.
VERBOSE: Response from Test-CertificateInWSL for https://google.com/: 000
WARNING: Certificate did not pass verification for https://google.com/.
WARNING: Certificate verification failed for all addresses. Trying next certificate.
VERBOSE: 
VERBOSE: Exporting certificate to file: C:\Users\YourUser\AppData\Local\Temp\Cert_Root_CA3.crt
VERBOSE: 
VERBOSE: './Cert_Root_CA3.crt' -> '/usr/local/share/ca-certificates/Cert_Root_CA3.crt'
VERBOSE: File exists
Certificate copied to /usr/local/share/ca-certificates/Cert_Root_CA3.crt
VERBOSE: Command check output: true
Success: update-ca-certificates is available in WSL.
rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL
VERBOSE: Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
CA certificates updated in WSL.
VERBOSE: Response from Test-CertificateInWSL for https://www.whatismyip.com/: 000
WARNING: Certificate did not pass verification for https://www.whatismyip.com/.
VERBOSE: Response from Test-CertificateInWSL for https://www.showmyip.com/: 000
WARNING: Certificate did not pass verification for https://www.showmyip.com/.
VERBOSE: Response from Test-CertificateInWSL for https://ipchicken.com/: 000
WARNING: Certificate did not pass verification for https://ipchicken.com/.
VERBOSE: Response from Test-CertificateInWSL for https://ifconfig.co/: 000
WARNING: Certificate did not pass verification for https://ifconfig.co/.
VERBOSE: Response from Test-CertificateInWSL for https://google.com/: 000
WARNING: Certificate did not pass verification for https://google.com/.
WARNING: Certificate verification failed for all addresses. Trying next certificate.
VERBOSE: 
VERBOSE: Exporting certificate to file: C:\Users\YourUser\AppData\Local\Temp\Cert_Root_CA1.crt
VERBOSE: 
VERBOSE: './Cert_Root_CA1.crt' -> '/usr/local/share/ca-certificates/Cert_Root_CA1.crt'
VERBOSE: File exists
Certificate copied to /usr/local/share/ca-certificates/Cert_Root_CA1.crt
VERBOSE: Command check output: true
Success: update-ca-certificates is available in WSL.
rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL
VERBOSE: Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
CA certificates updated in WSL.
VERBOSE: Response from Test-CertificateInWSL for https://www.whatismyip.com/: 000
WARNING: Certificate did not pass verification for https://www.whatismyip.com/.
VERBOSE: Response from Test-CertificateInWSL for https://www.showmyip.com/: 000
WARNING: Certificate did not pass verification for https://www.showmyip.com/.
VERBOSE: Response from Test-CertificateInWSL for https://ipchicken.com/: 000
WARNING: Certificate did not pass verification for https://ipchicken.com/.
VERBOSE: Response from Test-CertificateInWSL for https://ifconfig.co/: 000
WARNING: Certificate did not pass verification for https://ifconfig.co/.
VERBOSE: Response from Test-CertificateInWSL for https://google.com/: 000
WARNING: Certificate did not pass verification for https://google.com/.
WARNING: Certificate verification failed for all addresses. Trying next certificate.
VERBOSE: 
VERBOSE: Exporting certificate to file: C:\Users\YourUser\AppData\Local\Temp\Cert_Root_CA.crt
VERBOSE: 
VERBOSE: './Cert_Root_CA.crt' -> '/usr/local/share/ca-certificates/Cert_Root_CA.crt'
VERBOSE: File exists
Certificate copied to /usr/local/share/ca-certificates/Cert_Root_CA.crt
VERBOSE: Command check output: true
Success: update-ca-certificates is available in WSL.
rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL
VERBOSE: Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
CA certificates updated in WSL.
VERBOSE: Response from Test-CertificateInWSL for https://www.whatismyip.com/: 403
WARNING: Certificate did not pass verification for https://www.whatismyip.com/.
VERBOSE: Response from Test-CertificateInWSL for https://www.showmyip.com/: 200
Certificate installed and verified successfully for https://www.showmyip.com/.
Certificate installed and verified successfully for at least one address.

Example of execution for ArchLinux

> & ".\Auto-Install-CertificatesInWSL.ps1" -WSLDistro Arch -Verbose
VERBOSE: Searching certificates in store: Cert:\LocalMachine\My
VERBOSE: Searching certificates in store: Cert:\LocalMachine\Root
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root\BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root\CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
VERBOSE: Searching certificates in store: Cert:\LocalMachine\CA
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\CA\DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\CA\EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::LocalMachine\CA\FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
VERBOSE: Searching certificates in store: Cert:\LocalMachine\AuthRoot
VERBOSE: Searching certificates in store: Cert:\LocalMachine\TrustedPublisher
VERBOSE: Searching certificates in store: Cert:\LocalMachine\TrustedPeople
VERBOSE: Searching certificates in store: Cert:\LocalMachine\Disallowed
VERBOSE: Searching certificates in store: Cert:\CurrentUser\My
VERBOSE: Searching certificates in store: Cert:\CurrentUser\Root
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\Root\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\Root\BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\Root\CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
VERBOSE: Searching certificates in store: Cert:\CurrentUser\CA
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\CA\DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\CA\EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
VERBOSE: Matched certificate: Microsoft.PowerShell.Security\Certificate::CurrentUser\CA\FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
VERBOSE: Searching certificates in store: Cert:\CurrentUser\AuthRoot
VERBOSE: Searching certificates in store: Cert:\CurrentUser\TrustedPublisher
VERBOSE: Searching certificates in store: Cert:\CurrentUser\TrustedPeople
VERBOSE: Searching certificates in store: Cert:\CurrentUser\Disallowed
VERBOSE: Exporting certificate to file: C:\Users\username\AppData\Local\Temp\Example_Root_CA.crt
VERBOSE: 
VERBOSE: './Example_Root_CA.crt' -> '/etc/ca-certificates/trust-source/anchors/Example_Root_CA.crt'
VERBOSE: File exists
Certificate copied to /etc/ca-certificates/trust-source/anchors/Example_Root_CA.crt
VERBOSE: Command check output: true
Success: trust extract-compat is available in WSL.
VERBOSE: 
CA certificates updated in WSL.
VERBOSE: Response from Test-CertificateInWSL for https://www.example.com/: 403
WARNING: Certificate did not pass verification for https://www.example.com/.
VERBOSE: Response from Test-CertificateInWSL for https://www.example2.com/: 200

Functions

Get-DefaultWSLDistro

  • Purpose: Retrieves the default WSL distribution from the registry.
  • Example: $defaultDistro = Get-DefaultWSLDistro

Test-WSL

  • Purpose: Checks if WSL is available and if any distributions are installed.
  • Example: $isWSLAvailable = Test-WSL

Test-CurlAvailability

  • Purpose: Checks if curl is available in the target WSL distribution.
  • Parameters:
    • WSLDistro: The WSL distribution to check.
  • Example: $isCurlAvailable = Test-CurlAvailability -WSLDistro "Ubuntu"

Search-Certificates

  • Purpose: Searches for certificates with a specific description pattern.
  • Parameters:
    • DescriptionPattern: The pattern to search for in the certificate description.
    • ExcludeIssuers: An array of issuer names to exclude from the results.
  • Example: $certificates = Search-Certificates -DescriptionPattern "CA" -ExcludeIssuers @("DigiCert", "thawte")

Export-CertificateToFile

  • Purpose: Exports a certificate to a file in Base64 format.
  • Parameters:
    • Cert: The certificate to export.
    • FilePath: The file path to export the certificate to.
  • Example: Export-CertificateToFile -Cert $cert -FilePath "C:\Temp\cert.crt"

Remove-OldCertificateFromWSL

  • Purpose: Removes an old certificate from WSL.
  • Parameters:
    • CertFileName: The name of the certificate file to remove.
    • WSLDistro: The WSL distribution to remove the certificate from.
  • Example: Remove-OldCertificateFromWSL -CertFileName "cert.crt" -WSLDistro "Ubuntu"

Install-CertificateInWSL

  • Purpose: Installs a certificate in WSL.
  • Parameters:
    • CertFilePath: The file path of the certificate to install.
    • WSLDistro: The WSL distribution to install the certificate in.
    • UpdateCommand: The command to update the CA certificates.
    • CertPath: The path to install the certificate in WSL.
  • Example: Install-CertificateInWSL -CertFilePath "C:\Temp\cert.crt" -WSLDistro "Ubuntu" -UpdateCommand "update-ca-certificates" -CertPath "/usr/local/share/ca-certificates/"

Test-CertificateInWSL

  • Purpose: Checks the response from WSL using curl.
  • Parameters:
    • WSLDistro: The WSL distribution to check the certificate in.
    • Address: The address to test the certificate against.
  • Example: $response = Test-CertificateInWSL -WSLDistro "Ubuntu" -Address "https://google.com"

Main

  • Purpose: Main function to orchestrate the certificate search, export, installation, and verification.
  • Parameters:
    • DescriptionPattern: The pattern to search for in the certificate description.
    • ExcludeIssuers: An array of issuer names to exclude from the results.
    • WSLDistro: The WSL distribution to install the certificate in.
    • UpdateCommand: The command to update the CA certificates.
    • Verbose: Enables verbose output.
  • Example: Main -DescriptionPattern "CA" -ExcludeIssuers @("DigiCert", "thawte") -WSLDistro "Ubuntu" -Verbose

Related Links

@JosephLofving
Copy link

Absolutely amazing. Thank you! Spent hours trying to get my certs to work, and this worked beautifully.

@JustACasual
Copy link

Hi @emilwojcik93, thank you so so much for this script.
It helped me solve my own problem. Would you be interested in turning this into a small Repo to allow for public contributions and issues?

Otherwise, I could also do it and link here, if you don't mind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment