Skip to content

Instantly share code, notes, and snippets.

@mhudasch
Last active February 9, 2022 12:27
Show Gist options
  • Save mhudasch/696ff53140dd7c5ce13687e2a7395beb to your computer and use it in GitHub Desktop.
Save mhudasch/696ff53140dd7c5ce13687e2a7395beb to your computer and use it in GitHub Desktop.
Exports trusted root CAs to programs that do not use the Windows Certificate Store
#Requires -Version 5
#Requires -PSEdition Desktop
function Get-RootCAFromUrl {
[CmdletBinding()]
param(
# The uri of the website with the server certificate
[Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[uri]
[Alias("WebSite")]
$Url
)
$requestCertificate = $null;
$currentSecurityProtocol = [Net.ServicePointManager]::SecurityProtocol;
[Net.ServicePointManager]::SecurityProtocol = ($currentSecurityProtocol -bor
[Net.SecurityProtocolType]::Tls11 -bor
[Net.SecurityProtocolType]::Tls12)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [scriptblock] {
param(
$validationSender,
$validationX509Cert,
$validationX509Chain,
$validationSSLPolicyErrors
)
$ErrorActionPreference = "Stop";
$certificate2 = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList @($validationX509Cert);
if($null -eq ("System.IdentityModel.Selectors.X509CertificateValidator" -as [Type])) {
# certificate validator type is not known here
Write-Verbose -Message "X509CertificateValidator type is unknown. Assembly gets loaded.";
Add-Type -AssemblyName "System.IdentityModel" | Out-Null;
}
try {
[System.IdentityModel.Selectors.X509CertificateValidator]::PeerOrChainTrust.Validate($certificate2);
}
catch [System.IdentityModel.Tokens.SecurityTokenValidationException] {
Write-Verbose -Message "The server certificate of url: '$Url' ($($certificate2.Issuer)) was not trustworthy.";
Write-Debug -Message $Error[0].Exception.Message;
return $false;
}
$validationX509ChainRoot = @($validationX509Chain.ChainElements) | Select-Object -Last 1;
$rootCertificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList @($validationX509ChainRoot.Certificate)
Set-Variable -Name "requestCertificate" -Scope 1 -Value $rootCertificate;
$x509Issuer = "# Issuer: $($rootCertificate.Issuer)";
$x509Subject = "# Subject: $($rootCertificate.Subject)";
$x509Label = "# Label: `"$($rootCertificate.GetNameInfo("SimpleName", $false))`"";
$x509Serial = "# Serial: $($rootCertificate.SerialNumber)";
Write-Verbose -Message $(@("--Root Certificate--", $x509Issuer, $x509Subject, $x509Label, $x509Serial) -join "`n")
return $certificate2.Verify() -and $rootCertificate.Verify();
};
try {
$retryCount = 0;
$ex = $null;
while($retryCount -lt 5) {
try {
$request = [Net.HttpWebRequest]::Create($Url);
$request.GetResponse() | Out-Null;
break;
}
catch [System.Net.WebException] {
$ex = $_.Exception;
Write-Verbose -Message "Request failed. Reason: $($Error[0].Exception.Message)";
if($null -ne $requestCertificate) {
Write-Verbose -Message "We still could aquire the certificate we need!";
break;
}
$retryCount++;
if($retryCount -gt 5) {
break;
} else {
continue;
}
}
}
if (-not($requestCertificate)) {
throw "The given web site at url: '$Url' did not have a server certificate. Or the web request did not end in success state. ($($ex.Message))";
}
} finally {
# remove global cert validation callback
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null;
# revert back to security protocol defined earlier
[Net.ServicePointManager]::SecurityProtocol = $currentSecurityProtocol;
}
$x509 = $requestCertificate;
$bytes = $x509.Export("Cert");
$base64 = [Convert]::ToBase64String($bytes, "None");
$chunkSize = 64;
$base64WithLineBreaks = "";
# split the base64 string into chunks of 64 characters
# we do not use ToBase64String($bytes, "InsertLineBreaks") on purpose
# because it creates lines that are longer than 64 characters
for ($i = 0; $i -lt $base64.Length; $i += $chunkSize) {
$base64WithLineBreaks = $base64WithLineBreaks + $($base64.Substring($i, [Math]::Min($chunkSize, $base64.Length - $i)) + ([System.Environment]::NewLine));
}
$pem = "-----BEGIN CERTIFICATE-----$([System.Environment]::NewLine)$base64WithLineBreaks-----END CERTIFICATE-----";
$pem | Write-Output;
}
function Export-RootCA {
[CmdletBinding()]
param (
# The certificate to trust in base64 format (pem)
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[String]
[ValidateNotNullOrEmpty()]
[Alias("Base64", "Pem", "Certificate")]
$Base64Certificate,
# The target program that cannot access the Windows Certificate Store.
[Parameter(Mandatory = $true)]
[ValidateSet("Git", "Curl", "Rider", "WebStorm", "Java", "Node", "NPM", "AzureCli", "All")]
[String[]]
$Target
)
$principal = New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent());
if (-not($principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))) {
throw "This command must be executed in elevated mode. Please start a command prompt as an administrator and try again." +
" The elevated mode is needed to access the several certificate stores.";
}
$javaBasedTooling = [scriptblock] {
param($jh, $cert)
if (-not(Test-Path -Path $jh)) {
Write-Error -Message "Could not locate a JVM installation under '$jh'.";
}
$certificateTempFolder = $([environment]::GetFolderPath('UserProfile'));
$jreBinFolder = Get-ChildItem -Path $jh -Filter "bin" -Directory -ErrorAction "Ignore";
if (-not(Test-Path -Path "$($jreBinFolder.FullName)\keytool.exe")) {
Write-Verbose -Message "Cannot find keytool in path '$($jreBinFolder.FullName)'.";
return;
}
$jreKeyStore = Get-ChildItem -Path $jh -Filter "lib/security/cacerts" -File -ErrorAction "Ignore" | Select-Object -ExpandProperty "FullName";
if (-not($jreKeyStore)) {
Write-Verbose -Message "Could not find certificate store for trusted ca certificates.";
return;
}
$base64Raw = (($cert -ireplace "-----BEGIN CERTIFICATE-----", "") -ireplace "-----END CERTIFICATE-----", "") -ireplace "`r?`n", ""
$x509 = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList @(, ([System.Convert]::FromBase64String($base64Raw)));
$certificatePath = [IO.Path]::Combine($certificateTempFolder, "temp.cer");
$certCN = [System.Text.RegularExpressions.RegEx]::Match($x509.Subject, "CN\=(.+?),").Groups[1].Value;
$certVersion = $x509.Version;
if (-not($certCN)) {
Write-Verbose -Message "The given certificate has not valid cn.";
return;
}
$certAlias = $certCN.Replace(" ", "").ToLowerInvariant() + $certVersion.ToString();
$x509Bytes = $x509.Export("Cert");
if (Test-Path -Path $certificatePath) {
Remove-Item -Path $certificatePath -Force -ErrorAction "Ignore" | Out-Null;
}
[io.File]::WriteAllBytes($certificatePath, $([byte[]]$x509Bytes));
try {
$keyToolQueryCommand = "`"$($jreBinFolder.FullName)\keytool.exe`" -list -rfc -keystore `"$jreKeyStore`" -storepass changeit -noprompt";
Write-Verbose -Message "> $keyToolQueryCommand";
$keyToolQueryResult = (& cmd /s /c " $keyToolQueryCommand " *>&1) | Out-string;
Write-Debug -Message $keyToolQueryResult;
if (-not($keyToolQueryResult) -or $keyToolQueryResult -imatch "keytool error\:") {
Write-Verbose -Message "keytool query failed.";
return;
}
if ($keyToolQueryResult -imatch "Alias name\: $certAlias") {
Write-Verbose -Message "The keystore already contains the certificate you are trying to import.";
return;
}
$keyToolImportCommand = "`"$($jreBinFolder.FullName)\keytool.exe`" -import -trustcacerts -file `"$certificatePath`" -keystore `"$jreKeyStore`" -storepass changeit -noprompt -alias `"$certAlias`" "
Write-Verbose -Message "> $keyToolImportCommand";
$keyToolImportResult = (& cmd /s /c " $keyToolImportCommand " *>&1) | Out-String;
Write-Verbose -Message $keyToolImportResult;
if (-not($keyToolImportResult) -or $keyToolImportResult -imatch "keytool error\:") {
Write-Verbose -Message "keytool import failed.";
return;
}
}
finally {
Remove-Item -Path $certificatePath -Force -ErrorAction "Ignore" | Out-Null;
}
}
$jetbrainsTooling = [scriptblock] {
param($exec, $cert)
Write-Host "Locating all $exec installations (this could take several minutes)...";
$toolExecutables = @(Get-ChildItem -Path "C:\" -File -Filter $exec -Recurse -Force -ErrorAction "Ignore");
Write-Host "Found $($toolExecutables.Count) installations of $exec";
if (0 -eq $toolExecutables.Count) {
return;
}
$toolExecutables | ForEach-Object { $_ | Write-Host }
foreach ($toolExecutable in $toolExecutables) {
Write-Verbose -Message "Try to locate the JVM used by $exec installation at $($toolExecutable.FullName)";
$toolBinFolder = Split-Path $toolExecutable.FullName -Parent;
$toolRootFolder = Split-Path $toolBinFolder -Parent;
$jreRootFolder = Get-ChildItem -Path $toolRootFolder -Filter "jbr" -Directory -ErrorAction "Ignore";
if (-not($jreRootFolder)) {
Write-Verbose -Message "Could not locate the JVM for the '$toolExecutable' installation.";
continue;
}
$javaBasedTooling.InvokeReturnAsIs($jreRootFolder.FullName, $cert);
}
}
$locateGitCAStore = [scriptblock] {
if (-not(Get-Command -Name git -ErrorAction "Ignore")) {
Write-Warning "Git is not installed on the computer or is not available as command." +
" If it is installed please add it to the PATH environment variable of the user.";
return $null;
}
$gitConfiguredRootCA = (git config --get http.sslcainfo);
$gitConfiguredSslBackend = (git config --get http.sslbackend);
if ("schannel" -ieq $gitConfiguredSslBackend) {
$gitExecutableLocation = Get-Command -Name git | Select-Object -ExpandProperty Definition;
if (Test-Path -Path $gitExecutableLocation) {
$gitInstallRoot = Split-Path -Path (Split-Path -Path $gitExecutableLocation -Parent) -Parent;
$minwCerts = [io.Path]::Combine($gitInstallRoot, "mingw64", "ssl", "certs", "ca-bundle.crt");
if (Test-Path -Path $minwCerts) {
git config --system http.sslcainfo "$minwCerts";
$gitConfiguredRootCA = (git config --get http.sslcainfo);
}
}
throw "Setting a ssl ca info location is not possible when the 'http.sslbackend' is configured for 'schannel'. " +
"Please change the value to 'openssl' to go on. The command to change the setting is 'git config http.sslbackend openssl'. " +
"To change the setting globally add the '--global' parameter.";
}
if (-not($gitConfiguredRootCA)) {
Write-Warning -Message "The current git ssl ca info location is not configured.";
return $null;
}
if (-not(Test-Path -Path $gitConfiguredRootCA)) {
Write-Warning -Message "The current git ssl ca info location configured but does not exist.";
Write-Warning -Message "Creating a new ssl ca info file under '$gitConfiguredRootCA'.";
New-Item -ItemType File -Path $gitConfiguredRootCA -ErrorAction "Ignore" | Out-Null;
if (-not(Test-Path -Path $gitConfiguredRootCA)) {
Write-Verbose -Message "Could not create a new ssl ca info file under '$gitConfiguredRootCA'.";
return $null;
}
}
return $gitConfiguredRootCA;
};
$locateCurlCAStore = [scriptblock] {
param($curlProxy)
if ($env:CURL_CA_BUNDLE -and (Test-Path -Path $env:CURL_CA_BUNDLE)) {
Write-Verbose -Message "A valid ca store for curl is saved under '$env:CURL_CA_BUNDLE' (from CURL_CA_BUNDLE environment variable).";
return $env:CURL_CA_BUNDLE;
}
if ($env:REQUESTS_CA_BUNDLE -and (Test-Path -Path $env:REQUESTS_CA_BUNDLE)) {
Write-Verbose -Message "A valid ca store for curl is saved under '$env:REQUESTS_CA_BUNDLE' (from REQUESTS_CA_BUNDLE environment variable).";
return $env:REQUESTS_CA_BUNDLE;
}
if (-not(Get-Command -Name curl -ErrorAction "Ignore")) {
Write-Warning -Message "Curl is not installed on the computer or is not available as command." +
" If it is installed please add it to the PATH environment variable of the user.";
Write-Warning -Message "No separate curl installation found so libcurl is likely in use.";
return $null;
}
$curlExecutable = Get-Command -Name "curl" | Select-Object -ExpandProperty "Definition";
$curlCAQueryCommand = " `"$curlExecutable`" --cacert nonexistent https://www.github.com";
Write-Verbose -Message "> $curlCAQueryCommand";
$curlResult = (& cmd.exe /s /c " `"$curlExecutable`" --cacert nonexistent https://www.github.com" *>&1) | Out-String
Write-Debug -Message $curlResult;
if ($curlResult -and $curlResult -imatch "Could not resolve host") {
if (-not($curlProxy)) {
Write-Verbose -Message "Curl could not reach github and no proxy was given.";
return $null;
}
# missing proxy
Write-Verbose -Message "Host could not be resolved. This is likely caused by a non-defined proxy.";
$curlCAQueryCommand = " `"$curlExecutable`" --cacert nonexistent https://www.github.com --proxy $curlProxy --verbose";
Write-Verbose -Message "> $curlCAQueryCommand";
$curlResult = (& cmd.exe /s /c " `"$curlExecutable`" --cacert nonexistent https://www.github.com --proxy $curlProxy --verbose" *>&1) | Out-String;
Write-Debug -Message $curlResult;
}
if ($curlResult -and $curlResult -imatch "CApath\:\s*none") {
Write-Verbose -Message "The current curl trusted root ca store location is not configured.";
return $null;
}
elseif ($curlResult -and $curlResult -imatch "(?i)CApath\:\s*(?<crtPath>.*?)") {
$crtFileMatch = [System.Text.RegularExpressions.Regex]::Match($curlResult, "(?i)CApath\:\s*(?<crtPath>.*?)");
if (-not($crtFileMatch.Success)) {
throw "Curl executable could not communicate the correct path of its CApath variable.";
}
return $crtFileMatch.Groups["crtPath"].Value;
}
return $null;
};
$locateNodeCAStore = [scriptblock] {
if (-not(Get-Command -Name node -ErrorAction "Ignore")) {
Write-Warning -Message "Node is not installed on the computer or is not available as command." +
" If it is installed please add it to the PATH environment variable of the user.";
return $null;
}
if ($env:NODE_EXTRA_CA_CERTS -and (Test-Path -Path $env:NODE_EXTRA_CA_CERTS)) {
return $env:NODE_EXTRA_CA_CERTS;
}
return $null;
}
$locateAzureCliCAStore = [scriptblock] {
if(-not(Get-Command -Name az -ErrorAction "Ignore")) {
Write-Warning -Message "The Azure CLI is not installed on the computer or is not available as command." +
" If it is installed pleasse add it to PATH environment variable of the user.";
return $null;
}
$azExecutable = Get-Command -Name az | Select-Object -ExpandProperty "Definition";
$certifiLibPemFilePath = [io.path]::Combine($([io.path]::GetDirectoryName($azExecutable)), "../Lib/site-packages/certifi/cacert.pem");
if(-not(Test-Path -Path $certifiLibPemFilePath)) {
throw "The cacert.pem file used in the Azure CLI cannot be found at the expected location.";
}
return $certifiLibPemFilePath;
}
$locateNpmCAStore = [scriptblock] {
if (-not(Get-Command -Name npm -ErrorAction "Ignore")) {
Write-Warning -Message "NPM is not installed on the computer or is not available as command." +
" If it is installed please add it to the PATH environment variable of the user.";
return $null;
}
$npmConfiguration = (npm config ls -l);
$configuredCAFileMatch = [System.Text.RegularExpressions.Regex]::Match($npmConfiguration, '(?i)cafile\s*\=\s*\"(?<caFile>.*?)\"');
if(-not($configuredCAFileMatch.Success)) {
return $null
}
return $configuredCAFileMatch.Groups["caFile"].Value;
}
$createNewCAStore = [scriptblock] {
$storePath = [io.path]::Combine("$([environment]::GetFolderPath('UserProfile'))", "ssl", "ca_certs.crt");
Write-Host "Creating new trusted root CA store at '$storePath'.";
New-Item -Path $([io.path]::Combine("$([environment]::GetFolderPath('UserProfile'))", "ssl")) -ItemType Directory -Force -ErrorAction Stop | Out-Null;
Set-Content -Path $([io.path]::Combine("$([environment]::GetFolderPath('UserProfile'))", "ssl", "ca_certs.crt")) -Value "" -Encoding utf8;
Write-Host "Done creating new trusted root CA store at '$storePath'.";
return $storePath;
}
$crtContainsPem = [scriptblock] {
param($crtFilePath, $pemCertificate)
$crtFileContent = Get-Content -Path $crtFilePath -Raw;
$pemMatch = [System.Text.RegularExpressions.Regex]::Match($pemCertificate, "-+BEGIN CERTIFICATE-+\r?\n((?:.+\r?\n)+?)-+END CERTIFICATE-+");
$certificateMatches = [System.Text.RegularExpressions.Regex]::Matches($crtFileContent, "-+BEGIN CERTIFICATE-+\n((?:.+\n)+?)-+END CERTIFICATE-+");
if (-not($pemMatch.Success) -or 0 -eq $certificateMatches.Count) {
return $false;
}
foreach ($certificateMatch in $certificateMatches) {
$cleanedCertificateMatch = $certificateMatch.Groups[1].Value -ireplace "`r?`n", "";
$cleanedPemMatch = $pemMatch.Groups[1].Value -ireplace "`r?`n", "";
if ($cleanedCertificateMatch -eq $cleanedPemMatch) {
return $true
}
}
return $false;
}
$beautifyCert = [scriptblock] {
param($base64Cert)
$base64Raw = (($base64Cert -ireplace "-----BEGIN CERTIFICATE-----", "") -ireplace "-----END CERTIFICATE-----", "") -ireplace "`r?`n", ""
$base64RawBytes = [System.Convert]::FromBase64String($base64Raw);
$x509 = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList @(, $base64RawBytes);
$x509Issuer = "# Issuer: $($x509.Issuer)";
$x509Subject = "# Subject: $($x509.Subject)";
$x509Label = "# Label: `"$($x509.GetNameInfo("SimpleName", $false))`"";
$x509Serial = "# Serial: $($x509.SerialNumber)";
$x509Md5 = "# MD5 Fingerprint: $( (@([System.Security.Cryptography.MD5]::Create().ComputeHash($base64RawBytes)) | ForEach-Object { $_.ToString('x2') }) -join ':' )";
$x509SHA1 = "# SHA1 Fingerprint: $( (@([System.Security.Cryptography.SHA1]::Create().ComputeHash($base64RawBytes)) | ForEach-Object { $_.ToString('x2') }) -join ':' )";
$x509SHA256 = "# SHA256 Fingerprint: $( (@([System.Security.Cryptography.SHA256]::Create().ComputeHash($base64RawBytes)) | ForEach-Object { $_.ToString('x2') }) -join ':' )";
(@($x509Issuer, $x509Subject, $x509Label, $x509Serial, $x509Md5, $x509SHA1, $x509SHA256) -join "`n") + "`n" + ($Base64Certificate -ireplace "`r?`n", "`n") | Write-Output;
}
if ($Target -icontains "all") {
$Target = @("Rider", "WebStorm", "Java", "Git", "Curl", "Node", "NPM");
}
foreach ($exportTarget in @($Target | Select-Object -Unique)) {
if ("Rider" -ieq $exportTarget) {
$jetbrainsTooling.InvokeReturnAsIs(@("rider64.exe", $Base64Certificate)) | Write-Output;
}
if ("WebStorm" -ieq $exportTarget) {
$jetbrainsTooling.InvokeReturnAsIs(@("webstorm64.exe", $Base64Certificate)) | Write-Output;
}
if ("Java" -ieq $exportTarget) {
$javaHome = $env:JAVA_HOME;
if (-not($javaHome)) {
# when there is no globally defined java runtime configured
# we take newest installed version
$probe = @(Get-ChildItem -Path ([io.Path]::Combine($env:ProgramFiles, "Java")) -Recurse -Filter "java.exe" -ErrorAction "Ignore");
if (-not($probe)) {
Write-Verbose -Message "Could not find a 64 bit installation of java.";
$probe = @(Get-ChildItem -Path ([io.Path]::Combine(${env:ProgramFiles(x86)}, "Java")) -Recurse -Filter "java.exe" -ErrorAction "Ignore");
if (-not($probe)) {
Write-Warning -Message "No installation of java found on this machine.";
return;
}
}
$newestVersion = $probe | Sort-Object -Property "DirectoryName" -Descending | Select-Object -First 1;
$javaHome = Split-Path -Path $(Split-Path -Path $newestVersion -Parent) -Parent;
}
$is32BitVersionHome = ($javaHome -match [System.Text.RegularExpressions.Regex]::Escape(${env:ProgramFiles(x86)}) -or
$javaHome -match [System.Text.RegularExpressions.Regex]::Escape("Progra~2"));
$is64BitVersionHome = ($javaHome -match [System.Text.RegularExpressions.Regex]::Escape($env:ProgramFiles) -or
$javaHome -match [System.Text.RegularExpressions.Regex]::Escape("Progra~1"));
if ($is32BitVersionHome) {
$32BitJavaHome = $javaHome;
$64BitJavaHome = [System.Text.RegularExpressions.Regex]::Replace($javaHome,
$([System.Text.RegularExpressions.Regex]::Escape(${env:ProgramFiles(x86)}) + "|" +
[System.Text.RegularExpressions.Regex]::Escape("Progra~2")),
$env:ProgramFiles);
}
if ($is64BitVersionHome) {
$32BitJavaHome = [System.Text.RegularExpressions.Regex]::Replace($javaHome,
$([System.Text.RegularExpressions.Regex]::Escape($env:ProgramFiles) + "|" +
[System.Text.RegularExpressions.Regex]::Escape("Progra~1")),
${env:ProgramFiles(x86)});
$64BitJavaHome = $javaHome;
}
if ($32BitJavaHome -and (Test-Path -Path $32BitJavaHome -ErrorAction "Ignore")) {
$javaBasedTooling.InvokeReturnAsIs($32BitJavaHome, $Base64Certificate);
}
if ($64BitJavaHome -and (Test-Path -Path $64BitJavaHome -ErrorAction "Ignore")) {
$javaBasedTooling.InvokeReturnAsIs($64BitJavaHome, $Base64Certificate);
}
}
if ("Git" -ieq $exportTarget) {
Write-Verbose -Message "Get the git ssl ca info location.";
$gitSslCrt = $locateGitCAStore.InvokeReturnAsIs();
if (-not($gitSslCrt)) {
Write-Warning -Message "The current git ssl ca info location is not known.";
# Creating one at '$home/ssl/ca_certs.crt'.";
$gitSslCrt = $createNewCAStore.InvokeReturnAsIs();
git config --global http.sslcainfo $gitSslCrt
}
Write-Host "The location of the git ssl ca info is '$gitSslCrt'.";
if ((-not($crtContainsPem.InvokeReturnAsIs(@($gitSslCrt, $Base64Certificate))))) {
$beautifyCert.InvokeReturnAsIs($Base64Certificate) | Add-Content -Path $gitSslCrt -Encoding utf8 -ErrorAction Stop;
Write-Host "Saved certificate in the crt file '$crtFile'.";
}
else {
Write-Host "The git ssl ca info store already contains the given certificate.";
}
}
if ("Curl" -ieq $exportTarget) {
$curlHttpProxy = if ($env:HTTPS_PROXY) { $env:HTTPS_PROXY } else { "http://localhost:9000" }
$crtFile = $locateCurlCAStore.InvokeReturnAsIs(@($curlHttpProxy));
if (-not($crtFile)) {
# fall back on the git configured trusted ca store file
$gitSslCrt = $locateGitCAStore.InvokeReturnAsIs();
if (-not($gitSslCrt)) {
# cannot fall back on git so we create a custom one
Write-Warning -Message "Cannot use git ca_certs so we create a new one and use it.";
$crtFile = $createNewCAStore.InvokeReturnAsIs();
}
else {
Write-Host "Using the ca_certs.crt of git as the one for curl.";
$crtFile = $gitSslCrt;
}
}
if (-not($crtContainsPem.InvokeReturnAsIs(@($crtFile, $Base64Certificate)))) {
$beautifyCert.InvokeReturnAsIs($Base64Certificate) | Add-Content -Path $crtFile -Encoding utf8 -ErrorAction Stop;
Write-Host "Saved certificate in the crt file '$crtFile'.";
}
else {
Write-Host "The curl trusted root ca store already contains the given certificate.";
}
if (-not($env:CURL_CA_BUNDLE) -or ($env:CURL_CA_BUNDLE -ne $crtFile)) {
[System.Environment]::SetEnvironmentVariable("CURL_CA_BUNDLE", ($crtFile -replace "\/", "\"), "User");
Write-Verbose -Message "Set the curl trusted root ca store '$crtFile' as new CURL_CA_BUNDLE in user environment variables.";
}
if (-not($env:REQUESTS_CA_BUNDLE) -or ($env:REQUESTS_CA_BUNDLE -ne $crtFile)) {
[System.Environment]::SetEnvironmentVariable("REQUESTS_CA_BUNDLE", ($crtFile -replace "\/", "\"), "User");
Write-Verbose -Message "Set the curl trusted root ca store '$crtFile' as new REQUESTS_CA_BUNDLE in user environment variables.";
}
}
if ("Node" -ieq $exportTarget) {
$crtFile = $locateNodeCAStore.InvokeReturnAsIs();
if (-not($crtFile)) {
# fall back on the git configured trusted ca store file
$gitSslCrt = $locateGitCAStore.InvokeReturnAsIs();
if (-not($gitSslCrt)) {
# cannot fall back on git so we create a custom one
Write-Warning -Message "Cannot use git ca_certs so we create a new one and use it.";
$crtFile = $createNewCAStore.InvokeReturnAsIs();
}
else {
Write-Host "Using the ca_certs.crt of git as the one for node.";
$crtFile = $gitSslCrt;
}
}
if (-not($crtContainsPem.InvokeReturnAsIs(@($crtFile, $Base64Certificate)))) {
$beautifyCert.InvokeReturnAsIs($Base64Certificate) | Add-Content -Path $crtFile -Encoding utf8 -ErrorAction Stop;
Write-Host "Saved certificate in the crt file '$crtFile'.";
}
else {
Write-Host "The node extra trusted root ca store already contains the given certificate.";
}
if (-not($env:NODE_EXTRA_CA_CERTS) -or ($env:NODE_EXTRA_CA_CERTS -ne $crtFile)) {
[System.Environment]::SetEnvironmentVariable("NODE_EXTRA_CA_CERTS", ($crtFile -replace "\/", "\"), "User");
Write-Verbose -Message "Set the node extra trusted root ca store '$crtFile' as new NODE_EXTRA_CA_CERTS in user environment variables.";
}
}
if("NPM" -ieq $exportTarget) {
$crtFile = $locateNpmCAStore.InvokeReturnAsIs();
$setInNpmRc = $null -eq $crtFile;
if (-not($crtFile)) {
# fall back on the git configured trusted ca store file
$gitSslCrt = $locateGitCAStore.InvokeReturnAsIs();
if (-not($gitSslCrt)) {
# cannot fall back on git so we create a custom one
Write-Warning -Message "Cannot use git ca_certs so we create a new one and use it.";
$crtFile = $createNewCAStore.InvokeReturnAsIs();
}
else {
Write-Host "Using the ca_certs.crt of git as the one for node.";
$crtFile = $gitSslCrt;
}
}
if (-not($crtContainsPem.InvokeReturnAsIs(@($crtFile, $Base64Certificate)))) {
$beautifyCert.InvokeReturnAsIs($Base64Certificate) | Add-Content -Path $crtFile -Encoding utf8 -ErrorAction Stop;
Write-Host "Saved certificate in the crt file '$crtFile'.";
}
else {
Write-Host "The npm root ca store already contains the given certificate.";
}
if($setInNpmRc -and (Get-Command -Name npm -ErrorAction "Ignore")) {
Write-Verbose -Message "Setting npm root ca store to '$crtFile'.";
$npmResult = (npm config set cafile '"$crtFile"');
@($npmResult) | ForEach-Object { Write-Verbose -Message $_; };
}
}
if("AzureCli" -ieq $exportTarget) {
$crtFile = $locateAzureCliCAStore.InvokeReturnAsIs();
if($null -eq $crtFile) {
Write-Warning -Message "No installation of Azure CLI found on this machine.";
return;
}
if (-not($crtContainsPem.InvokeReturnAsIs(@($crtFile, $Base64Certificate)))) {
$beautifyCert.InvokeReturnAsIs($Base64Certificate) | Add-Content -Path $crtFile -Encoding utf8 -ErrorAction Stop;
Write-Host "Saved certificate in the crt file '$crtFile'.";
} else {
Write-Host "The Azure CLI root ca store already contains the given certificate.";
}
}
}
}
@mhudasch
Copy link
Author

The [System.Net.ServicePointManager]::ServerCertificateValidationCallback is not available in PowerShell Core. see PowerShell/PowerShell#4899 ... So I had to limit the script to PowerShell 5.

@mhudasch
Copy link
Author

Added support for Azure CLI pem file insertion.

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