Automating LDAPS Configuration on vCenter Server using PowerCLI and Bash 1

Automating LDAPS Configuration on vCenter Server using PowerCLI and Bash

In today’s post, we’ll explore a PowerShell script that automates the LDAPS configuration (LDAP over SSL) on a vCenter Server. This script, named Configure-VcIdentitySourceLdaps.ps1, performs various tasks, including connecting to a vCenter Server, retrieving certificates from a domain controller, and configuring LDAPS with SSO (Single Sign-On).

Let’s dive into the details of the script and understand its key components:

Logging Function: Write-Log

Function Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$Value,
        [switch]$ErrorType,
        [switch]$SuccessType
    )
    
    $date = Get-Date -Format s 
    $fdate = Get-Date -Format dd-MM-yyyy
    $currentFolder = Get-Location
    $logFile = "$currentFolder\logs\logfile.txt"

    if ((Test-Path -Path "$currentFolder\Logs") -like "False") {
        New-Item -ItemType Directory -Path "$currentFolder\Logs" | Out-Null
    }

    if ($ErrorType) {
        Write-Host "$date - ERROR: $Value" -ForegroundColor Red
        Out-File -InputObject "$date - ERROR: $Value" -FilePath $LogFile -Append -Encoding utf8
    }
    elseif ($SuccessType) {
        Write-Host "$date - ERROR: $Value" -ForegroundColor Green
        Out-File -InputObject "$date - ERROR: $Value" -FilePath $LogFile -Append -Encoding utf8
    } else {
        Write-Host "$date - INFO: $Value" -ForegroundColor White
        Out-File -InputObject "$date - INFO: $Value"  -FilePath $LogFile -Append -Encoding utf8
    }
    
}

The script begins with a custom logging function named Write-Log. This function logs messages with timestamps and differentiates between error, success, and informational messages. It creates a log file in the ‘logs’ directory, ensuring that the logs are organized and easy to review.

LDAPS Configuration Function: Configure-VcIdentitySourceLdaps

Function Configure-VcIdentitySourceLdaps {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)][string]$vcenter,
        [Parameter(Mandatory=$true)][string]$vcenter_username,
        [Parameter(Mandatory=$true)][string]$vcenter_password,
        [Parameter(Mandatory=$true)][string]$vcenter_root_password,
        [Parameter(Mandatory=$true)][string]$primary_server_url,
        [string]$secondary_server_url,
        [Parameter(Mandatory=$true)][string]$domain,
        [Parameter(Mandatory=$true)][string]$domain_user,
        [Parameter(Mandatory=$true)][string]$domain_password,
        [Parameter(Mandatory=$true)][string]$base_user_dn,
        [Parameter(Mandatory=$true)][string]$base_group_dn
        )
    
    try {
            $currentFolder = Get-Location
            $certFilePathSource = "$currentFolder\ldaps.cer"
            $certFilePathDestination = "/tmp/ldaps.cer"
            $tempBashFileSource = "$currentFolder\bash.sh"
            $tempBashFileDestination = "/tmp/bash.sh"

            # Connect to vCenter Server
            Connect-VIServer -Server $vcenter -User $vcenter_username -Password $vcenter_password -ErrorAction Stop | Out-Null
            Write-Log -Value "Successfully connected to $($vcenter)" -SuccessType -ErrorAction Stop

            # Query vCenter VM that matches FQDN as hostname
            $vCenterVM = Get-VM | Where-Object {$_.ExtensionData.Guest.hostname -eq $vcenter} -ErrorAction Stop
        
            # Retrieve certificate from domain controller
            $getRootCert = "openssl s_client -connect $($primary_server_url -replace "ldaps://") -showcerts"
            $output = Invoke-VMScript -ScriptText $getRootCert -vm $vCenterVM -GuestUser "root" -GuestPassword $vcenter_root_password -ErrorAction Stop

            # Define the begin and end markers
            $beginMarker = "-----BEGIN CERTIFICATE-----"
            $endMarker = "-----END CERTIFICATE-----"

            # Initialize variables to store certificate positions
            $beginIndex = 0
            $endIndex = 0
            $certificates = @()

            # Find all occurrences of begin and end markers
            while (($beginIndex = $output.ScriptOutput.IndexOf($beginMarker, $endIndex)) -ne -1) {
                $beginIndex += $beginMarker.Length
                $endIndex = $output.ScriptOutput.IndexOf($endMarker, $beginIndex)
                $endIndex += $endMarker.Length + 2
    
                if ($endIndex -ne -1) {
                    # Include the begin and end markers in the certificate
                    $certificate = $output.ScriptOutput.Substring($beginIndex - $beginMarker.Length, $endIndex - $beginIndex + $endMarker.Length)
                    $certificates += $certificate
                }
            }

            # Output the extracted certificates
            foreach ($cert in $certificates) {
                Write-Log -Value "Certificate:" -ErrorAction Stop
                Write-Log -Value $cert -ErrorAction Stop
            }

            # Select the last certificate in the chain (if needed)
            $lastCertificate = $certificates[-1]
            Write-Log -Value "Last Certificate:" -ErrorAction Stop
            Write-Log -Value $lastCertificate -ErrorAction Stop
            # Export ldaps certificate
            $lastCertificate | Out-File -FilePath $certFilePathSource -Encoding ascii -ErrorAction Stop 
            # Copy certificate to vCenter server
            Copy-VMGuestFile -VM $vCenterVM -Source $certFilePathSource -Destination $certFilePathDestination -LocalToGuest -GuestUser "root" -GuestPassword $vcenter_root_password -Force -ErrorAction Stop

            # Checking if secondary server url is used.
            if ($secondary_server_url) {
                $FileOutput = "/opt/vmware/bin/sso-config.sh -add_identity_source -type adldap -baseUserDN $base_user_dn -baseGroupDN $base_group_dn -domain $domain -alias $($domain.split('.')[0]) -username $domain_user -password $domain_password -primaryURL $primary_server_url -secondaryURL $secondary_server_url -useSSL true -sslCert $certFilePathDestination"
            } else {
                $FileOutput = "/opt/vmware/bin/sso-config.sh -add_identity_source -type adldap -baseUserDN $base_user_dn -baseGroupDN $base_group_dn -domain $domain -alias $($domain.split('.')[0]) -username $domain_user -password $domain_password -primaryURL $primary_server_url -useSSL true -sslCert $certFilePathDestination"
            }

            # Create bash file to configure SSO on the vCenter server
            $FileOutput | Out-File -FilePath "bash.sh" -ErrorAction Stop -Force -Encoding ascii

            # Copy bash file to the vCenter server
            Copy-VMGuestFile -VM $vCenterVM -Source $tempBashFileSource -Destination $tempBashFileDestination -LocalToGuest -GuestUser "root" -GuestPassword $vcenter_root_password -Force -ErrorAction Stop

            Write-Log -Value "Configuring execution permissions on /tmp/bash.sh file." -ErrorAction Stop
            $setPermission = "chmod +x $tempBashFileDestination"
            $output = Invoke-VMScript -ScriptText $setPermission -vm $vCenterVM -GuestUser "root" -GuestPassword $vcenter_root_password -ErrorAction Stop

            # Configure SSO on the vCenter Server
            $configureSso = "/tmp/bash.sh"
            $output = Invoke-VMScript -ScriptText $configureSso -vm $vCenterVM -GuestUser "root" -GuestPassword $vcenter_root_password -ErrorAction Stop
            if($output.ScriptOutput -like "*ERROR*"){
                Write-Log -Value $output.ScriptOutput -ErrorType -ErrorAction Stop
                return
            }else{
                Write-Log -Value "SSO has been configured successfully on vCenter $vcenter_fqdn" -SuccessType -ErrorAction Stop
            }

            # Removing temporary bash file and ldaps.cer from source.
            Write-Log -Value "Performing cleanup of temp files on source and destination"
            $tempBashFileSource | Remove-Item -Force -Confirm:$false
            $certFilePathSource | Remove-Item -Force -Confirm:$false
            $removeTempFiles = "rm $certFilePathDestination $tempBashFileDestination"

            $output = Invoke-VMScript -ScriptText $removeTempFiles -vm $vCenterVM -GuestUser "root" -GuestPassword $vcenter_root_password -ErrorAction Stop
            
            # Disconnecting from vCenter Server.
            Disconnect-VIServer -Server * -Confirm:$false -Force -ErrorAction Stop

        } catch {
            Write-Log -Value $_ -ErrorType -ErrorAction Stop
        }

}

