#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 ""