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>
381 lines
14 KiB
PowerShell
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 ""
|