Files
powershell-scripts/winrm-https/Sign-PCCertificate.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

381 lines
14 KiB
PowerShell

#Requires -RunAsAdministrator
<#
.SYNOPSIS
Signs an individual PC certificate using the Certificate Authority
.DESCRIPTION
Creates and signs a certificate for a specific PC using the CA certificate.
The certificate will have the proper hostname (e.g., g9kn7pz3esf.logon.ds.ge.com)
and will be automatically trusted on any computer that trusts the CA.
.PARAMETER Hostname
The hostname of the PC (without domain suffix)
Example: G9KN7PZ3ESF
.PARAMETER Domain
The domain suffix (default: logon.ds.ge.com)
.PARAMETER CAThumbprint
Thumbprint of the CA certificate used to sign this certificate
.PARAMETER CAPfxPath
Path to the CA PFX file (if CA is not in local store)
.PARAMETER CAPassword
Password for the CA PFX file
.PARAMETER OutputPath
Directory to save the signed certificate (default: current directory)
.PARAMETER ValidityYears
How many years the certificate should be valid (default: 2)
.PARAMETER ExportPassword
Password for exporting the signed certificate
.EXAMPLE
# Sign certificate using CA from local store
.\Sign-PCCertificate.ps1 -Hostname G9KN7PZ3ESF -CAThumbprint "ABC123..."
.EXAMPLE
# Sign certificate using CA from PFX file
$caPass = ConvertTo-SecureString "CAPassword" -AsPlainText -Force
$certPass = ConvertTo-SecureString "CertPassword" -AsPlainText -Force
.\Sign-PCCertificate.ps1 -Hostname G9KN7PZ3ESF -CAPfxPath "C:\CA\ca.pfx" `
-CAPassword $caPass -ExportPassword $certPass
.NOTES
Author: System Administrator
Date: 2025-10-17
#>
param(
[Parameter(Mandatory=$true)]
[string]$Hostname,
[Parameter(Mandatory=$false)]
[string]$Domain = "logon.ds.ge.com",
[Parameter(Mandatory=$false)]
[string]$CAThumbprint,
[Parameter(Mandatory=$false)]
[string]$CAPfxPath,
[Parameter(Mandatory=$false)]
[SecureString]$CAPassword,
[Parameter(Mandatory=$false)]
[string]$OutputPath = ".",
[Parameter(Mandatory=$false)]
[int]$ValidityYears = 2,
[Parameter(Mandatory=$false)]
[SecureString]$ExportPassword
)
Write-Host ""
Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║ Sign Individual PC Certificate with CA ║" -ForegroundColor Cyan
Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
Write-Host ""
# Clean hostname (remove domain if included)
$Hostname = $Hostname -replace "\.$Domain$", ""
$FQDN = "$Hostname.$Domain".ToLower()
Write-Host "Target PC:" -ForegroundColor Cyan
Write-Host " Hostname: $Hostname" -ForegroundColor White
Write-Host " FQDN: $FQDN" -ForegroundColor White
Write-Host ""
# Get CA certificate
$caCert = $null
if ($CAPfxPath) {
# Load CA from PFX file
Write-Host "Loading CA certificate from file..." -ForegroundColor Yellow
Write-Host " File: $CAPfxPath" -ForegroundColor Gray
if (-not (Test-Path $CAPfxPath)) {
Write-Host "✗ CA PFX file not found: $CAPfxPath" -ForegroundColor Red
exit 1
}
if (-not $CAPassword) {
$CAPassword = Read-Host "Enter CA certificate password" -AsSecureString
}
try {
$caCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CAPfxPath, $CAPassword, 'Exportable')
Write-Host "✓ CA certificate loaded" -ForegroundColor Green
} catch {
Write-Host "✗ Failed to load CA certificate: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
} elseif ($CAThumbprint) {
# Load CA from local store
Write-Host "Loading CA certificate from local store..." -ForegroundColor Yellow
Write-Host " Thumbprint: $CAThumbprint" -ForegroundColor Gray
try {
$caCert = Get-ChildItem Cert:\LocalMachine\My\$CAThumbprint -ErrorAction Stop
Write-Host "✓ CA certificate found" -ForegroundColor Green
} catch {
Write-Host "✗ CA certificate not found in local store" -ForegroundColor Red
Write-Host " Thumbprint: $CAThumbprint" -ForegroundColor Red
Write-Host " Try specifying -CAPfxPath instead" -ForegroundColor Yellow
exit 1
}
} else {
Write-Host "✗ Must specify either -CAThumbprint or -CAPfxPath" -ForegroundColor Red
exit 1
}
# Verify CA has private key
if (-not $caCert.HasPrivateKey) {
Write-Host "✗ CA certificate does not have private key" -ForegroundColor Red
Write-Host " Cannot sign certificates without CA private key" -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host "CA Certificate Details:" -ForegroundColor Cyan
Write-Host " Subject: $($caCert.Subject)" -ForegroundColor White
Write-Host " Thumbprint: $($caCert.Thumbprint)" -ForegroundColor White
Write-Host " Valid Until: $($caCert.NotAfter)" -ForegroundColor White
Write-Host ""
# Prompt for export password if not provided
if (-not $ExportPassword) {
Write-Host "Enter password to protect the PC certificate:" -ForegroundColor Yellow
$ExportPassword = Read-Host "Certificate Password" -AsSecureString
}
# Create output directory if needed
if (-not (Test-Path $OutputPath)) {
New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
}
# Generate the PC certificate
Write-Host "Generating certificate for $FQDN..." -ForegroundColor Yellow
try {
$notAfter = (Get-Date).AddYears($ValidityYears)
# Create certificate request (self-signed, will be replaced by CA-signed version)
$certParams = @{
Subject = "CN=$FQDN"
DnsName = @($FQDN, $Hostname)
KeyExportPolicy = 'Exportable'
KeyUsage = 'DigitalSignature', 'KeyEncipherment'
KeyUsageProperty = 'All'
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' # Enhanced Key Usage: Server Authentication
)
Signer = $caCert
}
Write-Host " Subject: CN=$FQDN" -ForegroundColor Gray
Write-Host " DNS Names: $FQDN, $Hostname" -ForegroundColor Gray
Write-Host " Valid for: $ValidityYears years" -ForegroundColor Gray
Write-Host ""
$pcCert = New-SelfSignedCertificate @certParams
Write-Host "✓ Certificate created and signed by CA" -ForegroundColor Green
Write-Host ""
Write-Host "Certificate Details:" -ForegroundColor Cyan
Write-Host " Subject: $($pcCert.Subject)" -ForegroundColor White
Write-Host " Thumbprint: $($pcCert.Thumbprint)" -ForegroundColor White
Write-Host " Issuer: $($pcCert.Issuer)" -ForegroundColor White
Write-Host " Valid From: $($pcCert.NotBefore)" -ForegroundColor White
Write-Host " Valid Until: $($pcCert.NotAfter)" -ForegroundColor White
Write-Host " DNS Names: $($pcCert.DnsNameList.Unicode -join ', ')" -ForegroundColor White
Write-Host ""
} catch {
Write-Host "✗ Failed to create certificate: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
# Export certificate with private key (PFX)
$timestamp = Get-Date -Format "yyyyMMdd"
$pfxPath = Join-Path $OutputPath "$Hostname-$Domain-$timestamp.pfx"
Write-Host "Exporting certificate with private key..." -ForegroundColor Yellow
Write-Host " File: $pfxPath" -ForegroundColor Gray
try {
Export-PfxCertificate -Cert $pcCert -FilePath $pfxPath -Password $ExportPassword | Out-Null
Write-Host "✓ Certificate exported" -ForegroundColor Green
Write-Host ""
} catch {
Write-Host "✗ Failed to export PFX: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
# Export certificate without private key (CER) for verification
$cerPath = Join-Path $OutputPath "$Hostname-$Domain-$timestamp.cer"
Write-Host "Exporting public certificate..." -ForegroundColor Yellow
Write-Host " File: $cerPath" -ForegroundColor Gray
try {
Export-Certificate -Cert $pcCert -FilePath $cerPath | Out-Null
Write-Host "✓ Public certificate exported" -ForegroundColor Green
Write-Host ""
} catch {
Write-Host "✗ Failed to export CER: $($_.Exception.Message)" -ForegroundColor Red
}
# Remove certificate from local store (cleanup)
Write-Host "Removing temporary certificate from local store..." -ForegroundColor Gray
try {
Remove-Item "Cert:\LocalMachine\My\$($pcCert.Thumbprint)" -Force
Write-Host "✓ Local store cleaned up" -ForegroundColor Green
} catch {
Write-Host "⚠ Could not remove temporary certificate (not critical)" -ForegroundColor Yellow
}
Write-Host ""
# Create certificate info file
$infoPath = Join-Path $OutputPath "$Hostname-$Domain-$timestamp-INFO.txt"
$infoContent = @"
================================================================================
PC CERTIFICATE INFORMATION
================================================================================
Created: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
PC Details:
-----------
Hostname: $Hostname
FQDN: $FQDN
Certificate: CN=$FQDN
DNS Names: $($pcCert.DnsNameList.Unicode -join ', ')
Certificate Details:
--------------------
Thumbprint: $($pcCert.Thumbprint)
Issuer: $($pcCert.Issuer)
Serial Number: $($pcCert.SerialNumber)
Valid From: $($pcCert.NotBefore)
Valid Until: $($pcCert.NotAfter)
Key Size: 2048-bit RSA
Hash Algorithm: SHA256
CA Details:
-----------
CA Subject: $($caCert.Subject)
CA Thumbprint: $($caCert.Thumbprint)
Files Created:
--------------
1. $pfxPath
- PC certificate WITH private key
- Protected with password
- Deploy this to $Hostname
2. $cerPath
- PC certificate WITHOUT private key (public only)
- For verification purposes only
================================================================================
DEPLOYMENT INSTRUCTIONS
================================================================================
1. Copy the PFX file to the PC:
Copy-Item "$pfxPath" \\$FQDN\C$\Temp\
2. On the PC ($Hostname), import the certificate:
`$certPass = ConvertTo-SecureString "YourPassword" -AsPlainText -Force
Import-PfxCertificate -FilePath "C:\Temp\$(Split-Path $pfxPath -Leaf)" ``
-CertStoreLocation Cert:\LocalMachine\My ``
-Password `$certPass
3. Configure WinRM HTTPS with the certificate:
.\Setup-WinRM-HTTPS.ps1 -CertificateThumbprint "$($pcCert.Thumbprint)" ``
-Domain "$Domain"
4. Or use the deployment package with this certificate:
- Replace wildcard certificate with this PC-specific certificate
- Run Deploy-WinRM-HTTPS.bat on $Hostname
================================================================================
VERIFICATION
================================================================================
On the PC ($Hostname):
# View certificate
Get-ChildItem Cert:\LocalMachine\My\$($pcCert.Thumbprint)
# Verify issuer
`$cert = Get-ChildItem Cert:\LocalMachine\My\$($pcCert.Thumbprint)
Write-Host "Issuer: `$(`$cert.Issuer)"
# Should show: $($caCert.Subject)
On Management Computer:
# Verify CA is trusted
Get-ChildItem Cert:\LocalMachine\Root | Where-Object {`$_.Thumbprint -eq "$($caCert.Thumbprint)"}
# Test connection
Test-WSMan -ComputerName $FQDN -UseSSL -Port 5986
# Should work without -SessionOption if CA is trusted
================================================================================
TROUBLESHOOTING
================================================================================
If certificate isn't trusted:
1. Install CA certificate on management computer:
Import-Certificate -FilePath "CA.cer" -CertStoreLocation Cert:\LocalMachine\Root
2. Verify certificate chain on PC:
Test-Certificate -Cert (Get-Item Cert:\LocalMachine\My\$($pcCert.Thumbprint))
3. Check WinRM listener:
winrm enumerate winrm/config/listener
# Should show Hostname = $FQDN (not wildcard)
================================================================================
"@
$infoContent | Out-File -FilePath $infoPath -Encoding UTF8
Write-Host "✓ Certificate info created: $infoPath" -ForegroundColor Green
Write-Host ""
# Final summary
Write-Host "╔══════════════════════════════════════════════════════════════╗" -ForegroundColor Green
Write-Host "║ PC CERTIFICATE CREATED SUCCESSFULLY ║" -ForegroundColor Green
Write-Host "╚══════════════════════════════════════════════════════════════╝" -ForegroundColor Green
Write-Host ""
Write-Host "Files Created:" -ForegroundColor Cyan
Write-Host " 1. $pfxPath" -ForegroundColor White
Write-Host " (Deploy to $Hostname)" -ForegroundColor Gray
Write-Host ""
Write-Host " 2. $cerPath" -ForegroundColor White
Write-Host " (Public certificate for verification)" -ForegroundColor Gray
Write-Host ""
Write-Host " 3. $infoPath" -ForegroundColor White
Write-Host " (Deployment instructions)" -ForegroundColor Gray
Write-Host ""
Write-Host "Certificate Thumbprint: $($pcCert.Thumbprint)" -ForegroundColor Yellow
Write-Host ""
Write-Host "Next Steps:" -ForegroundColor Cyan
Write-Host " 1. Deploy PFX file to $Hostname" -ForegroundColor White
Write-Host " 2. Import certificate on $Hostname" -ForegroundColor White
Write-Host " 3. Configure WinRM HTTPS with this certificate" -ForegroundColor White
Write-Host " 4. Ensure CA certificate is installed on management computers" -ForegroundColor White
Write-Host ""