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:
503
winrm-https/deployment-package/Setup-WinRM-HTTPS.ps1
Normal file
503
winrm-https/deployment-package/Setup-WinRM-HTTPS.ps1
Normal file
@@ -0,0 +1,503 @@
|
||||
#Requires -RunAsAdministrator
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sets up WinRM HTTPS configuration using a wildcard certificate.
|
||||
|
||||
.DESCRIPTION
|
||||
This script configures WinRM for HTTPS connections using a wildcard certificate
|
||||
(e.g., *.logon.ds.ge.com). It handles:
|
||||
1. Certificate installation from PFX file
|
||||
2. HTTPS listener creation with proper hostname
|
||||
3. Firewall rule configuration for port 5986
|
||||
4. WinRM service configuration
|
||||
|
||||
.PARAMETER CertificatePath
|
||||
Path to the PFX certificate file containing the wildcard certificate.
|
||||
|
||||
.PARAMETER CertificatePassword
|
||||
SecureString password for the PFX certificate file.
|
||||
|
||||
.PARAMETER Domain
|
||||
The domain suffix for FQDNs (e.g., "logon.ds.ge.com").
|
||||
Will construct FQDN as: hostname.domain
|
||||
|
||||
.PARAMETER CertificateThumbprint
|
||||
Use existing certificate by thumbprint instead of importing from PFX.
|
||||
|
||||
.PARAMETER Port
|
||||
HTTPS port for WinRM (default: 5986).
|
||||
|
||||
.PARAMETER SkipFirewall
|
||||
Skip firewall rule creation.
|
||||
|
||||
.PARAMETER TestConnection
|
||||
Test HTTPS connection after setup.
|
||||
|
||||
.EXAMPLE
|
||||
# Import certificate and setup WinRM HTTPS
|
||||
$certPass = ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force
|
||||
.\Setup-WinRM-HTTPS.ps1 -CertificatePath "C:\Certs\wildcard.pfx" `
|
||||
-CertificatePassword $certPass -Domain "logon.ds.ge.com"
|
||||
|
||||
.EXAMPLE
|
||||
# Use existing certificate by thumbprint
|
||||
.\Setup-WinRM-HTTPS.ps1 -CertificateThumbprint "AB123..." -Domain "logon.ds.ge.com"
|
||||
|
||||
.EXAMPLE
|
||||
# Prompt for certificate password
|
||||
.\Setup-WinRM-HTTPS.ps1 -CertificatePath "C:\Certs\wildcard.pfx" -Domain "logon.ds.ge.com"
|
||||
|
||||
.NOTES
|
||||
Author: System Administrator
|
||||
Date: 2025-10-17
|
||||
Version: 1.0
|
||||
|
||||
Prerequisites:
|
||||
1. Wildcard certificate PFX file with private key
|
||||
2. Administrator privileges
|
||||
3. Windows with PowerShell 5.1 or later
|
||||
|
||||
After running this script:
|
||||
- WinRM will listen on HTTPS (port 5986)
|
||||
- HTTP listener (port 5985) will remain active
|
||||
- Connections require -UseSSL flag in PowerShell remoting commands
|
||||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$CertificatePath,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[SecureString]$CertificatePassword,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$CertificateThumbprint,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Domain,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[int]$Port = 5986,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$SkipFirewall = $false,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]$TestConnection = $false,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$LogFile
|
||||
)
|
||||
|
||||
function Write-ColorOutput {
|
||||
param([string]$Message, [string]$Color = "White")
|
||||
Write-Host $Message -ForegroundColor $Color
|
||||
|
||||
# Also write to log file if specified
|
||||
if ($script:LogFile) {
|
||||
try {
|
||||
Add-Content -Path $script:LogFile -Value $Message -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
# Silently ignore logging errors to avoid breaking the script
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Show-WinRMStatus {
|
||||
Write-ColorOutput "`n=== Current WinRM Configuration ===" "Cyan"
|
||||
|
||||
try {
|
||||
$winrmStatus = Get-Service WinRM
|
||||
$statusColor = if($winrmStatus.Status -eq 'Running') {'Green'} else {'Red'}
|
||||
Write-ColorOutput "WinRM Service Status: $($winrmStatus.Status)" $statusColor
|
||||
|
||||
Write-ColorOutput "`nWinRM Listeners:" "Yellow"
|
||||
winrm enumerate winrm/config/listener
|
||||
|
||||
} catch {
|
||||
Write-ColorOutput "Error checking WinRM status: $($_.Exception.Message)" "Red"
|
||||
}
|
||||
}
|
||||
|
||||
function Import-WildcardCertificate {
|
||||
param(
|
||||
[string]$CertPath,
|
||||
[SecureString]$CertPassword
|
||||
)
|
||||
|
||||
Write-ColorOutput "`n=== Importing Certificate ===" "Cyan"
|
||||
|
||||
if (-not (Test-Path $CertPath)) {
|
||||
throw "Certificate file not found: $CertPath"
|
||||
}
|
||||
|
||||
try {
|
||||
# Prompt for password if not provided
|
||||
if (-not $CertPassword) {
|
||||
$CertPassword = Read-Host "Enter certificate password" -AsSecureString
|
||||
}
|
||||
|
||||
# Import certificate to Local Computer Personal store
|
||||
Write-ColorOutput "Importing certificate from: $CertPath" "Yellow"
|
||||
$cert = Import-PfxCertificate -FilePath $CertPath `
|
||||
-CertStoreLocation Cert:\LocalMachine\My `
|
||||
-Password $CertPassword `
|
||||
-Exportable
|
||||
|
||||
Write-ColorOutput "[OK] Certificate imported successfully" "Green"
|
||||
Write-ColorOutput " Subject: $($cert.Subject)" "Gray"
|
||||
Write-ColorOutput " Thumbprint: $($cert.Thumbprint)" "Gray"
|
||||
Write-ColorOutput " Expiration: $($cert.NotAfter)" "Gray"
|
||||
|
||||
return $cert
|
||||
}
|
||||
catch {
|
||||
throw "Failed to import certificate: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ExistingCertificate {
|
||||
param([string]$Thumbprint)
|
||||
|
||||
Write-ColorOutput "`n=== Locating Existing Certificate ===" "Cyan"
|
||||
|
||||
try {
|
||||
$cert = Get-ChildItem -Path Cert:\LocalMachine\My |
|
||||
Where-Object { $_.Thumbprint -eq $Thumbprint }
|
||||
|
||||
if (-not $cert) {
|
||||
throw "Certificate with thumbprint $Thumbprint not found in Local Machine store"
|
||||
}
|
||||
|
||||
Write-ColorOutput "[OK] Certificate found" "Green"
|
||||
Write-ColorOutput " Subject: $($cert.Subject)" "Gray"
|
||||
Write-ColorOutput " Thumbprint: $($cert.Thumbprint)" "Gray"
|
||||
Write-ColorOutput " Expiration: $($cert.NotAfter)" "Gray"
|
||||
|
||||
# Check if certificate has private key
|
||||
if (-not $cert.HasPrivateKey) {
|
||||
throw "Certificate does not have a private key. WinRM HTTPS requires a certificate with private key."
|
||||
}
|
||||
|
||||
return $cert
|
||||
}
|
||||
catch {
|
||||
throw "Failed to locate certificate: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
function Find-WildcardCertificate {
|
||||
param([string]$Domain)
|
||||
|
||||
Write-ColorOutput "`n=== Searching for Wildcard Certificate ===" "Cyan"
|
||||
Write-ColorOutput "Looking for certificate matching: *.$Domain" "Yellow"
|
||||
|
||||
try {
|
||||
$certs = Get-ChildItem -Path Cert:\LocalMachine\My |
|
||||
Where-Object {
|
||||
$_.Subject -like "*$Domain*" -and
|
||||
$_.HasPrivateKey -and
|
||||
$_.NotAfter -gt (Get-Date)
|
||||
}
|
||||
|
||||
if ($certs.Count -eq 0) {
|
||||
throw "No valid wildcard certificate found for *.$Domain in Local Machine store"
|
||||
}
|
||||
|
||||
if ($certs.Count -gt 1) {
|
||||
Write-ColorOutput "Multiple certificates found:" "Yellow"
|
||||
for ($i = 0; $i -lt $certs.Count; $i++) {
|
||||
Write-ColorOutput " [$i] Subject: $($certs[$i].Subject) | Expires: $($certs[$i].NotAfter)" "White"
|
||||
}
|
||||
$selection = Read-Host "Select certificate number (0-$($certs.Count - 1))"
|
||||
$cert = $certs[$selection]
|
||||
} else {
|
||||
$cert = $certs[0]
|
||||
}
|
||||
|
||||
Write-ColorOutput "[OK] Certificate selected" "Green"
|
||||
Write-ColorOutput " Subject: $($cert.Subject)" "Gray"
|
||||
Write-ColorOutput " Thumbprint: $($cert.Thumbprint)" "Gray"
|
||||
Write-ColorOutput " Expiration: $($cert.NotAfter)" "Gray"
|
||||
|
||||
return $cert
|
||||
}
|
||||
catch {
|
||||
throw "Failed to find wildcard certificate: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
function Remove-ExistingHTTPSListener {
|
||||
Write-ColorOutput "`n=== Checking for Existing HTTPS Listeners ===" "Cyan"
|
||||
|
||||
try {
|
||||
$listeners = winrm enumerate winrm/config/listener | Select-String "Transport = HTTPS" -Context 0,10
|
||||
|
||||
if ($listeners) {
|
||||
Write-ColorOutput "Found existing HTTPS listener(s). Removing..." "Yellow"
|
||||
|
||||
# Remove all HTTPS listeners
|
||||
$result = winrm delete winrm/config/Listener?Address=*+Transport=HTTPS 2>&1
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-ColorOutput "[OK] Existing HTTPS listener removed" "Green"
|
||||
}
|
||||
} else {
|
||||
Write-ColorOutput "[OK] No existing HTTPS listener found" "Green"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-ColorOutput "[WARN] Could not check/remove existing listeners: $($_.Exception.Message)" "Yellow"
|
||||
}
|
||||
}
|
||||
|
||||
function New-WinRMHTTPSListener {
|
||||
param(
|
||||
[System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate,
|
||||
[string]$Hostname,
|
||||
[int]$Port
|
||||
)
|
||||
|
||||
Write-ColorOutput "`n=== Creating WinRM HTTPS Listener ===" "Cyan"
|
||||
Write-ColorOutput "Computer FQDN: $Hostname" "Gray"
|
||||
Write-ColorOutput "Port: $Port" "Gray"
|
||||
|
||||
try {
|
||||
# Remove existing HTTPS listener if present
|
||||
Remove-ExistingHTTPSListener
|
||||
|
||||
# Create new HTTPS listener
|
||||
$thumbprint = $Certificate.Thumbprint
|
||||
|
||||
# Extract the wildcard CN from the certificate subject
|
||||
# For wildcard cert like CN=*.logon.ds.ge.com, we need to use the wildcard format
|
||||
$certSubject = $Certificate.Subject
|
||||
Write-ColorOutput "Certificate Subject: $certSubject" "Gray"
|
||||
|
||||
# Extract the CN value (e.g., "*.logon.ds.ge.com")
|
||||
if ($certSubject -match 'CN=([^,]+)') {
|
||||
$certCN = $matches[1]
|
||||
Write-ColorOutput "Certificate CN: $certCN" "Gray"
|
||||
} else {
|
||||
throw "Could not extract CN from certificate subject"
|
||||
}
|
||||
|
||||
# For wildcard certificates, WinRM listener hostname must match the certificate CN exactly
|
||||
# So we use the wildcard CN (*.logon.ds.ge.com) not the specific FQDN
|
||||
$listenerHostname = $certCN
|
||||
|
||||
Write-ColorOutput "Creating HTTPS listener..." "Yellow"
|
||||
Write-ColorOutput "Certificate Thumbprint: $thumbprint" "Gray"
|
||||
Write-ColorOutput "Listener Hostname: $listenerHostname" "Gray"
|
||||
|
||||
# Use cmd.exe to execute winrm command to avoid PowerShell quoting issues
|
||||
$winrmArgs = "create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=`"$listenerHostname`";CertificateThumbprint=`"$thumbprint`";Port=`"$Port`"}"
|
||||
|
||||
Write-ColorOutput "Executing: winrm $winrmArgs" "Gray"
|
||||
|
||||
$result = cmd.exe /c "winrm $winrmArgs" 2>&1
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-ColorOutput "Error output: $result" "Red"
|
||||
throw "Failed to create HTTPS listener. Error code: $LASTEXITCODE"
|
||||
}
|
||||
|
||||
Write-ColorOutput "[OK] HTTPS listener created successfully" "Green"
|
||||
Write-ColorOutput "Note: Clients will connect using the specific FQDN ($Hostname)" "Gray"
|
||||
Write-ColorOutput " but the listener uses the wildcard CN ($listenerHostname)" "Gray"
|
||||
|
||||
# Verify listener was created
|
||||
Write-ColorOutput "`nVerifying HTTPS listener:" "Yellow"
|
||||
winrm enumerate winrm/config/listener | Select-String "Transport = HTTPS" -Context 0,15
|
||||
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
throw "Failed to create HTTPS listener: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
function Enable-WinRMService {
|
||||
Write-ColorOutput "`n=== Configuring WinRM Service ===" "Cyan"
|
||||
|
||||
try {
|
||||
# Enable PowerShell Remoting
|
||||
Write-ColorOutput "Enabling PowerShell Remoting..." "Yellow"
|
||||
Enable-PSRemoting -Force -SkipNetworkProfileCheck
|
||||
Write-ColorOutput "[OK] PowerShell Remoting enabled" "Green"
|
||||
|
||||
# Start WinRM service
|
||||
Write-ColorOutput "Configuring WinRM service..." "Yellow"
|
||||
Start-Service WinRM -ErrorAction SilentlyContinue
|
||||
Set-Service WinRM -StartupType Automatic
|
||||
Write-ColorOutput "[OK] WinRM service configured" "Green"
|
||||
|
||||
# Configure service settings
|
||||
Set-Item WSMan:\localhost\Service\Auth\Certificate -Value $true
|
||||
Write-ColorOutput "[OK] Certificate authentication enabled" "Green"
|
||||
|
||||
} catch {
|
||||
throw "Failed to configure WinRM service: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
function New-FirewallRule {
|
||||
param([int]$Port)
|
||||
|
||||
if ($SkipFirewall) {
|
||||
Write-ColorOutput "`n[SKIP] Firewall configuration skipped" "Yellow"
|
||||
return
|
||||
}
|
||||
|
||||
Write-ColorOutput "`n=== Configuring Windows Firewall ===" "Cyan"
|
||||
|
||||
try {
|
||||
$ruleName = "WinRM HTTPS-In"
|
||||
|
||||
# Check if rule already exists
|
||||
$existingRule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
|
||||
|
||||
if ($existingRule) {
|
||||
Write-ColorOutput "Removing existing firewall rule..." "Yellow"
|
||||
Remove-NetFirewallRule -DisplayName $ruleName
|
||||
}
|
||||
|
||||
Write-ColorOutput "Creating firewall rule for port $Port..." "Yellow"
|
||||
New-NetFirewallRule -DisplayName $ruleName `
|
||||
-Name $ruleName `
|
||||
-Profile Any `
|
||||
-LocalPort $Port `
|
||||
-Protocol TCP `
|
||||
-Direction Inbound `
|
||||
-Action Allow `
|
||||
-Enabled True | Out-Null
|
||||
|
||||
Write-ColorOutput "[OK] Firewall rule created" "Green"
|
||||
|
||||
} catch {
|
||||
Write-ColorOutput "[WARN] Could not configure firewall: $($_.Exception.Message)" "Yellow"
|
||||
}
|
||||
}
|
||||
|
||||
function Test-WinRMHTTPSConnection {
|
||||
param([string]$Hostname, [int]$Port)
|
||||
|
||||
Write-ColorOutput "`n=== Testing HTTPS Connection ===" "Cyan"
|
||||
|
||||
try {
|
||||
Write-ColorOutput "Testing connection to https://${Hostname}:${Port}/wsman..." "Yellow"
|
||||
|
||||
$testResult = Test-WSMan -ComputerName $Hostname -Port $Port -UseSSL -ErrorAction Stop
|
||||
|
||||
Write-ColorOutput "[OK] HTTPS connection successful!" "Green"
|
||||
Write-ColorOutput "`nTest-WSMan Output:" "Gray"
|
||||
$testResult | Format-List
|
||||
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
Write-ColorOutput "[WARN] HTTPS connection test failed: $($_.Exception.Message)" "Yellow"
|
||||
Write-ColorOutput "This may be normal if testing from the local machine." "Gray"
|
||||
Write-ColorOutput "Try testing from a remote computer using:" "Gray"
|
||||
Write-ColorOutput " Test-WSMan -ComputerName $Hostname -Port $Port -UseSSL" "White"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Show-NextSteps {
|
||||
param([string]$Hostname, [int]$Port)
|
||||
|
||||
Write-ColorOutput "`n=== Next Steps ===" "Cyan"
|
||||
Write-ColorOutput ""
|
||||
Write-ColorOutput "WinRM HTTPS is now configured on this computer." "Green"
|
||||
Write-ColorOutput ""
|
||||
Write-ColorOutput "To connect from a remote computer:" "Yellow"
|
||||
Write-ColorOutput ""
|
||||
Write-ColorOutput " # Test connection" "Gray"
|
||||
Write-ColorOutput " Test-WSMan -ComputerName $Hostname -Port $Port -UseSSL" "White"
|
||||
Write-ColorOutput ""
|
||||
Write-ColorOutput " # Create remote session" "Gray"
|
||||
Write-ColorOutput " `$cred = Get-Credential" "White"
|
||||
Write-ColorOutput " New-PSSession -ComputerName $Hostname -Credential `$cred -UseSSL -Port $Port" "White"
|
||||
Write-ColorOutput ""
|
||||
Write-ColorOutput " # Or use Enter-PSSession" "Gray"
|
||||
Write-ColorOutput " Enter-PSSession -ComputerName $Hostname -Credential `$cred -UseSSL -Port $Port" "White"
|
||||
Write-ColorOutput ""
|
||||
Write-ColorOutput "Notes:" "Yellow"
|
||||
Write-ColorOutput " - HTTP listener on port 5985 is still active" "Gray"
|
||||
Write-ColorOutput " - Always use -UseSSL flag for HTTPS connections" "Gray"
|
||||
Write-ColorOutput " - Certificate must be trusted on the client computer" "Gray"
|
||||
Write-ColorOutput ""
|
||||
}
|
||||
|
||||
# Main execution
|
||||
try {
|
||||
# Make LogFile available to all functions
|
||||
$script:LogFile = $LogFile
|
||||
|
||||
Write-ColorOutput "=== WinRM HTTPS Setup Script ===" "Cyan"
|
||||
Write-ColorOutput "Date: $(Get-Date)" "Gray"
|
||||
if ($LogFile) {
|
||||
Write-ColorOutput "Logging to: $LogFile" "Gray"
|
||||
}
|
||||
Write-ColorOutput ""
|
||||
|
||||
# Construct FQDN
|
||||
$hostname = $env:COMPUTERNAME
|
||||
$fqdn = "$hostname.$Domain".ToLower()
|
||||
Write-ColorOutput "Computer FQDN: $fqdn" "Gray"
|
||||
|
||||
# Show current status
|
||||
Show-WinRMStatus
|
||||
|
||||
# Get or import certificate
|
||||
$certificate = $null
|
||||
|
||||
if ($CertificateThumbprint) {
|
||||
# Use existing certificate by thumbprint
|
||||
$certificate = Get-ExistingCertificate -Thumbprint $CertificateThumbprint
|
||||
}
|
||||
elseif ($CertificatePath) {
|
||||
# Import certificate from PFX
|
||||
$certificate = Import-WildcardCertificate -CertPath $CertificatePath -CertPassword $CertificatePassword
|
||||
}
|
||||
else {
|
||||
# Try to find existing wildcard certificate
|
||||
$certificate = Find-WildcardCertificate -Domain $Domain
|
||||
}
|
||||
|
||||
if (-not $certificate) {
|
||||
throw "No certificate available. Provide -CertificatePath or -CertificateThumbprint"
|
||||
}
|
||||
|
||||
# Verify certificate validity
|
||||
if ($certificate.NotAfter -lt (Get-Date)) {
|
||||
throw "Certificate has expired: $($certificate.NotAfter)"
|
||||
}
|
||||
|
||||
# Enable WinRM service
|
||||
Enable-WinRMService
|
||||
|
||||
# Create HTTPS listener
|
||||
New-WinRMHTTPSListener -Certificate $certificate -Hostname $fqdn -Port $Port
|
||||
|
||||
# Configure firewall
|
||||
New-FirewallRule -Port $Port
|
||||
|
||||
# Show updated status
|
||||
Show-WinRMStatus
|
||||
|
||||
# Test connection if requested
|
||||
if ($TestConnection) {
|
||||
Test-WinRMHTTPSConnection -Hostname $fqdn -Port $Port
|
||||
}
|
||||
|
||||
# Show next steps
|
||||
Show-NextSteps -Hostname $fqdn -Port $Port
|
||||
|
||||
Write-ColorOutput "`n[SUCCESS] WinRM HTTPS setup completed successfully!" "Green"
|
||||
|
||||
} catch {
|
||||
Write-ColorOutput "`n[ERROR] Setup failed: $($_.Exception.Message)" "Red"
|
||||
exit 1
|
||||
}
|
||||
Reference in New Issue
Block a user