Some time ago I blogged about how I automate acquisition of Let’s Encrypt Certificates for my lab (NSX + vCloud Director) with PowerShell. The old script no longer works due to some changes on Let’s Encrypt side therefore the need for part 2.
To quickly summarize my situation. My lab consists of vCloud Director with multiple cells fronted by NSX-V Load Balancer. I need public certificate for vCloud Director which is uploaded to the NSX-V Load Balancer (that does L7 SSL termination) and to vCloud Director public addresses.
Prerequisites:
- Web server on the domain your are getting the certificate for. It is necessary for the DNS challenge that proves you own the domain you are requesting the certificate for. I am using IIS on the machine I trigger the script from and supply the root folder where the challenge file needs to be placed.
- NSX-V API access information – needed to replace the certificate on the NSX-Edge
- Details about the load balancer (on which Edge it is running and what is the LB application profile of vCloud Director)
- vCloud Director API access information – needed to upload new certificate and the full chain to vCloud Director public addresses.
- PowerShell modules: POSH-ACME and PowerCLI
$Username = "admin" $Password = "default" $NSXManager = "nsx01.fojta.com" $LBEdge = 'edge-1' $ApplicationProfile = 'applicationProfile-1' $Email = "mailto:admin@fojta.com" $Domain = "vcloud.fojta.com" $Vcd = "vcloud.fojta.com" $VcdAdmin = "administrator" $VcdPassword = "vcloud" $IisAcmeRoot = "C:\inetpub\wwwroot\.well-known\acme-challenge" $RootCert = "-----BEGIN CERTIFICATE----- MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw 7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ -----END CERTIFICATE----- " #Set-PAServer LE_STAGE Set-PAServer LE_PROD ## Read https://github.com/rmbolger/Posh-ACME/wiki/%28Advanced%29-Manual-HTTP-Challenge-Validation New-PAAccount -AcceptTOS -Contact $Email New-PAOrder $Domain $auths = Get-PAOrder | Get-PAAuthorizations $token = $auths[0].HTTP01Token $toPublish = Get-KeyAuthorization $token ## Upload challenge file to the IIS web server New-Item -Path $IisAcmeRoot -Name $token -Value $toPublish $auths.HTTP01Url | Send-ChallengeAck New-PACertificate $Domain $cert = Get-PACertificate $IssuerCert = [IO.File]::ReadAllText($cert.ChainFile) $PrivateKey = [IO.File]::ReadAllText($cert.KeyFile) $LBCertificate = [IO.File]::ReadAllText($cert.CertFile) ## Create authorization string and store in $head $auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Username + ":" + $Password)) $head = @{"Authorization"="Basic $auth"} ##Upload certificate $Uri = "https://$NSXManager/api/2.0/services/truststore/certificate/" + $LBEdge $Body = " <trustObject> <pemEncoding>" + $LBCertificate + $IssuerCert + $RootCert + "</pemEncoding> <privateKey>" + $PrivateKey + "</privateKey> <description>vCloud Certificate</description> </trustObject>" $r = Invoke-WebRequest -URI $Uri -Method Post -Headers $head -ContentType "application/xml" -Body $Body -ErrorAction:Stop $NewCertificateId = ([xml]$r).certificates.certificate.objectId ##Delete Root and intermediate certificate from the Edge as they are not needed $Uri = "https://$NSXManager/api/2.0/services/truststore/certificate/" + $NewCertificateId[0] $r = Invoke-WebRequest -URI $Uri -Method Delete -Headers $head -ContentType "application/xml" -ErrorAction:Stop $Uri = "https://$NSXManager/api/2.0/services/truststore/certificate/" + $NewCertificateId[1] $r = Invoke-WebRequest -URI $Uri -Method Delete -Headers $head -ContentType "application/xml" -ErrorAction:Stop ##Replace certificate in the application profile $Uri = "https://$NSXManager/api/4.0/edges/" + $LBEdge + "/loadbalancer/config/applicationprofiles/" + $ApplicationProfile $r = Invoke-WebRequest -URI $Uri -Method Get -Headers $head -ContentType "application/xml" -ErrorAction:Stop [xml]$sxml = $r.Content $OldCertificateId = $sxml.applicationProfile.clientSsl.serviceCertificate $sxml.applicationProfile.clientSsl.serviceCertificate = $NewCertificateId[2] $r = Invoke-WebRequest -Uri $Uri -Method Put -Headers $head -ContentType "application/xml" -Body $sxml.OuterXML -ErrorAction:Stop ##Delete old certificate from the Edge $Uri = "https://$NSXManager/api/2.0/services/truststore/certificate/" + $OldCertificateId $r = Invoke-WebRequest -URI $Uri -Method Delete -Headers $head -ContentType "application/xml" -ErrorAction:Stop ##Update vCloud Director with new certificates $VcdSession = Connect-CIServer $Vcd -User $VcdAdmin -Password $VcdPassword $Uri = "https://"+$Vcd+"/api/admin/extension/settings/general" $head = @{"x-vcloud-authorization"=$VcdSession.SessionSecret} + @{"Accept"="application/*;version=33.0"} $r = Invoke-WebRequest -URI $Uri -Method Get -Headers $head -ErrorAction:Stop [xml]$sxml = $r.Content $sxml.GeneralSettings.RestApiBaseUriPublicCertChain = $LBCertificate + $IssuerCert + $RootCert $sxml.GeneralSettings.SystemExternalAddressPublicCertChain = $LBCertificate + $IssuerCert + $RootCert $r = Invoke-WebRequest -URI $Uri -Method Put -Headers $head -ContentType "application/vnd.vmware.admin.generalSettings+xml" -Body $sxml.OuterXML -ErrorAction:Stop