#Requires -RunAsAdministrator <# .SYNOPSIS Deploys PC-specific certificate from network share and configures WinRM HTTPS .DESCRIPTION This script: 1. Finds the certificate for this PC on the network share 2. Imports it to the local certificate store 3. Configures WinRM HTTPS listener with the certificate 4. Creates firewall rule 5. Logs everything .PARAMETER NetworkSharePath Path to network share containing PC certificates Default: S:\dt\adata\script\deploy\pc-certificates .PARAMETER CertificatePassword Password for the certificate (if not provided, will prompt) .PARAMETER Domain Domain suffix for FQDN (default: logon.ds.ge.com) .PARAMETER LogFile Path to log file (optional) .PARAMETER AllowedSubnets Comma-separated list of allowed remote subnets in CIDR notation Default: "10.48.130.0/23" (management subnet) Use "Any" to allow all subnets .EXAMPLE .\Deploy-PCCertificate.ps1 .EXAMPLE $certPass = ConvertTo-SecureString "PCCert2025!" -AsPlainText -Force .\Deploy-PCCertificate.ps1 -CertificatePassword $certPass .EXAMPLE .\Deploy-PCCertificate.ps1 -AllowedSubnets "10.48.130.0/23,10.134.48.0/24" .NOTES Author: System Administrator Date: 2025-10-17 Run this script ON THE TARGET PC as Administrator #> param( [string]$NetworkSharePath = "S:\dt\adata\script\deploy\pc-certificates", [SecureString]$CertificatePassword, [string]$Domain = "logon.ds.ge.com", [string]$LogFile, [string]$AllowedSubnets = "10.48.130.0/23" ) function Write-Log { param([string]$Message, [string]$Color = "White") $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logMessage = "[$timestamp] $Message" Write-Host $Message -ForegroundColor $Color if ($LogFile) { Add-Content -Path $LogFile -Value $logMessage -ErrorAction SilentlyContinue } } Write-Host "" Write-Host "========================================" -ForegroundColor Cyan Write-Host " PC Certificate Deployment" -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "" # Get hostname $hostname = $env:COMPUTERNAME $fqdn = "$hostname.$Domain".ToLower() Write-Log "Computer: $hostname" Write-Log "FQDN: $fqdn" Write-Log "" # Check network share access Write-Log "Checking network share access..." -Color Yellow if (-not (Test-Path $NetworkSharePath)) { Write-Log "[ERROR] Cannot access network share: $NetworkSharePath" -Color Red Write-Log "Make sure the network share is accessible" -Color Yellow exit 1 } Write-Log "[OK] Network share accessible" -Color Green Write-Log "" # Find certificate for this PC Write-Log "Looking for certificate for $hostname..." -Color Yellow $certFiles = Get-ChildItem -Path "$NetworkSharePath\batch-*\$hostname-*.pfx" -ErrorAction SilentlyContinue if (-not $certFiles) { # Try alternative search $certFiles = Get-ChildItem -Path $NetworkSharePath -Recurse -Filter "$hostname-*.pfx" -ErrorAction SilentlyContinue } if (-not $certFiles -or $certFiles.Count -eq 0) { Write-Log "[ERROR] Certificate not found for $hostname" -Color Red Write-Log "Searched in: $NetworkSharePath" -Color Yellow Write-Log "Expected filename pattern: $hostname-*.pfx" -Color Yellow exit 1 } if ($certFiles.Count -gt 1) { Write-Log "Multiple certificates found:" -Color Yellow $certFiles | ForEach-Object { Write-Log " - $($_.FullName)" } Write-Log "Using newest: $($certFiles[0].Name)" -Color Yellow $certFile = $certFiles | Sort-Object LastWriteTime -Descending | Select-Object -First 1 } else { $certFile = $certFiles[0] } Write-Log "[OK] Found certificate: $($certFile.Name)" -Color Green Write-Log " Path: $($certFile.FullName)" -Color Gray Write-Log "" # Get password if not provided if (-not $CertificatePassword) { Write-Log "Enter certificate password:" -Color Yellow $CertificatePassword = Read-Host "Password" -AsSecureString Write-Log "" } # Import certificate Write-Log "Importing certificate to Local Machine store..." -Color Yellow try { $cert = Import-PfxCertificate ` -FilePath $certFile.FullName ` -CertStoreLocation Cert:\LocalMachine\My ` -Password $CertificatePassword ` -Exportable Write-Log "[OK] Certificate imported successfully" -Color Green Write-Log " Subject: $($cert.Subject)" -Color Gray Write-Log " Thumbprint: $($cert.Thumbprint)" -Color Gray Write-Log " Issuer: $($cert.Issuer)" -Color Gray Write-Log " Valid Until: $($cert.NotAfter)" -Color Gray Write-Log "" } catch { Write-Log "[ERROR] Failed to import certificate: $($_.Exception.Message)" -Color Red exit 1 } # Set Network Profile to Private Write-Log "Checking network profile..." -Color Yellow try { $profiles = Get-NetConnectionProfile $publicProfiles = $profiles | Where-Object { $_.NetworkCategory -eq 'Public' } if ($publicProfiles) { Write-Log " Found Public network profile(s), changing to Private..." -Color Gray foreach ($profile in $publicProfiles) { Set-NetConnectionProfile -InterfaceIndex $profile.InterfaceIndex -NetworkCategory Private -ErrorAction SilentlyContinue } Write-Log "[OK] Network profile set to Private" -Color Green } else { Write-Log "[OK] Network profile is already Private/Domain" -Color Green } Write-Log "" } catch { Write-Log "[WARN] Could not change network profile: $($_.Exception.Message)" -Color Yellow Write-Log "" } # Configure WinRM Service Write-Log "Configuring WinRM service..." -Color Yellow try { # Enable PowerShell Remoting Enable-PSRemoting -Force -SkipNetworkProfileCheck | Out-Null # Start WinRM service Start-Service WinRM -ErrorAction SilentlyContinue Set-Service WinRM -StartupType Automatic # Enable certificate authentication Set-Item WSMan:\localhost\Service\Auth\Certificate -Value $true Write-Log "[OK] WinRM service configured" -Color Green Write-Log "" } catch { Write-Log "[ERROR] Failed to configure WinRM: $($_.Exception.Message)" -Color Red } # Remove existing HTTPS listeners Write-Log "Checking for existing HTTPS listeners..." -Color Yellow try { $existingListeners = winrm enumerate winrm/config/listener | Select-String "Transport = HTTPS" if ($existingListeners) { Write-Log "Removing existing HTTPS listener..." -Color Yellow winrm delete winrm/config/Listener?Address=*+Transport=HTTPS 2>&1 | Out-Null Write-Log "[OK] Existing HTTPS listener removed" -Color Green } else { Write-Log "[OK] No existing HTTPS listener found" -Color Green } Write-Log "" } catch { Write-Log "[WARN] Could not check/remove existing listeners" -Color Yellow } # Create HTTPS listener Write-Log "Creating WinRM HTTPS listener..." -Color Yellow Write-Log " Hostname: $fqdn" -Color Gray Write-Log " Port: 5986" -Color Gray Write-Log " Certificate: $($cert.Thumbprint)" -Color Gray try { $winrmArgs = "create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname=`"$fqdn`";CertificateThumbprint=`"$($cert.Thumbprint)`";Port=`"5986`"}" $result = cmd.exe /c "winrm $winrmArgs" 2>&1 if ($LASTEXITCODE -ne 0) { Write-Log "[ERROR] Failed to create HTTPS listener" -Color Red Write-Log "Error: $result" -Color Red exit 1 } Write-Log "[OK] HTTPS listener created successfully" -Color Green Write-Log "" } catch { Write-Log "[ERROR] Failed to create HTTPS listener: $($_.Exception.Message)" -Color Red exit 1 } # Configure firewall Write-Log "Configuring Windows Firewall..." -Color Yellow try { $ruleName = "WinRM HTTPS-In" # Remove existing rule if present $existingRule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue if ($existingRule) { Remove-NetFirewallRule -DisplayName $ruleName } # Determine remote address if ($AllowedSubnets -eq "Any") { $remoteAddr = "Any" Write-Log " Remote Access: Any (all subnets)" -Color Gray } else { # Split comma-separated subnets $remoteAddr = $AllowedSubnets -split "," | ForEach-Object { $_.Trim() } Write-Log " Remote Access: $AllowedSubnets" -Color Gray } # Create new rule New-NetFirewallRule -DisplayName $ruleName ` -Name $ruleName ` -Profile Any ` -LocalPort 5986 ` -Protocol TCP ` -Direction Inbound ` -Action Allow ` -RemoteAddress $remoteAddr ` -Enabled True | Out-Null Write-Log "[OK] Firewall rule created" -Color Green Write-Log "" } catch { Write-Log "[WARN] Could not configure firewall: $($_.Exception.Message)" -Color Yellow } # Verify configuration Write-Log "Verifying configuration..." -Color Yellow Write-Log "" # Check service $winrmService = Get-Service WinRM Write-Log "WinRM Service: $($winrmService.Status) [$($winrmService.StartType)]" -Color $(if($winrmService.Status -eq 'Running'){'Green'}else{'Red'}) # Check listener Write-Log "" Write-Log "WinRM Listeners:" -Color Cyan winrm enumerate winrm/config/listener | Out-String | ForEach-Object { Write-Log $_ -Color Gray } # Check port Write-Log "" Write-Log "Port 5986 Status:" -Color Cyan $portCheck = netstat -an | Select-String ":5986" if ($portCheck) { Write-Log "[OK] Port 5986 is listening" -Color Green $portCheck | ForEach-Object { Write-Log " $_" -Color Gray } } else { Write-Log "[WARNING] Port 5986 is not listening" -Color Yellow } # Summary Write-Log "" Write-Log "========================================" -ForegroundColor Green Write-Log " DEPLOYMENT COMPLETE" -ForegroundColor Green Write-Log "========================================" -ForegroundColor Green Write-Log "" Write-Log "Certificate: $($cert.Subject)" -Color White Write-Log "Thumbprint: $($cert.Thumbprint)" -Color White Write-Log "Hostname: $fqdn" -Color White Write-Log "" Write-Log "Test connection from management computer:" -Color Yellow Write-Log " Test-WSMan -ComputerName $fqdn -UseSSL -Port 5986" -Color White Write-Log "" Write-Log " `$cred = Get-Credential" -Color White Write-Log " Enter-PSSession -ComputerName $fqdn -Credential `$cred -UseSSL -Port 5986" -Color White Write-Log "" if ($LogFile) { Write-Log "Log saved to: $LogFile" -Color Cyan }