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>
324 lines
10 KiB
PowerShell
324 lines
10 KiB
PowerShell
#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
|
|
}
|