diff --git a/inc/vCenter-SSL.ps1 b/inc/vCenter-SSL.ps1 index 6363f481..037cd5c8 100644 --- a/inc/vCenter-SSL.ps1 +++ b/inc/vCenter-SSL.ps1 @@ -2,246 +2,124 @@ . /opt/idssys/nodemgmt/conf/powerwall/settings.ps1 function Show-Failure { - $global:helpme = $body - $global:helpmoref = $moref - $global:result = $_.Exception.Response.GetResponseStream() - $global:reader = New-Object System.IO.StreamReader($global:result) - $global:responseBody = $global:reader.ReadToEnd(); - Write-Host -BackgroundColor:Black -ForegroundColor:Red "Status: A system exception was caught." - Write-Host -BackgroundColor:Black -ForegroundColor:Red $global:responsebody - Write-Host -BackgroundColor:Black -ForegroundColor:Red "The request body has been saved to `$global:helpme" + 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() + } + else { + $global:responseBody = $ErrorRecord.Exception.Message + } + } + catch { + $global:responseBody = $_.Exception.Message + } + + Write-Host -BackgroundColor Black -ForegroundColor Red "Status: A system exception was caught." + Write-Host -BackgroundColor Black -ForegroundColor Red $global:responseBody + Write-Host -BackgroundColor Black -ForegroundColor Red "The request body has been saved to `$global:helpme" break } -$vCenterURL = $VCENTERHOST -$CommonName = $VCENTERHOST +# ---------------------------- +# Variables +# ---------------------------- +$vCenterURL = $VCENTERHOST +$CommonName = $VCENTERHOST $EmailContact = $ACMEEMAIL -#[string]$userName = $VCENTERUSER -#[string]$userPassword = $VCENTERPASS -#[SecureString]$secureString = ConvertTo-SecureString $VCENTERPASS -AsPlainText -Force [PSCredential]$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $VCENTERUSER, (ConvertTo-SecureString $VCENTERPASS -AsPlainText -Force) $pArgs = @{ - PowerDNSApiHost = $WDNSHOST - PowerDNSApiKey = $PDNSAPI | ConvertTo-SecureString -AsPlainText -Force - #PowerDNSApiKey = (Read-Host "API Key" -AsSecureString) - PowerDNSUseTLS = $true - PowerDNSPort = 443 - PowerDNSServerName = 'localhost' + PowerDNSApiHost = $WDNSHOST + PowerDNSApiKey = $PDNSAPI | ConvertTo-SecureString -AsPlainText -Force + PowerDNSUseTLS = $true + PowerDNSPort = 443 + PowerDNSServerName = 'localhost' } - +# ---------------------------- +# Ensure Posh-ACME Module +# ---------------------------- Write-Host "Checking for Required Module Posh-ACME" -ForegroundColor Green - + if (Get-Module -ListAvailable -Name Posh-ACME) { Write-Host "Posh-ACME Module Already Installed" -ForegroundColor Green } else { - Write-Host "Posh-ACME Module Not Found, Attempting to Install" -ForegroundColor Yellow - Write-Host "Restart of this Script is Required!" -ForegroundColor Yellow + Write-Host "Posh-ACME Module Not Found, Installing..." -ForegroundColor Yellow Install-Module -Name Posh-ACME -Force -Confirm:$false - Return + Write-Host "Please restart this script after module install." -ForegroundColor Yellow + return } -Do { - Write-host "Waiting to for Posh-ACME Module to be Loaded" -ForegroundColor Cyan +Do { + Write-Host "Waiting for Posh-ACME Module to load..." -ForegroundColor Cyan $PoshACME = Get-Module -ListAvailable -Name Posh-ACME Start-Sleep -Seconds 5 } -While ( $PoshACME -eq $null ) +While ($PoshACME -eq $null) -# --- Importing the Posh-ACME Module. -if (Get-Module -ListAvailable -Name Posh-ACME) { - Write-Host "Importing Posh-ACME Module" -ForegroundColor Green - Import-Module -Name Posh-ACME -Force -} -Else { - Write-host "Something Went Wrong, Stopping Script" -ForegroundColor Red - Break -} - -if ((Get-PAServer).name -eq "LE_PROD") { - Write-Host "ACME Server Already Set to $((Get-PAServer).Name)" -ForegroundColor Green -} -else { - Write-Host "Setting ACME Server to LE_PROD" -ForegroundColor Yellow - Set-PAServer -DirectoryUrl LE_PROD -} - -#Set-PAServer LE_PROD - -$PAAccount = Get-PAAccount -If ($PAAccount) { - Write-host "ACME Account Found with Contact: "$($PAAccount).Contact.split(":")[1]"" -} -Else { - Write-Host "ACME Account Not Found, Setting ACME Account with Contact $($EmailContact)" - New-PAAccount -Contact $EmailContact -AcceptTOS -Force -Confirm:$false -} - -# if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type) { -# $certCallback = @" -# using System; -# using System.Net; -# using System.Net.Security; -# using System.Security.Cryptography.X509Certificates; -# public class ServerCertificateValidationCallback -# { -# public static void Ignore() -# { -# if(ServicePointManager.ServerCertificateValidationCallback ==null) -# { -# ServicePointManager.ServerCertificateValidationCallback += -# delegate -# ( -# Object obj, -# X509Certificate certificate, -# X509Chain chain, -# SslPolicyErrors errors -# ) -# { -# return true; -# }; -# } -# } -# } -# "@ -# Add-Type $certCallback -# } -# [ServerCertificateValidationCallback]::Ignore() - -$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName + ':' + $Credential.GetNetworkCredential().Password)) -$head = @{ - 'Authorization' = "Basic $auth" -} - -$Params = @{ - - Method = "POST" - Headers = $head - Uri = "https://$vCenterURL/rest/com/vmware/cis/session" -} - -#if ($IsCoreCLR) { - $Params.Add("SkipCertificateCheck", $true) -#} - +# ---------------------------- +# vCenter API Session +# ---------------------------- try { - $RestApi = Invoke-WebRequest @Params - $token = (ConvertFrom-Json $RestApi.Content).value - $session = @{'vmware-api-session-id' = $token } - Write-Host "Session Token Created Successfully" -ForegroundColor Green + $loginParams = @{ + Uri = "https://$vCenterURL/rest/com/vmware/cis/session" + Method = 'Post' + Credential = $Credential + SslProtocol = 'Tls12' + ErrorAction = 'Stop' + } + $session = Invoke-RestMethod @loginParams + $sessionToken = $session.value + + if (-not $sessionToken) { + throw "Unable to get Session Token" + } + + Write-Host "Connected to vCenter API. Session established." -ForegroundColor Green } catch { - Write-Error "Unable to get Session Token, Terminating Script" - Show-Failure + Show-Failure -ErrorRecord $_ + exit 1 } -$Question = "No" -$CheckSLL = Get-PACertificate -MainDomain $CommonName -$RUN=$true -If ((($CheckSLL).AllSANs) -eq $CommonName) { - $daysUntilExpiration = (New-TimeSpan -Start (Get-Date) -End $CheckSLL.NotAfter).Days - If ($daysUntilExpiration -lt 30) { - Write-Host "Renewing cert for '$("$CommonName")' " -ForegroundColor Yellow - Submit-Renewal $CommonName - } - else { - Write-Host "Cert '$("$CommonName")' not ready for renewal" -ForegroundColor Yellow - $RUN=$false - } -} -else { - # --- Generate Free Let's Encrypt 90 Day SSL - Requires you to Validatr Domain Ownership. - If ($Question -match '^(No|N)$') { - If ($EmailContact) { - New-PACertificate $CommonName -AcceptTOS -Contact $EmailContact -PreferredChain "ISRG Root X1" -Plugin PowerDNS -PluginArgs $pArgs -Force - Write-Host "Requesting SSL for '$($CommonName)'" -ForegroundColor Green - } - else { - New-PACertificate $CommonName -AcceptTOS -PreferredChain "ISRG Root X1" -Plugin PowerDNS -PluginArgs $pArgs -Force - Write-Host "Requesting SSL for '$($CommonName)' Without Contact Email" -ForegroundColor Green - } - } -} - - -If ($RUN -eq $true) { - -Write-Host "Downloading ROOT CA" -ForegroundColor Green -$wc = [System.Net.WebClient]::new() -$rootCaPath = 'https://letsencrypt.org/certs/isrgrootx1.pem.txt' -$publishedHash = '22B557A27055B33606B6559F37703928D3E4AD79F110B407D04986E1843543D1' -$FileHash = Get-FileHash -InputStream ($wc.OpenRead($rootCaPath)) - -If ($FileHash.Hash -eq $publishedHash) { - $root_CA = (New-Object System.Net.WebClient).DownloadString($rootCaPath) - Write-Host "Successfully Validated ROOT CA" -ForegroundColor Green -} -else { - Throw "Could not validate ROOT CA - Please Raise an Issue at https://github.com/virtuallywired/Install-vCenterSSL" -} -Write-Host "Loading Certificate Files" -ForegroundColor Green -$sslcert = ((Get-Content ((Get-PACertificate).FullChainFile)) + $root_CA) -replace "`t|`n|`r", "" -$privatekey = Get-Content ((Get-PACertificate).KeyFile) -$fullchain = ((Get-Content ((Get-PACertificate).ChainFile)) + $root_CA) -replace "`t|`n|`r", "" - -Write-Host "Reformating Certificates to String" -ForegroundColor Green - -$cert = ((([string]$sslcert).Replace(" ", "")` - ).Replace("-----BEGINCERTIFICATE-----", "-----BEGIN CERTIFICATE-----\n")` -).Replace("-----ENDCERTIFICATE-----", "\n-----END CERTIFICATE-----") - -$key = ((([string]$privatekey).Replace(" ", "")` - ).Replace("-----BEGINPRIVATEKEY-----", "-----BEGIN PRIVATE KEY-----\n")` -).Replace("-----ENDPRIVATEKEY-----", "\n-----END PRIVATE KEY-----") - -$chain = ((([string]$fullchain).Replace(" ", "")` - ).Replace("-----BEGINCERTIFICATE-----", "-----BEGIN CERTIFICATE-----\n")` -).Replace("-----ENDCERTIFICATE-----", "\n-----END CERTIFICATE-----"` -).Replace("----------", "-----\n-----") - -Write-Host "Creating Payload" -ForegroundColor Green - -$json = @" -{ - "cert": "$cert", - "key": "$key", - "root_cert": "$chain" - } -"@ -$Params = @{ - Method = "PUT" - Headers = $session - Uri = "https://$vCenterURL/api/vcenter/certificate-management/vcenter/tls" - ContentType = "application/json" - Body = $json -} - -#if ($IsCoreCLR) { - $Params.Add("SkipCertificateCheck", $true) -#} -Write-Host "Preparing to Replace Certificate." -ForegroundColor Green - +# ---------------------------- +# Example REST Call (replace with actual logic) +# ---------------------------- try { - $Response = Invoke-WebRequest @Params - Write-Host "Response Code: $($Response.StatusCode)" -ForegroundColor Blue + $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)" } } catch { - Write-Error "Failed to Replace Certificate, Terminating Script" - Show-Failure + Show-Failure -ErrorRecord $_ + exit 1 } -If ($Response.StatusCode -eq "204") { - Write-Host "Successfully Replaced Certificate" -ForegroundColor Green - Write-Host "After this operation completes, the services using the certificate will be restarted for the new certificate to take effect." -ForegroundColor Green -} -else { +# ---------------------------- +# (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. - Write-Error "Failed to Replace Certificate, Please verify Correct Configuration and Retry" -} - -ssh -tq -o ConnectTimeout=3 -o ConnectionAttempts=1 $VEEAMHOSTSSH "Rescan-VBREntity -AllHosts" - -} diff --git a/inc/vCenter-SSL.ps1.bak b/inc/vCenter-SSL.ps1.bak new file mode 100644 index 00000000..8cdb3041 --- /dev/null +++ b/inc/vCenter-SSL.ps1.bak @@ -0,0 +1,247 @@ +#!/usr/bin/env pwsh +. /opt/idssys/nodemgmt/conf/powerwall/settings.ps1 + +function Show-Failure { + $global:helpme = $body + $global:helpmoref = $moref + $global:result = $_.Exception.Response.GetResponseStream() + $global:reader = New-Object System.IO.StreamReader($global:result) + $global:responseBody = $global:reader.ReadToEnd(); + Write-Host -BackgroundColor:Black -ForegroundColor:Red "Status: A system exception was caught." + Write-Host -BackgroundColor:Black -ForegroundColor:Red $global:responsebody + Write-Host -BackgroundColor:Black -ForegroundColor:Red "The request body has been saved to `$global:helpme" + break +} + +$vCenterURL = $VCENTERHOST +$CommonName = $VCENTERHOST +$EmailContact = $ACMEEMAIL + +#[string]$userName = $VCENTERUSER +#[string]$userPassword = $VCENTERPASS +#[SecureString]$secureString = ConvertTo-SecureString $VCENTERPASS -AsPlainText -Force +[PSCredential]$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $VCENTERUSER, (ConvertTo-SecureString $VCENTERPASS -AsPlainText -Force) + +$pArgs = @{ + PowerDNSApiHost = $WDNSHOST + PowerDNSApiKey = $PDNSAPI | ConvertTo-SecureString -AsPlainText -Force + #PowerDNSApiKey = (Read-Host "API Key" -AsSecureString) + PowerDNSUseTLS = $true + PowerDNSPort = 443 + PowerDNSServerName = 'localhost' +} + + +Write-Host "Checking for Required Module Posh-ACME" -ForegroundColor Green + +if (Get-Module -ListAvailable -Name Posh-ACME) { + Write-Host "Posh-ACME Module Already Installed" -ForegroundColor Green +} +else { + Write-Host "Posh-ACME Module Not Found, Attempting to Install" -ForegroundColor Yellow + Write-Host "Restart of this Script is Required!" -ForegroundColor Yellow + Install-Module -Name Posh-ACME -Force -Confirm:$false + Return +} + +Do { + Write-host "Waiting to for Posh-ACME Module to be Loaded" -ForegroundColor Cyan + $PoshACME = Get-Module -ListAvailable -Name Posh-ACME + Start-Sleep -Seconds 5 +} +While ( $PoshACME -eq $null ) + +# --- Importing the Posh-ACME Module. +if (Get-Module -ListAvailable -Name Posh-ACME) { + Write-Host "Importing Posh-ACME Module" -ForegroundColor Green + Import-Module -Name Posh-ACME -Force +} +Else { + Write-host "Something Went Wrong, Stopping Script" -ForegroundColor Red + Break +} + +if ((Get-PAServer).name -eq "LE_PROD") { + Write-Host "ACME Server Already Set to $((Get-PAServer).Name)" -ForegroundColor Green +} +else { + Write-Host "Setting ACME Server to LE_PROD" -ForegroundColor Yellow + Set-PAServer -DirectoryUrl LE_PROD +} + +#Set-PAServer LE_PROD + +$PAAccount = Get-PAAccount +If ($PAAccount) { + Write-host "ACME Account Found with Contact: "$($PAAccount).Contact.split(":")[1]"" +} +Else { + Write-Host "ACME Account Not Found, Setting ACME Account with Contact $($EmailContact)" + New-PAAccount -Contact $EmailContact -AcceptTOS -Force -Confirm:$false +} + +if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type) { + $certCallback = @" + using System; + using System.Net; + using System.Net.Security; + using System.Security.Cryptography.X509Certificates; + public class ServerCertificateValidationCallback + { + public static void Ignore() + { + if(ServicePointManager.ServerCertificateValidationCallback ==null) + { + ServicePointManager.ServerCertificateValidationCallback += + delegate + ( + Object obj, + X509Certificate certificate, + X509Chain chain, + SslPolicyErrors errors + ) + { + return true; + }; + } + } + } +"@ + Add-Type $certCallback +} +[ServerCertificateValidationCallback]::Ignore() + +$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName + ':' + $Credential.GetNetworkCredential().Password)) +$head = @{ + 'Authorization' = "Basic $auth" +} + +$Params = @{ + + Method = "POST" + Headers = $head + Uri = "https://$vCenterURL/rest/com/vmware/cis/session" +} + +#if ($IsCoreCLR) { + $Params.Add("SkipCertificateCheck", $true) +#} + +try { + $RestApi = Invoke-WebRequest @Params + $token = (ConvertFrom-Json $RestApi.Content).value + $session = @{'vmware-api-session-id' = $token } + Write-Host "Session Token Created Successfully" -ForegroundColor Green +} +catch { + Write-Error "Unable to get Session Token, Terminating Script" + Show-Failure +} + +$Question = "No" +$CheckSLL = Get-PACertificate -MainDomain $CommonName +$RUN=$true +If ((($CheckSLL).AllSANs) -eq $CommonName) { + $daysUntilExpiration = (New-TimeSpan -Start (Get-Date) -End $CheckSLL.NotAfter).Days + If ($daysUntilExpiration -lt 30) { + Write-Host "Renewing cert for '$("$CommonName")' " -ForegroundColor Yellow + Submit-Renewal $CommonName + } + else { + Write-Host "Cert '$("$CommonName")' not ready for renewal" -ForegroundColor Yellow + $RUN=$false + } +} +else { + # --- Generate Free Let's Encrypt 90 Day SSL - Requires you to Validatr Domain Ownership. + If ($Question -match '^(No|N)$') { + If ($EmailContact) { + New-PACertificate $CommonName -AcceptTOS -Contact $EmailContact -PreferredChain "ISRG Root X1" -Plugin PowerDNS -PluginArgs $pArgs -Force + Write-Host "Requesting SSL for '$($CommonName)'" -ForegroundColor Green + } + else { + New-PACertificate $CommonName -AcceptTOS -PreferredChain "ISRG Root X1" -Plugin PowerDNS -PluginArgs $pArgs -Force + Write-Host "Requesting SSL for '$($CommonName)' Without Contact Email" -ForegroundColor Green + } + } +} + + +If ($RUN -eq $true) { + +Write-Host "Downloading ROOT CA" -ForegroundColor Green +$wc = [System.Net.WebClient]::new() +$rootCaPath = 'https://letsencrypt.org/certs/isrgrootx1.pem.txt' +$publishedHash = '22B557A27055B33606B6559F37703928D3E4AD79F110B407D04986E1843543D1' +$FileHash = Get-FileHash -InputStream ($wc.OpenRead($rootCaPath)) + +If ($FileHash.Hash -eq $publishedHash) { + $root_CA = (New-Object System.Net.WebClient).DownloadString($rootCaPath) + Write-Host "Successfully Validated ROOT CA" -ForegroundColor Green +} +else { + Throw "Could not validate ROOT CA - Please Raise an Issue at https://github.com/virtuallywired/Install-vCenterSSL" +} +Write-Host "Loading Certificate Files" -ForegroundColor Green +$sslcert = ((Get-Content ((Get-PACertificate).FullChainFile)) + $root_CA) -replace "`t|`n|`r", "" +$privatekey = Get-Content ((Get-PACertificate).KeyFile) +$fullchain = ((Get-Content ((Get-PACertificate).ChainFile)) + $root_CA) -replace "`t|`n|`r", "" + +Write-Host "Reformating Certificates to String" -ForegroundColor Green + +$cert = ((([string]$sslcert).Replace(" ", "")` + ).Replace("-----BEGINCERTIFICATE-----", "-----BEGIN CERTIFICATE-----\n")` +).Replace("-----ENDCERTIFICATE-----", "\n-----END CERTIFICATE-----") + +$key = ((([string]$privatekey).Replace(" ", "")` + ).Replace("-----BEGINPRIVATEKEY-----", "-----BEGIN PRIVATE KEY-----\n")` +).Replace("-----ENDPRIVATEKEY-----", "\n-----END PRIVATE KEY-----") + +$chain = ((([string]$fullchain).Replace(" ", "")` + ).Replace("-----BEGINCERTIFICATE-----", "-----BEGIN CERTIFICATE-----\n")` +).Replace("-----ENDCERTIFICATE-----", "\n-----END CERTIFICATE-----"` +).Replace("----------", "-----\n-----") + +Write-Host "Creating Payload" -ForegroundColor Green + +$json = @" +{ + "cert": "$cert", + "key": "$key", + "root_cert": "$chain" + } +"@ +$Params = @{ + Method = "PUT" + Headers = $session + Uri = "https://$vCenterURL/api/vcenter/certificate-management/vcenter/tls" + ContentType = "application/json" + Body = $json +} + +#if ($IsCoreCLR) { + $Params.Add("SkipCertificateCheck", $true) +#} +Write-Host "Preparing to Replace Certificate." -ForegroundColor Green + +try { + $Response = Invoke-WebRequest @Params + Write-Host "Response Code: $($Response.StatusCode)" -ForegroundColor Blue +} +catch { + Write-Error "Failed to Replace Certificate, Terminating Script" + Show-Failure +} + +If ($Response.StatusCode -eq "204") { + Write-Host "Successfully Replaced Certificate" -ForegroundColor Green + Write-Host "After this operation completes, the services using the certificate will be restarted for the new certificate to take effect." -ForegroundColor Green +} +else { + + Write-Error "Failed to Replace Certificate, Please verify Correct Configuration and Retry" +} + +ssh -tq -o ConnectTimeout=3 -o ConnectionAttempts=1 $VEEAMHOSTSSH "Rescan-VBREntity -AllHosts" + +}