Files
runner-images/images/win/scripts/Installers/Install-RootCA.ps1
Marinus Pfund 59997be01a Add retry to Install-RootCA.ps1 generateSSTFromWU (#3018)
* Update Install-RootCA.ps1

added retry behaviour to certutil.exe -generateSSTFromWU

* Update Install-RootCA.ps1

removed multi line

* fixed pr comments in Install-RootCA.ps1

fixed PR comments
2021-04-12 10:50:39 +03:00

149 lines
4.6 KiB
PowerShell

# https://www.sysadmins.lv/blog-en/how-to-retrieve-certificate-purposes-property-with-cryptoapi-and-powershell.aspx
# https://www.sysadmins.lv/blog-en/dump-authroot-and-disallowed-certificates-with-powershell.aspx
# https://www.sysadmins.lv/blog-en/constraining-extended-key-usages-in-microsoft-windows.aspx
function Add-ExtendedCertType {
$signature = @"
[DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CertGetCertificateContextProperty(
IntPtr pCertContext,
uint dwPropId,
Byte[] pvData,
ref uint pcbData
);
[DllImport("Crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CertSetCertificateContextProperty(
IntPtr pCertContext,
int dwPropId,
uint dwFlags,
IntPtr pvData
);
"@
Add-Type -MemberDefinition $signature -Namespace PKI -Name Cert
}
function Get-CertificatesWithoutPropId {
# List installed certificates
$certs = Get-ChildItem -Path Cert:\LocalMachine\Root
Write-Host "Certificates without CERT_NOT_BEFORE_FILETIME_PROP_ID property"
$certsWithoutPropId = @{}
$certs | ForEach-Object -Process {
$certHandle = $_.Handle
$isPropertySet = [PKI.Cert]::CertGetCertificateContextProperty(
$certHandle, $CERT_NOT_BEFORE_FILETIME_PROP_ID, $null, [ref]$null
)
if (-not $isPropertySet) {
Write-Host "Subject: $($_.Subject)"
$certsWithoutPropId[$_.Thumbprint] = $null
}
}
$certsWithoutPropId
}
function Invoke-WithRetry {
<#
.SYNOPSIS
Runs $command block until $BreakCondition or $RetryCount is reached.
#>
param([ScriptBlock]$Command, [ScriptBlock] $BreakCondition, [int] $RetryCount=5, [int] $Sleep=10)
$c = 0
while($c -lt $RetryCount){
$result = & $Command
if(& $BreakCondition){
break
}
Start-Sleep $Sleep
$c++
}
$result
}
function Import-SSTFromWU {
# Serialized Certificate Store File
$sstFile = "$env:TEMP\roots.sst"
# Generate SST from Windows Update
$result = Invoke-WithRetry { certutil.exe -generateSSTFromWU $sstFile } {$LASTEXITCODE -eq 0}
if ($LASTEXITCODE -ne 0) {
Write-Host "[Error]: failed to generate $sstFile sst file`n$result"
exit $LASTEXITCODE
}
$result = certutil.exe -dump $sstFile
if ($LASTEXITCODE -ne 0) {
Write-Host "[Error]: failed to dump $sstFile sst file`n$result"
exit $LASTEXITCODE
}
try {
Import-Certificate -FilePath $sstFile -CertStoreLocation Cert:\LocalMachine\Root
} catch {
Write-Host "[Error]: failed to import ROOT CA`n$_"
exit 1
}
}
function Clear-CertificatesPropId {
param([hashtable]$CertsWithoutPropId)
# List installed certificates
$certs = Get-ChildItem -Path Cert:\LocalMachine\Root
# Clear property CERT_NOT_BEFORE_FILETIME_PROP_ID
$certs | ForEach-Object -Process {
$thumbprint = $_.Thumbprint
if ($certsWithoutPropId.ContainsKey($thumbprint)) {
$subject = $_.Subject
$certHandle = $_.Handle
$result = [PKI.Cert]::CertSetCertificateContextProperty(
$certHandle, $CERT_NOT_BEFORE_FILETIME_PROP_ID, 0, [System.IntPtr]::Zero
)
if ($result) {
Write-Host "[Success] Clear CERT_NOT_BEFORE_FILETIME_PROP_ID property $subject"
} else {
Write-Host "[Fail] Clear CERT_NOT_BEFORE_FILETIME_PROP_ID property $subject"
}
}
}
}
function Disable-RootAutoUpdate {
Write-Host "Disable auto root update mechanism"
$regPath = "HKLM:\Software\Policies\Microsoft\SystemCertificates\AuthRoot"
$regKey = "DisableRootAutoUpdate"
# Create the registry key if it doesn't exist
if (-not (Test-Path $regPath)) {
Write-Verbose "Creating $regPath"
New-Item $regPath | Out-Null
}
Set-ItemProperty $regPath -Name $regKey -Type DWord -Value 1
}
# Property to remove
$CERT_NOT_BEFORE_FILETIME_PROP_ID = 126
# Add extended cert type
Add-ExtendedCertType
# Get certificates without property CERT_NOT_BEFORE_FILETIME_PROP_ID
$certsWithoutPropId = Get-CertificatesWithoutPropId
# Download and install the latest version of root ca list
Import-SSTFromWU
# Clear property CERT_NOT_BEFORE_FILETIME_PROP_ID
if ($certsWithoutPropId.Count -gt 0) {
Clear-CertificatesPropId -CertsWithoutPropId $certsWithoutPropId
} else {
Write-Host "Nothing to clear"
}
# Disable auto root update mechanism
Disable-RootAutoUpdate