From e400fc796d95dca5fcb19030d38b5ca0996a994d Mon Sep 17 00:00:00 2001 From: David Schroeder Date: Tue, 26 Aug 2025 19:46:52 -0500 Subject: [PATCH] Update vCenter-SSL.ps1 --- inc/vCenter-SSL.ps1 | 145 +++++++++++++++++++++++++++++++++----------- 1 file changed, 109 insertions(+), 36 deletions(-) diff --git a/inc/vCenter-SSL.ps1 b/inc/vCenter-SSL.ps1 index 52174b8e..2f025c04 100644 --- a/inc/vCenter-SSL.ps1 +++ b/inc/vCenter-SSL.ps1 @@ -1,17 +1,18 @@ #!/usr/bin/env pwsh . /opt/idssys/nodemgmt/conf/powerwall/settings.ps1 +# ---------------------------- +# Error handler +# ---------------------------- function Show-Failure { param($ErrorRecord) try { $response = $ErrorRecord.Exception.Response if ($response -is [System.Net.Http.HttpResponseMessage]) { - # PowerShell 7 (.NET HttpClient) $global:responseBody = $response.Content.ReadAsStringAsync().Result } elseif ($response -is [System.Net.WebResponse]) { - # Legacy (.NET Framework) $stream = $response.GetResponseStream() $reader = New-Object System.IO.StreamReader($stream) $global:responseBody = $reader.ReadToEnd() @@ -30,6 +31,45 @@ function Show-Failure { break } +# ---------------------------- +# Unified REST wrapper (TLS 1.2 + skip cert check) +# ---------------------------- +function Invoke-SafeRestMethod { + param( + [string]$Uri, + [string]$Method = 'Get', + [hashtable]$Headers, + $Body, + [switch]$AsJson + ) + + try { + $params = @{ + Uri = $Uri + Method = $Method + Headers = $Headers + SslProtocol = 'Tls12' + SkipCertificateCheck = $true + ErrorAction = 'Stop' + } + + if ($Body) { + if ($AsJson) { + $params.Body = ($Body | ConvertTo-Json -Depth 10 -Compress) + $params.ContentType = 'application/json' + } else { + $params.Body = $Body + } + } + + return Invoke-RestMethod @params + } + catch { + Show-Failure -ErrorRecord $_ + exit 1 + } +} + # ---------------------------- # Variables # ---------------------------- @@ -72,23 +112,69 @@ While ($PoshACME -eq $null) # ---------------------------- # vCenter API Session # ---------------------------- +$loginUri = "https://$vCenterURL/rest/com/vmware/cis/session" +$session = Invoke-SafeRestMethod -Uri $loginUri -Method Post -Headers @{ } -Body @{ } -AsJson +$sessionToken = $session.value + +if (-not $sessionToken) { + Write-Error "Unable to get Session Token, Terminating Script" + exit 1 +} +Write-Host "Connected to vCenter API. Session established." -ForegroundColor Green + +# ---------------------------- +# Example: Retrieve VMs +# ---------------------------- +$headers = @{ 'vmware-api-session-id' = $sessionToken } +$vmList = Invoke-SafeRestMethod -Uri "https://$vCenterURL/rest/vcenter/vm" -Headers $headers +Write-Host "Retrieved VM list from vCenter:" -ForegroundColor Cyan +$vmList.value | ForEach-Object { Write-Host " - $($_.name)" } + +# ---------------------------- +# PowerDNS Integration (via Posh-ACME plugin args) +# ---------------------------- +Write-Host "Configuring PowerDNS with Posh-ACME" -ForegroundColor Green +$pArgs = @{ + PowerDNSApiHost = $WDNSHOST + PowerDNSApiKey = $PDNSAPI + PowerDNSUseTLS = $true + PowerDNSPort = 443 + PowerDNSServerName = 'localhost' +} + +# Example ACME order with DNS plugin +$certName = "vcenter-cert" +New-PACertificate $CommonName -DnsPlugin PowerDNS -PluginArgs $pArgs -Contact $EmailContact -AcceptTOS -Verbose + +# ---------------------------- +# Push certificate back to vCenter (example) +# ---------------------------- +$certPath = (Join-Path -Path (Get-PAAccount).CertFolder -ChildPath "$certName\cert.pem") +$keyPath = (Join-Path -Path (Get-PAAccount).CertFolder -ChildPath "$certName\privkey.pem") +$chainPath = (Join-Path -Path (Get-PAAccount).CertFolder -ChildPath "$certName\chain.pem") + +# Upload cert (example REST call to vCenter CertMgmt API) +$uploadUri = "https://$vCenterURL/rest/vcenter/certificate-management/vcenter/tls" +$headers = @{ 'vmware-api-session-id' = $sessionToken } + +$body = @{ + cert = Get-Content -Path $certPath -Raw + key = Get-Content -Path $keyPath -Raw + chain = Get-Content -Path $chainPath -Raw +} + +Invoke-SafeRestMethod -Uri $uploadUri -Method Post -Headers $headers -Body $body -AsJson +Write-Host "New TLS certificate uploaded to vCenter" -ForegroundColor Green + +# ---------------------------- +# Apply certificate to vCenter +# ---------------------------- try { - $loginParams = @{ - Uri = "https://$vCenterURL/rest/com/vmware/cis/session" - Method = 'Post' - Credential = $Credential - SslProtocol = 'Tls12' - SkipCertificateCheck = $true - ErrorAction = 'Stop' - } - $session = Invoke-RestMethod @loginParams - $sessionToken = $session.value + $applyUri = "https://$vCenterURL/rest/vcenter/certificate-management/vcenter/tls?action=apply" + $headers = @{ 'vmware-api-session-id' = $sessionToken } - if (-not $sessionToken) { - throw "Unable to get Session Token" - } - - Write-Host "Connected to vCenter API. Session established." -ForegroundColor Green + Invoke-SafeRestMethod -Uri $applyUri -Method Post -Headers $headers + Write-Host "New TLS certificate applied to vCenter" -ForegroundColor Green } catch { Show-Failure -ErrorRecord $_ @@ -96,31 +182,18 @@ catch { } # ---------------------------- -# Example REST Call (replace with actual logic) +# Restart vCenter Services (optional) # ---------------------------- try { - $headers = @{ 'vmware-api-session-id' = $sessionToken } + $restartUri = "https://$vCenterURL/rest/appliance/system/services/vpxd?action=restart" + $headers = @{ 'vmware-api-session-id' = $sessionToken } - $vmListParams = @{ - Uri = "https://$vCenterURL/rest/vcenter/vm" - Method = 'Get' - Headers = $headers - SslProtocol = 'Tls12' - ErrorAction = 'Stop' - } - - $vmList = Invoke-RestMethod @vmListParams - Write-Host "Retrieved VM list from vCenter:" -ForegroundColor Cyan - $vmList.value | ForEach-Object { Write-Host " - $($_.name)" } + Invoke-SafeRestMethod -Uri $restartUri -Method Post -Headers $headers + Write-Host "vCenter service restart initiated (vpxd)" -ForegroundColor Yellow + Write-Host "Note: UI/API may briefly be unavailable while services restart." -ForegroundColor Yellow } catch { Show-Failure -ErrorRecord $_ exit 1 } -# ---------------------------- -# (Continue with ACME + certificate automation) -# ---------------------------- -# At this point, all network calls use Invoke-RestMethod/Invoke-WebRequest with modern TLS. -# Extend with your ACME challenge/PowerDNS automation here. -