Files
powershell-scripts/winrm-https/winrm-ca-scripts/Sign-BulkCertificates.ps1
cproudlock 62c0c7bb06 Initial commit: Organized PowerShell scripts for ShopDB asset collection
Structure:
- asset-collection/: Local PC data collection scripts
- remote-execution/: WinRM remote execution scripts
- setup-utilities/: Configuration and testing utilities
- registry-backup/: GE registry backup scripts
- winrm-https/: WinRM HTTPS certificate setup
- docs/: Complete documentation

Each folder includes a README with detailed documentation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 10:57:54 -05:00

228 lines
7.2 KiB
PowerShell

#Requires -RunAsAdministrator
param(
[Parameter(Mandatory=$false)]
[string]$HostnameFile = "shopfloor-hostnames.txt",
[Parameter(Mandatory=$false)]
[string]$CAPfxPath,
[string]$Domain = "logon.ds.ge.com",
[string]$OutputPath = ".\pc-certificates",
[int]$ValidityYears = 2,
[SecureString]$CAPassword,
[SecureString]$CertificatePassword
)
Write-Host ""
Write-Host "=== Bulk PC Certificate Signing ===" -ForegroundColor Cyan
Write-Host ""
# Check hostname file
if (-not (Test-Path $HostnameFile)) {
Write-Host "[ERROR] Hostname file not found: $HostnameFile" -ForegroundColor Red
Write-Host "Looking for: $HostnameFile" -ForegroundColor Yellow
exit 1
}
$hostnames = Get-Content $HostnameFile | Where-Object {$_ -match '\S'} | ForEach-Object {$_.Trim()}
Write-Host "Found $($hostnames.Count) hostnames to process"
Write-Host ""
# Auto-detect CA file if not specified
if (-not $CAPfxPath) {
Write-Host "Looking for CA certificate file..." -ForegroundColor Yellow
$caFiles = Get-ChildItem -Filter "*CA*.pfx" | Sort-Object LastWriteTime -Descending
if ($caFiles.Count -eq 0) {
Write-Host "[ERROR] No CA PFX file found in current directory" -ForegroundColor Red
Write-Host "Please specify -CAPfxPath parameter or ensure CA PFX file is in current directory" -ForegroundColor Yellow
exit 1
}
if ($caFiles.Count -gt 1) {
Write-Host "Multiple CA files found:" -ForegroundColor Yellow
for ($i = 0; $i -lt $caFiles.Count; $i++) {
Write-Host " [$i] $($caFiles[$i].Name) (Modified: $($caFiles[$i].LastWriteTime))"
}
$selection = Read-Host "Select CA file number (0-$($caFiles.Count - 1))"
$CAPfxPath = $caFiles[$selection].FullName
} else {
$CAPfxPath = $caFiles[0].FullName
Write-Host "[OK] Found CA file: $($caFiles[0].Name)" -ForegroundColor Green
}
Write-Host ""
}
# Check CA file
if (-not (Test-Path $CAPfxPath)) {
Write-Host "[ERROR] CA PFX file not found: $CAPfxPath" -ForegroundColor Red
exit 1
}
# Get passwords
if (-not $CAPassword) {
$CAPassword = Read-Host "Enter CA certificate password" -AsSecureString
}
if (-not $CertificatePassword) {
$CertificatePassword = Read-Host "Enter password for PC certificates (same for all)" -AsSecureString
}
# Load CA certificate
Write-Host "Loading CA certificate..."
try {
$caCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CAPfxPath, $CAPassword, 'Exportable')
Write-Host "[OK] CA loaded: $($caCert.Subject)"
Write-Host " Thumbprint: $($caCert.Thumbprint)"
Write-Host ""
} catch {
Write-Host "[ERROR] Failed to load CA: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
if (-not $caCert.HasPrivateKey) {
Write-Host "[ERROR] CA certificate does not have private key" -ForegroundColor Red
exit 1
}
# Create output directory
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$batchPath = Join-Path $OutputPath "batch-$timestamp"
New-Item -ItemType Directory -Path $batchPath -Force | Out-Null
Write-Host "Output directory: $batchPath"
Write-Host ""
Write-Host "Processing certificates..."
Write-Host ""
$results = @()
$successCount = 0
$failCount = 0
$counter = 0
foreach ($hostname in $hostnames) {
$counter++
$hostname = $hostname.Trim() -replace "\.$Domain$", ""
$fqdn = "$hostname.$Domain".ToLower()
Write-Host "[$counter/$($hostnames.Count)] $hostname ... " -NoNewline
try {
$notAfter = (Get-Date).AddYears($ValidityYears)
$pcCert = New-SelfSignedCertificate `
-Subject "CN=$fqdn" `
-DnsName @($fqdn, $hostname) `
-KeyExportPolicy Exportable `
-KeyUsage DigitalSignature,KeyEncipherment `
-KeyLength 2048 `
-KeyAlgorithm RSA `
-HashAlgorithm SHA256 `
-CertStoreLocation 'Cert:\LocalMachine\My' `
-NotAfter $notAfter `
-TextExtension '2.5.29.37={text}1.3.6.1.5.5.7.3.1' `
-Signer $caCert
# Export PFX
$pfxPath = Join-Path $batchPath "$hostname-$Domain-$timestamp.pfx"
Export-PfxCertificate -Cert $pcCert -FilePath $pfxPath -Password $CertificatePassword | Out-Null
# Export CER
$cerPath = Join-Path $batchPath "$hostname-$Domain-$timestamp.cer"
Export-Certificate -Cert $pcCert -FilePath $cerPath | Out-Null
# Remove from store
Remove-Item "Cert:\LocalMachine\My\$($pcCert.Thumbprint)" -Force -ErrorAction SilentlyContinue
Write-Host "OK" -ForegroundColor Green
$results += [PSCustomObject]@{
Hostname = $hostname
FQDN = $fqdn
Thumbprint = $pcCert.Thumbprint
ValidUntil = $pcCert.NotAfter
PFXFile = Split-Path $pfxPath -Leaf
Status = "Success"
Error = $null
}
$successCount++
} catch {
Write-Host "FAILED: $($_.Exception.Message)" -ForegroundColor Red
$results += [PSCustomObject]@{
Hostname = $hostname
FQDN = $fqdn
Thumbprint = $null
ValidUntil = $null
PFXFile = $null
Status = "Failed"
Error = $_.Exception.Message
}
$failCount++
}
}
# Export results
$csvPath = Join-Path $batchPath "certificate-list.csv"
$results | Export-Csv -Path $csvPath -NoTypeInformation
$summaryPath = Join-Path $batchPath "SUMMARY.txt"
$summaryContent = @"
Certificate Signing Summary
===========================
Date: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
Batch: $timestamp
Statistics:
Total: $($hostnames.Count)
Successful: $successCount
Failed: $failCount
CA Certificate:
Subject: $($caCert.Subject)
Thumbprint: $($caCert.Thumbprint)
Output Directory: $batchPath
Files:
- $successCount PFX files (certificates with private keys)
- $successCount CER files (public certificates)
- certificate-list.csv (spreadsheet)
Next Steps:
1. Install CA certificate on management computers:
Import-Certificate -FilePath 'CA.cer' -CertStoreLocation Cert:\LocalMachine\Root
2. Deploy certificates to PCs (each PC gets its own):
- Copy PFX file to PC
- Import: Import-PfxCertificate -FilePath 'HOSTNAME.pfx' -CertStoreLocation Cert:\LocalMachine\My -Password `$pass
- Configure WinRM: .\Setup-WinRM-HTTPS.ps1 -CertificateThumbprint THUMBPRINT -Domain logon.ds.ge.com
3. Connect from management computer:
Enter-PSSession -ComputerName HOSTNAME.logon.ds.ge.com -Credential `$cred -UseSSL -Port 5986
(No -SessionOption needed!)
"@
$summaryContent | Out-File -FilePath $summaryPath -Encoding UTF8
Write-Host ""
Write-Host "=== CERTIFICATE SIGNING COMPLETE ===" -ForegroundColor Green
Write-Host ""
Write-Host "Summary:"
Write-Host " Total: $($hostnames.Count)"
Write-Host " Successful: $successCount" -ForegroundColor Green
Write-Host " Failed: $failCount" -ForegroundColor $(if($failCount -gt 0){'Red'}else{'Green'})
Write-Host ""
Write-Host "Output: $batchPath"
Write-Host ""
Write-Host "Files:"
Write-Host " - certificate-list.csv (list of all certificates)"
Write-Host " - SUMMARY.txt (detailed summary)"
Write-Host " - $successCount PFX files (one per PC)"
Write-Host ""