This function is the heart of the script, responsible for setting up LDAPS on the vCenter Server. Let’s break down its steps:

  1. Connection to vCenter Server:
    • Uses Connect-VIServer cmdlet to establish a connection to the vCenter Server.
    • Logs a success message upon successful connection.
  2. Querying vCenter VM:
    • Retrieves the VM object representing the vCenter Server using Get-VM and filtering based on the FQDN.
  3. Retrieving Certificates:
    • Invokes a script on the vCenter VM using Invoke-VMScript to obtain certificates from the primary domain controller.
    • Parses the output to extract individual certificates.
  4. Exporting Certificates:
    • Saves the last certificate in the chain to a local file (ldaps.cer) for later use.
  5. Copying Certificates to vCenter:
    • Uses Copy-VMGuestFile to transfer the certificate file to the vCenter Server.
  6. Creating Bash Script:
    • Generates a Bash script (bash.sh) containing SSO configuration commands based on the provided parameters.
  7. Copying Bash Script to vCenter:
    • Transfers the Bash script to the vCenter Server using Copy-VMGuestFile.
  8. Setting Execution Permissions:
    • Grants execution permissions to the Bash script on the vCenter Server.
  9. Configuring SSO:
    • Executes the Bash script on the vCenter Server to configure LDAPS and SSO.
    • Logs success or failure messages based on the script output.
  10. Cleanup:
    • Removes temporary files (bash.sh and ldaps.cer) from the source and destination.
  11. Disconnecting from vCenter Server:
    • Uses Disconnect-VIServer to close the connection to the vCenter Server.

Executing the Script:

The script is executed with specific parameters, such as vCenter Server details, domain information, and LDAPS URLs for primary and secondary servers.

Configure-VcIdentitySourceLdaps -vcenter "vc01.lab.lan" -vcenter_username "administrator@vsphere.local" -vcenter_password "VMware1!" -base_user_dn "dc=lab,dc=lan" -base_group_dn "dc=lab,dc=lan" -vcenter_root_password "VMware1!" -domain "lab.lan" -domain_user "administrator@lab.lan" -domain_password "VMware1!" -primary_server_url "ldaps://ldc01.lab.lan:636" -secondary_server_url "ldaps://ldc02.lab.lan:636"
LDAPS configuration
vCenter
Powercli
Identity Provider
LDAPS Configuration
vCenter
Powercli
Identity Provider

Download the Script :

To access and download the Configure-VcIdentitySourceLdaps.ps1 script, visit my GitHub repository at vkernel/vmware-scripts.

2 Comments

    1. Hi Jason,

      Sorry for my late reply, but i’m not sure if it will refresh an existing connection.
      You should test this first in a lab.

Leave a Comment