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>
This commit is contained in:
227
winrm-https/winrm-ca-scripts/Sign-BulkCertificates.ps1
Normal file
227
winrm-https/winrm-ca-scripts/Sign-BulkCertificates.ps1
Normal file
@@ -0,0 +1,227 @@
|
||||
#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 ""
|
||||
Reference in New Issue
Block a user