mirror of
https://github.com/actions/runner-images.git
synced 2025-12-15 06:08:07 +00:00
* 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
149 lines
4.6 KiB
PowerShell
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
|