#Requires -RunAsAdministrator <# .SYNOPSIS Generates a self-signed wildcard certificate for testing WinRM HTTPS. .DESCRIPTION Creates a self-signed wildcard certificate for *.logon.ds.ge.com that can be used for testing WinRM HTTPS configuration. The certificate includes: - Server Authentication EKU - Private key marked as exportable - 2-year validity period - Strong 2048-bit RSA key .PARAMETER Domain The domain for the wildcard certificate (default: logon.ds.ge.com). .PARAMETER ExportPath Path where the PFX file will be exported (default: current directory). .PARAMETER Password Password for the PFX file. If not provided, will prompt securely. .PARAMETER ValidityYears Certificate validity in years (default: 2). .EXAMPLE .\Generate-WildcardCert.ps1 .EXAMPLE $pass = ConvertTo-SecureString "MyPassword123!" -AsPlainText -Force .\Generate-WildcardCert.ps1 -Password $pass -ExportPath "C:\Certs" .NOTES Author: System Administrator Date: 2025-10-17 Version: 1.0 IMPORTANT: This creates a SELF-SIGNED certificate suitable for TESTING only. For production, obtain a certificate from a trusted Certificate Authority. #> param( [Parameter(Mandatory=$false)] [string]$Domain = "logon.ds.ge.com", [Parameter(Mandatory=$false)] [string]$ExportPath = ".", [Parameter(Mandatory=$false)] [SecureString]$Password, [Parameter(Mandatory=$false)] [int]$ValidityYears = 2 ) function Write-ColorOutput { param([string]$Message, [string]$Color = "White") Write-Host $Message -ForegroundColor $Color } function New-SelfSignedWildcardCertificate { param( [string]$Domain, [int]$ValidityYears ) Write-ColorOutput "`n=== Generating Self-Signed Wildcard Certificate ===" "Cyan" Write-ColorOutput "Domain: *.$Domain" "Gray" Write-ColorOutput "Validity: $ValidityYears years" "Gray" try { # Calculate validity period $notAfter = (Get-Date).AddYears($ValidityYears) # Certificate parameters $certParams = @{ DnsName = @("*.$Domain", $Domain) CertStoreLocation = "Cert:\LocalMachine\My" KeyExportPolicy = "Exportable" KeySpec = "KeyExchange" KeyLength = 2048 KeyAlgorithm = "RSA" HashAlgorithm = "SHA256" NotAfter = $notAfter Subject = "CN=*.$Domain" FriendlyName = "Wildcard Certificate for *.$Domain (Self-Signed)" KeyUsage = "DigitalSignature", "KeyEncipherment" TextExtension = @("2.5.29.37={text}1.3.6.1.5.5.7.3.1") # Server Authentication EKU } Write-ColorOutput "`nCreating certificate..." "Yellow" $cert = New-SelfSignedCertificate @certParams Write-ColorOutput "[OK] Certificate created successfully" "Green" Write-ColorOutput "`nCertificate Details:" "Cyan" Write-ColorOutput " Subject: $($cert.Subject)" "White" Write-ColorOutput " Thumbprint: $($cert.Thumbprint)" "White" Write-ColorOutput " Valid From: $($cert.NotBefore)" "White" Write-ColorOutput " Valid To: $($cert.NotAfter)" "White" Write-ColorOutput " Has Private Key: $($cert.HasPrivateKey)" "White" return $cert } catch { throw "Failed to create certificate: $($_.Exception.Message)" } } function Export-CertificateToPFX { param( [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate, [string]$ExportPath, [SecureString]$Password ) Write-ColorOutput "`n=== Exporting Certificate to PFX ===" "Cyan" try { # Ensure export directory exists if (-not (Test-Path $ExportPath)) { New-Item -ItemType Directory -Path $ExportPath -Force | Out-Null } # Construct filename $filename = "wildcard-$($Domain.Replace('.', '-'))-$(Get-Date -Format 'yyyyMMdd').pfx" $fullPath = Join-Path $ExportPath $filename Write-ColorOutput "Export path: $fullPath" "Gray" # Export certificate with private key Export-PfxCertificate -Cert $Certificate -FilePath $fullPath -Password $Password | Out-Null Write-ColorOutput "[OK] Certificate exported successfully" "Green" # Get file size $fileSize = (Get-Item $fullPath).Length Write-ColorOutput " File size: $([math]::Round($fileSize / 1KB, 2)) KB" "White" return $fullPath } catch { throw "Failed to export certificate: $($_.Exception.Message)" } } function Install-CertificateToTrustedRoot { param( [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate ) Write-ColorOutput "`n=== Installing to Trusted Root ===" "Cyan" Write-ColorOutput "This allows the self-signed cert to be trusted on this machine" "Gray" try { # Export to trusted root store $rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store( "Root", "LocalMachine" ) $rootStore.Open("ReadWrite") # Check if already exists $existing = $rootStore.Certificates | Where-Object { $_.Thumbprint -eq $Certificate.Thumbprint } if ($existing) { Write-ColorOutput "[OK] Certificate already in Trusted Root" "Yellow" } else { $rootStore.Add($Certificate) Write-ColorOutput "[OK] Certificate added to Trusted Root Certification Authorities" "Green" } $rootStore.Close() } catch { Write-ColorOutput "[WARN] Could not add to Trusted Root: $($_.Exception.Message)" "Yellow" Write-ColorOutput "You may need to manually trust this certificate on client machines" "Yellow" } } function Show-NextSteps { param([string]$PfxPath, [string]$Domain) Write-ColorOutput "`n=== Next Steps ===" "Cyan" Write-ColorOutput "" Write-ColorOutput "1. The wildcard certificate has been generated and exported to:" "Yellow" Write-ColorOutput " $PfxPath" "White" Write-ColorOutput "" Write-ColorOutput "2. To set up WinRM HTTPS on a computer, copy the PFX file and run:" "Yellow" Write-ColorOutput " `$certPass = ConvertTo-SecureString 'YourPassword' -AsPlainText -Force" "White" Write-ColorOutput " .\Setup-WinRM-HTTPS.ps1 -CertificatePath '$PfxPath' ``" "White" Write-ColorOutput " -CertificatePassword `$certPass -Domain '$Domain'" "White" Write-ColorOutput "" Write-ColorOutput "3. For client machines to trust this certificate:" "Yellow" Write-ColorOutput " Option A: Import to Trusted Root on each client" "White" Write-ColorOutput " Option B: Use -SkipCertificateCheck in collection script (less secure)" "White" Write-ColorOutput "" Write-ColorOutput "4. Test the setup:" "Yellow" Write-ColorOutput " .\Invoke-RemoteAssetCollection-HTTPS.ps1 ``" "White" Write-ColorOutput " -HostnameList @('hostname') -Domain '$Domain' -TestConnections" "White" Write-ColorOutput "" Write-ColorOutput "IMPORTANT: This is a SELF-SIGNED certificate for TESTING only!" "Red" Write-ColorOutput "For production, obtain a certificate from a trusted CA." "Red" Write-ColorOutput "" } # Main execution try { Write-ColorOutput "=== Wildcard Certificate Generator ===" "Cyan" Write-ColorOutput "Date: $(Get-Date)" "Gray" Write-ColorOutput "" # Get password if not provided if (-not $Password) { Write-ColorOutput "Enter password for PFX file:" "Yellow" $Password = Read-Host "Password" -AsSecureString $Password2 = Read-Host "Confirm password" -AsSecureString # Compare passwords $pwd1 = [Runtime.InteropServices.Marshal]::PtrToStringAuto( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password) ) $pwd2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password2) ) if ($pwd1 -ne $pwd2) { throw "Passwords do not match" } } # Generate certificate $cert = New-SelfSignedWildcardCertificate -Domain $Domain -ValidityYears $ValidityYears # Export to PFX $pfxPath = Export-CertificateToPFX -Certificate $cert -ExportPath $ExportPath -Password $Password # Install to trusted root (optional, for local testing) $installToRoot = Read-Host "`nInstall to Trusted Root Certification Authorities on this machine? (Y/N)" if ($installToRoot -eq 'Y' -or $installToRoot -eq 'y') { Install-CertificateToTrustedRoot -Certificate $cert } # Show next steps Show-NextSteps -PfxPath $pfxPath -Domain $Domain Write-ColorOutput "`n[SUCCESS] Wildcard certificate generation completed!" "Green" Write-ColorOutput "Certificate Thumbprint: $($cert.Thumbprint)" "Cyan" Write-ColorOutput "PFX File: $pfxPath" "Cyan" } catch { Write-ColorOutput "`n[ERROR] Certificate generation failed: $($_.Exception.Message)" "Red" exit 1 }