From 6a9a96caf226d32d00fba335e1932c59179a729a Mon Sep 17 00:00:00 2001 From: David Schroeder Date: Sat, 15 Nov 2025 19:50:41 -0600 Subject: [PATCH] Update vCenter-SSL.ps1 --- inc/vCenter-SSL.ps1 | 164 ++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 112 deletions(-) diff --git a/inc/vCenter-SSL.ps1 b/inc/vCenter-SSL.ps1 index d55872d6..861f4222 100644 --- a/inc/vCenter-SSL.ps1 +++ b/inc/vCenter-SSL.ps1 @@ -1,6 +1,6 @@ #!/usr/bin/env pwsh # ----------------------------------------------------------------------------------- -# vCenter + Posh-ACME Script (Linux/macOS-safe, TLS 1.2 enforced) +# vCenter + Posh-ACME Script using PowerCLI (TLS-safe, cross-platform) # ----------------------------------------------------------------------------------- . /opt/idssys/nodemgmt/conf/powerwall/settings.ps1 @@ -11,31 +11,13 @@ $global:helpme = $null $global:responseBody = $null -# ---------------------------- -# Force TLS 1.2 globally -# ---------------------------- -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - # ---------------------------- # Error handler # ---------------------------- function Show-Failure { param([System.Management.Automation.ErrorRecord]$ErrorRecord) - $global:responseBody = "" - - try { - $ex = $ErrorRecord.Exception - if ($ex.Response -is [System.Net.Http.HttpResponseMessage]) { - try { $global:responseBody = $ex.Response.Content.ReadAsStringAsync().GetAwaiter().GetResult() } catch { $global:responseBody = "" } - } elseif ($ex.Response -is [System.Net.WebResponse]) { - try { - $stream = $ex.Response.GetResponseStream() - if ($stream) { $global:responseBody = [System.IO.StreamReader]::new($stream).ReadToEnd() } - } catch { $global:responseBody = "" } - } else { $global:responseBody = $ex.Message } - } catch { $global:responseBody = "" } - + $global:responseBody = $ErrorRecord.Exception.Message $global:helpme = $global:responseBody Write-Host "----------------------------------------" -ForegroundColor Red @@ -48,96 +30,25 @@ function Show-Failure { } # ---------------------------- -# Invoke-RestMethod wrapper with SkipCertificateCheck +# Ensure PowerCLI module # ---------------------------- -function Invoke-SafeRestMethod { - param( - [Parameter(Mandatory=$true)][string]$Uri, - [string]$Method = 'GET', - [hashtable]$Headers = @{}, - $Body = $null, - [switch]$AsJson - ) - - try { - $params = @{ - Uri = $Uri - Method = $Method - Headers = $Headers - SkipCertificateCheck = $true - ErrorAction = 'Stop' - } - - if ($Body -ne $null) { - if ($AsJson) { - $params.Body = ($Body | ConvertTo-Json -Depth 12 -Compress) - $params.ContentType = 'application/json' - } else { - $params.Body = $Body - } - } - - return Invoke-RestMethod @params - } catch { - Show-Failure -ErrorRecord $_ - } +if (-not (Get-Module -ListAvailable -Name VMware.PowerCLI)) { + Install-Module -Name VMware.PowerCLI -Force -Scope AllUsers } +Import-Module VMware.PowerCLI -ErrorAction Stop # ---------------------------- -# Variables +# Ignore self-signed cert warnings # ---------------------------- -$vCenterURL = $VCENTERHOST -$CommonName = $VCENTERHOST -$EmailContact = $ACMEEMAIL - -[PSCredential]$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $VCENTERUSER, (ConvertTo-SecureString $VCENTERPASS -AsPlainText -Force) - -# PowerDNS plugin args (plain string API key) -$pArgs = @{ - PowerDNSApiHost = $WDNSHOST - PowerDNSApiKey = $PDNSAPI - PowerDNSUseTLS = $true - PowerDNSPort = 443 - PowerDNSServerName = 'localhost' -} +Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false | Out-Null # ---------------------------- -# Ensure Posh-ACME Module +# Connect to vCenter # ---------------------------- -if (-not (Get-Module -ListAvailable -Name Posh-ACME)) { - Install-Module -Name Posh-ACME -Force -Confirm:$false -Scope AllUsers -} -Import-Module Posh-ACME -ErrorAction Stop - -# ---------------------------- -# Connect to vCenter API using HttpClient (TLS 1.2 enforced) -# ---------------------------- -Write-Host "Connecting to vCenter at $vCenterURL ..." -ForegroundColor Cyan - try { - $handler = [System.Net.Http.HttpClientHandler]::new() - $handler.SslProtocols = [System.Security.Authentication.SslProtocols]::Tls12 - $handler.ServerCertificateCustomValidationCallback = { $true } - - $client = [System.Net.Http.HttpClient]::new($handler) - $client.Timeout = [System.TimeSpan]::FromSeconds(60) - - $loginUri = "https://$vCenterURL/rest/com/vmware/cis/session" - $response = $client.PostAsync($loginUri, $null).GetAwaiter().GetResult() - - if (-not $response.IsSuccessStatusCode) { - throw "vCenter session request failed: $($response.StatusCode)" - } - - $content = $response.Content.ReadAsStringAsync().GetAwaiter().GetResult() - $json = $content | ConvertFrom-Json - $sessionToken = $json.value - - if (-not $sessionToken) { throw "Failed to obtain vCenter session token" } - - $headers = @{ 'vmware-api-session-id' = $sessionToken } + Write-Host "Connecting to vCenter at $VCENTERHOST ..." -ForegroundColor Cyan + $vCenterConn = Connect-VIServer -Server $VCENTERHOST -User $VCENTERUSER -Password $VCENTERPASS -Force Write-Host "Connected to vCenter API. Session established." -ForegroundColor Green - } catch { Show-Failure -ErrorRecord $_ } @@ -146,18 +57,37 @@ try { # Retrieve VM list (optional) # ---------------------------- try { - $vmList = Invoke-SafeRestMethod -Uri "https://$vCenterURL/rest/vcenter/vm" -Headers $headers - if ($vmList.value) { $vmList.value | ForEach-Object { Write-Host " - $($_.name)" } } -} catch { Write-Host "Unable to retrieve VM list, continuing..." -ForegroundColor Yellow } + $vms = Get-VM + Write-Host "Retrieved VM list:" -ForegroundColor Cyan + $vms | ForEach-Object { Write-Host " - $($_.Name)" } +} catch { + Write-Host "Unable to retrieve VM list, continuing..." -ForegroundColor Yellow +} # ---------------------------- -# ACME certificate request +# Ensure Posh-ACME module # ---------------------------- +if (-not (Get-Module -ListAvailable -Name Posh-ACME)) { + Install-Module -Name Posh-ACME -Force -Scope AllUsers +} +Import-Module Posh-ACME -ErrorAction Stop + +# ---------------------------- +# ACME / PowerDNS certificate request +# ---------------------------- +$pArgs = @{ + PowerDNSApiHost = $WDNSHOST + PowerDNSApiKey = $PDNSAPI + PowerDNSUseTLS = $true + PowerDNSPort = 443 + PowerDNSServerName = 'localhost' +} + $certName = "vcenter-cert" $certSuccess = $false try { Write-Host "Requesting certificate via Posh-ACME..." -ForegroundColor Cyan - New-PACertificate -Domain $CommonName -DnsPlugin PowerDNS -PluginArgs $pArgs -Contact $EmailContact -AcceptTOS -Verbose -Force + New-PACertificate -Domain $VCENTERHOST -DnsPlugin PowerDNS -PluginArgs $pArgs -Contact $ACMEEMAIL -AcceptTOS -Verbose -Force $certSuccess = $true } catch { Write-Host "ACME certificate request failed: $($_.Exception.Message)" -ForegroundColor Yellow @@ -183,18 +113,27 @@ if ($certSuccess) { } # ---------------------------- -# Upload and apply certificate +# Upload and apply certificate via REST (PowerCLI session) # ---------------------------- if ($certSuccess) { try { - Invoke-SafeRestMethod -Uri "https://$vCenterURL/rest/vcenter/certificate-management/vcenter/tls" -Method Post -Headers $headers -Body @{ + $sessionHeaders = @{ + 'vmware-api-session-id' = $vCenterConn.ExtensionData.Content.SessionManager.SessionId + } + + $body = @{ cert = Get-Content -Path $certPath -Raw key = Get-Content -Path $keyPath -Raw chain = Get-Content -Path $chainPath -Raw - } -AsJson - Write-Host "Certificate uploaded successfully." -ForegroundColor Green - Invoke-SafeRestMethod -Uri "https://$vCenterURL/rest/vcenter/certificate-management/vcenter/tls?action=apply" -Method Post -Headers $headers - Write-Host "TLS certificate applied." -ForegroundColor Green + } + + $uriUpload = "https://$VCENTERHOST/rest/vcenter/certificate-management/vcenter/tls" + Invoke-RestMethod -Uri $uriUpload -Method Post -Body ($body | ConvertTo-Json -Compress) -ContentType 'application/json' -Headers $sessionHeaders -SkipCertificateCheck + + $uriApply = "https://$VCENTERHOST/rest/vcenter/certificate-management/vcenter/tls?action=apply" + Invoke-RestMethod -Uri $uriApply -Method Post -Headers $sessionHeaders -SkipCertificateCheck + + Write-Host "TLS certificate uploaded and applied successfully." -ForegroundColor Green } catch { Write-Host "Certificate upload/apply failed: $($_.Exception.Message)" -ForegroundColor Yellow $global:helpme = $_.Exception.Message @@ -207,7 +146,8 @@ if ($certSuccess) { # Restart vpxd service # ---------------------------- try { - Invoke-SafeRestMethod -Uri "https://$vCenterURL/rest/appliance/system/services/vpxd?action=restart" -Method Post -Headers $headers + $uriRestart = "https://$VCENTERHOST/rest/appliance/system/services/vpxd?action=restart" + Invoke-RestMethod -Uri $uriRestart -Method Post -Headers $sessionHeaders -SkipCertificateCheck Write-Host "vCenter vpxd service restart requested." -ForegroundColor Yellow } catch { Write-Host "Failed to restart vpxd service: $($_.Exception.Message)" -ForegroundColor Yellow