Configuring syslog on NSX Controllers using PowerShell

Share on:

I recently needed to configure a number of NSX Controller nodes to forward their logs using syslog to a vRealize Log Insight cluster.  Unlike the NSX manager (and most other components of a VMware SDDC), NSX controllers don’t provide a graphical way of configuring syslog.  In fact, they don’t even offer a CLI command for syslog configuration.  Instead, you need to use the NSX REST API.

Now, if you take a look at the official documentation for performing this configuration (including the NSX 6.3 documentation centre, or the VMware Validated Design for SDDC 4.0 documentation), you’ll find instructions which involve installing REST plug-ins into your firefox or chrome browser.  This can be a headache if you are running these commands from a jump host which only has internet access through a tightly controlled proxy.  Luckily, there is a powerful automation tool that comes pre-installed on the vast majority of jump hosts in the world: PowerShell!

I wrote a PowerShell script to configure syslog on my NSX controller nodes using the Invoke-RestMethod cmdlet, which I’ve made public below:

 1# Declare variables
 2$Credentials = Get-Credential # These are the credentials of your NSX Manager
 3$NsxManagerFqdn = "Example.demo.fqdn" # This is the FQDN of your NSX manager
 4$NsxControllers = "controller-1","controller-2","controller-3" # This specifies the ID's of the NSX controllers you wish to configure.
 5$SyslogHost = "Syslog.demo.fqdn" # This is the hostname of the syslog collector.
 7# Start Script
 8# Generate body of the rest method
 9$body = @'
10    <controllerSyslogServer>
11        <syslogServer>$SyslogHost</syslogServer>
12        <port>514</port>
13        <protocol>UDP</protocol>
14        <level>INFO</level>
15    </controllerSyslogServer>
18# Create the header containing authentication credentials - by default Invoke-RestMethod will expect a challenge/response method of authentication (401 response)
19# if using the -Credentials parameter, but NSX manager uses basic authentication which requires authentication immediately.
20$headers = @{ Authorization = "Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $($Credentials.UserName),$($Credentials.GetNetworkCredential().Password)))) }
22foreach ($NsxController in $NsxControllers) {
23    $url = "https://$NsxManagerFqdn/api/2.0/vdn/controller/$NsxController/syslog"
24    Invoke-RestMethod -Method Post -Uri $url -Headers $headers -ContentType "application/xml" -Body $body
27# Run additional loop for reporting purposes.
28foreach ($NsxController in $NsxControllers) {
29    $url = "https://$NsxManagerFqdn/api/2.0/vdn/controller/$NsxController/syslog"
30    $result = Invoke-RestMethod -Method Get -Uri $url -Headers $headers
31    Write-Host "NSX $NsxController is configured with the following syslog server: $($result.controllerSyslogServer.syslogServer)"
34# Wipe credentials
35$Credentials = $null

I hope that most of the code is fairly self-explanatory, but there are a few things I’ll mention.

Firstly, take note of the actual NSX controller ID’s which are being used in your environment.   Although the example in the script assumes NSX controllers 1, 2, and 3, remember that NSX controller ID persist forever, even after a controller node has been decommissioned (or failed to deploy in the first place).

Secondly, I spent a bit of time trying to work out how to best handle the credentials required to authenticate to the NSX managers.  Originally, I needed a quick solution so I simply provided the password as an unsecured string.  This is not ideal, especially since I intended to make this script publicly available for reuse by other people, and after a bit of investigation it turns out you can extract a password in plain text from a PSCredential object. Thus, you don’t need to provide your password in plain text (like by saving it in the script or typing it into the console via Read-Host), as the script will extract the password from the PSCredential to generate the header which is used to authenticate to the NSX Manager.  The script will also wipe the $Credentials variable after it has finished running.

Thirdly, you can edit the $body variable to change things like the port, protocol, or logging level, as required by your environment.

Lastly, it seems that all NSX controllers identify in their syslog messages as NSX-Controller.  This is less than ideal, especially when you might have 10-20 NSX controllers in your environment.  It’s possible to change the hostname of the NSX controller at the command line, but this step isn’t covered in any of the official documentation which makes me wonder if it’s the right approach (as maybe it causes some unintended side effects).  I’m looking into this and will report back when I have a solution.

If anyone wants to recommend some changes, feel free.  One thing I’d like to do is make the script handle multiple NSX Managers, and self-discover the valid NSX controller ID’s, but that’s a a job for another day. Until then, I hope this helps some people out there!

comments powered by Disqus