Public/Appliance/Install-vCAVCertificate.ps1
function Install-vCAVCertificate(){ <# .SYNOPSIS Replaces the certificate that is currently installed on the appliance with a custom certificate. .DESCRIPTION Replaces the certificate that is currently installed on the appliance with a custom certificate. The old certificate will be backed up and stored on the appliance. This will restart the service. .PARAMETER Certificate Full file path to PKCS#12 file which contains one private key and its corresponding certificate. .PARAMETER CertificateFileSecret A secure string with the keystore password. The keystore password and the password for the private key must be the same. .PARAMETER Force If set as True, the user will not be warned and the cmdlet will execute without prompting for confirmation .EXAMPLE Install-vCAVCertificate -Certificate "D:\Tools\Scripts\vSphere\vCAV\vcav-site-a-pigeonnuggets-com.pfx" -Password ("Password!" | ConvertTo-SecureString) Installs the certificate in PKCS#12 file D:\Tools\Scripts\vSphere\vCAV\vcav-site-a-pigeonnuggets-com.pfx with keystore and private key password of Password! to the connected vCloud Availability service. .EXAMPLE Install-vCAVCertificate -Certificate "D:\Tools\Scripts\vSphere\vCAV\vcav-site-a-pigeonnuggets-com.pfx" -Password ("Password!" | ConvertTo-SecureString) -Force $true Installs the certificate in PKCS#12 file D:\Tools\Scripts\vSphere\vCAV\vcav-site-a-pigeonnuggets-com.pfx with keystore and private key password of Password! to the connected vCloud Availability service without prompting for confirmation. .NOTES AUTHOR: Adrian Begg LASTEDIT: 2019-09-16 VERSION: 2.0 #> Param( [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [String] $Certificate, [Parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [SecureString] $CertificateFileSecret, [Parameter(Mandatory=$False)] [bool]$Force = $false ) # First validate if the certificate and password are valid and the Usage Type contains Server Authentication try{ $objCertVerify = Get-PfxCertificate -FilePath $Certificate -Password $CertificateFileSecret } catch { if($_.Exception.Message -eq "The specified network password is not correct"){ throw "The password provided for the PKCS#12 certificate $Certificate is not correct." } elseif($_.Exception.Message -eq "Command cannot find any of the specified files"){ throw "The file $Certificate does not exist. Please check the path and try the cmdlet again." } elseif($_.Exception.Message -eq "Cannot find the requested object"){ throw "The file $Certificate is corrupt or does not appear to be a valid PKCS#12 file. Please check the path and try the cmdlet again." } else { throw $_ } } if($objCertVerify.EnhancedKeyUsageList.FriendlyName -notcontains "Server Authentication"){ throw "The provided certificate does not have a Enhanced Key Usage of type Server Authentication. vCAV requires a certificate with this Usage Type." } # As non-JSON/standard API call need to directly create the request for the Payload # Validate the environment is ready based on the input parameters if($DefaultvCAVServer.buildVersion -lt "3.0"){ throw "This cmdlet is only supported on vCloud Availability 3.0+. The current connected version is $($DefaultvCAVServer.buildVersion)" } $PlainTextCertSecret = New-Object System.Management.Automation.PSCredential ("empty", $CertificateFileSecret) # Construct the headers for the API call $APIHeaders = @{ 'Content-Type' = 'application/octet-stream' 'Accept' = 'application/vnd.vmware.h4-v3+json' 'X-VCAV-Auth' = $global:DefaultvCAVServer.AccessToken 'Secret' = $PlainTextCertSecret.GetNetworkCredential().Password } # Create a Hashtable with base paramters to use for splatting to Invoke-WebRequest $HashInvokeArguments = @{ Uri = ($global:DefaultvCAVServer.ServiceURI + "config/certificate") Method = "Post" Headers = $APIHeaders InFile = $Certificate } # Next check the PowerCLI Proxy policy to determine if what Proxy Policy should be used for the API call, if((Get-PowerCLIConfiguration -Scope "User" | Select-Object ProxyPolicy).ProxyPolicy -eq "NoProxy") { $HashInvokeArguments.Add("NoProxy",$true) } # Check if the Certificate Check should be performed and add the argument if not if((Get-PowerCLIConfiguration -Scope "User" | Select-Object InvalidCertificateAction).InvalidCertificateAction -eq "Ignore") { $HashInvokeArguments.Add("SkipCertificateCheck",$true) } # Warn the users that this is dangerous if(!$Force){ Write-Warning "This cmdlet overwrites the currently installed certificate on the connected vCAV Service. This will cause all existing trusts with other sites and customer on-pemise appliances to become invalid. Please proceed with caution/during an organised and planned maintenance window." -WarningAction Inquire } # Now try and make the API call try{ $Request = Invoke-WebRequest @HashInvokeArguments $objResponse = New-Object System.Management.Automation.PSObject $objResponse | Add-Member Note* Headers $Request.Headers if($null -ne $Request.Content){ $objResponse | Add-Member Note* JSONData (ConvertFrom-JSON ([System.Text.Encoding]::UTF8.GetString($Request.Content))) } $objResponse.JSONData Write-Warning "Certificate installation complete. The service will automatically restart. You must reconnect to vCloud Availability." Disconnect-vCAVService } catch { if($_.Exception.Response.StatusCode -eq "Unauthorized"){ throw "An Unauhorized Exception was thrown attempting to make the API call to $($global:DefaultvCAVServer.ServiceURI + "config/certificate"). Please check that you have the required permissions to execute this call and that you have a current connected session." } else { throw "An error occured making an API call to $($global:DefaultvCAVServer.ServiceURI + "config/certificate"). Exception details: $($_.Exception)" } } } |