Get NetScaler License Details

Retrieve NetScaler detailed License file informatio, using the Invoke-RestMethod cmdlet for the REST API calls.
Version 1.0.1
Created on 2018-05-06
Modified on 2018-05-06
Created by Esther Barthel
Downloads: 172

The Script Copy Script Copied to clipboard
function Get-NSLicenseDetails {
    <#
    .SYNOPSIS
      Retrieve NetScaler detailed License file information.
    .DESCRIPTION
      Retrieve NetScaler detailed License file informatio, using the Invoke-RestMethod cmdlet for the REST API calls.
    .NOTES
      Version:        0.1
      Author:         Esther Barthel, MSc
      Creation Date:  2018-02-22
      Purpose:        SBA - Created for ControlUp NetScaler Monitoring
      Credits:        A big shoutout to Ryan Butler (Citrix CTA) for showing me how to retrieve data from the license files of the NetScaler

      Copyright (c) cognition IT. All rights reserved.
      Copyright (c) ControlUp All rights reserved.
    #>

    [CmdletBinding()]
    Param(
      # Declaring the input parameters, provided for the SBA
      [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
      [string]
      $NSIP,
      [Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$true)]
      [string]
      $NSUserName,
      [Parameter(Position=2, Mandatory=$true, ValueFromPipeline=$true)]
      [string]
      $NSUserPW
     )

    #region NITRO settings
        # NITRO Constants
        $ContentType = "application/json"
    #endregion NITRO settings

    #region Credentials
    #    $NSCreds = Get-Credential
    #    $NSUserName = $NSCreds.UserName
    #    $NSUserPW = $NSCreds.GetNetworkCredential().Password
    #endregion Credentials

    Write-Output "------------------------------------------------------------ " #-ForegroundColor Yellow
    Write-Output "| Retrieving License files information from the NetScaler: | " #-ForegroundColor Yellow
    Write-Output "------------------------------------------------------------ " #-ForegroundColor Yellow
    Write-Output ""

    # ----------------------------------------
    # | Method #1: Using the SessionVariable |
    # ----------------------------------------
    #region Start NetScaler NITRO Session
        #Force PowerShell to bypass the CRL check for certificates and SSL connections
            Write-Verbose "Forcing PowerShell to trust all certificates (including the self-signed NetScaler certificate)"
            # source: https://blogs.technet.microsoft.com/bshukla/2010/04/12/ignoring-ssl-trust-in-powershell-system-net-webclient/ 
            [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

        #Connect to NetScaler VPX/MPX
        $Login = ConvertTo-Json @{"login" = @{"username"=$NSUserName;"password"=$NSUserPW}}
        try
        {
            $loginresponse = Invoke-RestMethod -Uri "https://$NSIP/nitro/v1/config/login" -Body $Login -Method POST -SessionVariable NetScalerSession -ContentType $ContentType -Verbose:$VerbosePreference -ErrorAction SilentlyContinue
        }
        Catch [System.Net.WebException]
        {
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Break
        }
        Catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Break
        }
        Catch
        {
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
    #        echo $_.Exception | Format-List -Force
            Break
        }
        Finally
        {
            If ($loginresponse.errorcode -eq 0)
            {
                Write-Verbose "REST API call to login to NS: successful"
            }
        }
    #endregion Start NetScaler NITRO Session

    # ----------------------------------------
    # | Getting NetScaler Time for reference |
    # ----------------------------------------
    #region Get NetScaler System Time
        # Specifying the correct URL 
        $strURI = "https://$NSIP/nitro/v1/config/nsconfig"

        # Method #1: Making the REST API call to the NetScaler
        try
        {
            # start with clean response variable
            $response = $null
            $response = Invoke-RestMethod -Method Get -Uri $strURI -ContentType $ContentType -WebSession $NetScalerSession -Verbose:$VerbosePreference -ErrorAction SilentlyContinue
        }
        catch
        {
            Write-Error ("A " + $_.Exception.GetType().FullName + " error occurred, with message: " + $_.Exception.Message)
            Write-Verbose "Error full details: "
            If ($VerbosePreference -eq "Continue")
            {
                echo $_.Exception | Format-List -Force
            }
        }
        Finally
        {
            If ($response.errorcode -eq 0)
            {
                Write-Verbose "REST API call to retrieve system time: successful"
                If ($response.nsconfig)
                {
                    $referenceDate = Get-Date "1/1/1970"
                    $nsDate = $referenceDate.AddSeconds($response.nsconfig.systemtime)

                    Write-Verbose ("Calculated NS Date: " + $nsDate)
                }
                Else
                {
                    If ($response.errorcode -eq 0)
                    {
                        Write-Output ""
                        Write-Output "No system time was found."
                    }
                    Else
                    {
                        Write-Error ("errorcode: " + $response.errorcode + ", message: " + $response.message)
                    }
                }
            }
        }
    #endregion

    #region Get NetScaler License Server Type
        # Specifying the correct URL 
        $strURI = "https://$NSIP/nitro/v1/config/nslicense"

        # Method #1: Making the REST API call to the NetScaler
        try
        {
            # start with clean response variable
            $response = $null
            $response = Invoke-RestMethod -Method Get -Uri $strURI -ContentType $ContentType -WebSession $NetScalerSession -Verbose:$VerbosePreference -ErrorAction SilentlyContinue
        }
        catch
        {
            Write-Error ("A " + $_.Exception.GetType().FullName + " error occurred, with message: " + $_.Exception.Message)
            Write-Verbose "Error full details: "
            If ($VerbosePreference -eq "Continue")
            {
                echo $_.Exception | Format-List -Force
            }
        }
        Finally
        {
            If ($response.errorcode -eq 0)
            {
                Write-Verbose "REST API call to retrieve NS license information: successful"
                If ($response.nslicense)
                {
                    $licensingMode = $response.nslicense.licensingmode
                    #Write-Host ("licensing mode: " + $licensingMode) -ForegroundColor Yellow
                    If (($licensingMode -eq "Pooled") -or ($licensingMode -eq "CICO"))
                    {
                        # retrieve license server information
                        Write-Output "This NetScaler is using a license server"

                        #region Retrieve License Server information
                            # Specifying the correct URL 
                            $strURI = "https://$NSIP/nitro/v1/config/nslicenseserver"

                            # Method #1: Making the REST API call to the NetScaler
                            try
                            {
                                # start with clean response variable
                                $response = $null
                                $response = Invoke-RestMethod -Method Get -Uri $strURI -ContentType $ContentType -WebSession $NetScalerSession -Verbose:$VerbosePreference -ErrorAction SilentlyContinue
                            }
                            catch
                            {
                                Write-Error ("A " + $_.Exception.GetType().FullName + " error occurred, with message: " + $_.Exception.Message)
                                Write-Verbose "Error full details: "
                                If ($VerbosePreference -eq "Continue")
                                {
                                    echo $_.Exception | Format-List -Force
                                }
                            }
                            Finally
                            {
                                #$response.nslicenseserver | Format-List
                                $response.nslicenseserver | Select-Object @{N='Server Name'; E={$_.servername}}, 
                                                                    @{N='IP address'; E={$_.licenseserverip}}, 
                                                                    @{N='Port'; E={$_.port}}, 
                                                                    @{N='Status'; E={$_.status}}, 
                                                                    @{N='Grace status'; E={$_.grace}}, 
                                                                    @{N='Grace time left'; E={$_.gptimeleft}} | Format-List

                            }
                        
                        #endregion

                    }
                    If ($licensingMode -eq "Local")
                    {
                        Write-Output "This NetScaler is using a local license file."
                        #region Get License File(s) information

                            # Specifying the correct URL 
                            $strURI = ("https://$NSIP/nitro/v1/config/systemfile?args=filelocation:" + [System.Web.HttpUtility]::UrlEncode("/nsconfig/license"))

                            # Method #1: Making the REST API call to the NetScaler
                            try
                            {
                                # start with clean response variable
                                $responseFiles = $null
                                $responseFiles = Invoke-RestMethod -Method Get -Uri $strURI -ContentType $ContentType -WebSession $NetScalerSession -Verbose:$VerbosePreference -ErrorAction SilentlyContinue
                            }
                            catch
                            {
                                Write-Error ("A " + $_.Exception.GetType().FullName + " error occurred, with message: " + $_.Exception.Message)
                                Write-Verbose "Error full details: "
                                If ($VerbosePreference -eq "Continue")
                                {
                                    echo $_.Exception | Format-List -Force
                                }
                            }
                            Finally
                            {
                                If ($responseFiles.errorcode -eq 0)
                                {
                                    Write-Verbose "REST API call to retrieve all NetScaler system files in ""\nsconfig\license\"": successful"
                                    If ($responseFiles.systemfile.Count -gt 0)
                                    {
                                        [array]$licFiles = $responseFiles.systemfile | Where-Object {$_.filename -like "*.lic"}

                                        # Show how many license files were found
                                        Write-Output ""
                                        Write-Output ($licFiles.Count.ToString() + " license file(s) found in \nsconfig\license.")

                                        foreach ($licFile in $licFiles)
                                        {
                                            Write-Output ""
                                            Write-Output ("* License File: " + $licFile.filename)
                    
                                            # Specifying the correct URL (to retrieve the license file details)
                                            $strURI = ("https://$NSIP/nitro/v1/config/systemfile?args=filename:" + [System.Web.HttpUtility]::UrlEncode($licFile.filename) + ",filelocation:" + [System.Web.HttpUtility]::UrlEncode("/nsconfig/license")) 
                    
                                            # Method #1: Making the REST API call to the NetScaler
                                            try
                                            {
                                                # start with clean response variable
                                                $responseFile = $null
                                                $responseFile = Invoke-RestMethod -Method Get -Uri $strURI -ContentType $ContentType -WebSession $NetScalerSession -Verbose:$VerbosePreference #-ErrorAction SilentlyContinue
                                            }
                                            catch
                                            {
                                                Write-Error ("A " + $_.Exception.GetType().FullName + " error occurred, with message: " + $_.Exception.Message)
                                                Write-Verbose "Error full details: "
                                                If ($VerbosePreference -eq "Continue")
                                                {
                                                    echo $_.Exception | Format-List -Force
                                                }
                                            }
                                            Finally
                                            {
                                                $results = @()
                                                $featresults = @()
                                                #Get actual file content
                                                If ($responseFile.systemfile.fileencoding -eq "BASE64")
                                                {
                                                    # Get license file content
                                                    $FileContent = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($responseFile.systemfile.filecontent))
                                                }
                                                Else
                                                {
                                                    Throw ("Fileencoding " + $responseFile.systemfile.fileencoding + " unknown")
                                                }
                        
                                                #Process File Content
                                                #Grabs needed line that has licensing information
                                                $licLines = $FileContent.Split("`n")|where-object{$_ -like "*INCREMENT*"}
                                                $licdates = @()

                                                # Process the ecpire date
                                                foreach ($line in $licLines)
                                                {
                                                    $licdate = $line.Split()
    
                                                    if ($licdate[4] -like "permanent")
                                                    {
                                                        $expire = "PERMANENT"
                                                    }
                                                    else
                                                    {
                                                        $expire = [datetime]$licdate[4]
                                                    }
    
                                                    #adds date to object
                                                    $temp = New-Object PSObject -Property @{
                                                                expdate = $expire
                                                                feature = $licdate[1]
                                                                }
                                                    $licdates += $temp
                                                }

                                                # Get Feature descriptions from License File
                                                $featLines = $FileContent.Split("`n")|where-object{$_ -like "#CITRIXTERM*`tEN`t*"}
                                                foreach ($featLine in $featLines)
                                                {
                                                    $feat = $featLine.Split("`t",4)
                                                        # test[1] = feature name
                                                        # test[3] = feature description
                                                    $feattemp = New-Object PSObject -Property @{
                                                        LicenseFile = $licFile.filename
                                                        Feature = $feat[1]
                                                        Description = $feat[3]
                                                    }
                                                    $featresults += $feattemp
                                                }

                                                # Get License file information
                                                foreach ($date in $licdates)
                                                {
                                                    if ($date.expdate -like "PERMANENT")
                                                    {
                                                        $expires = "PERMANENT"
                                                        $span = "9999"
                                                    }
                                                    else
                                                    {
                                                        $expires = ($date.expdate).ToShortDateString()
                                                        $span = (New-TimeSpan -Start $nsDate -end ($date.expdate)).days
                                                    }
    
                                                    $temp = New-Object PSObject -Property @{
                                                        Expires = $expires
                                                        Feature = $date.feature
                                                        Description = ($featresults | Where-Object {($_.LicenseFile -eq $licFile.filename) -and ($_.Feature -eq $date.feature)}).Description # 
                                                        DaysLeft = $span
                                                        LicenseFile = $licFile.filename
                                                        ModifiedTime = $licFile.filemodifiedtime
                                                    }
                                                    # Link License Expire Date for each type to License description for each type
                                                    $results += $temp    
                                                }    
                                            $results | Select-Object Feature, @{N='Expire Date'; E={$_.Expires}}, DaysLeft, Description| Format-Table  # ModifiedTime, Expires not shown in results
                                            }
                                        }
                                    }
                                    Else
                                    {
                                        If ($response.errorcode -eq 0)
                                        {
                                            Write-Output ""
                                            Write-Warning "No license file(s) were found."
                                        }
                                        Else
                                        {
                                            Write-Error ("errorcode: " + $response.errorcode + ", message: " + $response.message)
                                        }
                                    }
                                }
                                Else
                                {
                                    Write-Warning "An error occured. (""errorcode: " + $response.errorcode + ", message: " + $response.message + """)"
                                }
                            }
                        #endregion

                    }
                }
                Else
                {
                    If ($response.errorcode -eq 0)
                    {
                        Write-Output ""
                        Write-Output "No license information was found."
                    }
                    Else
                    {
                        Write-Error ("errorcode: " + $response.errorcode + ", message: " + $response.message)
                    }
                }
            }
        }
    #endregion




    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler VPX
        $LogOut = @{"logout" = @{}} | ConvertTo-Json
        $dummy = Invoke-RestMethod -Uri "https://$NSIP/nitro/v1/config/logout" -Body $LogOut -Method POST -ContentType $ContentType -WebSession $NetScalerSession -Verbose:$VerbosePreference -ErrorAction SilentlyContinue
    #endregion End NetScaler NITRO Session
}

# Altering the size of the PS Buffer
$PSWindow = (Get-Host).UI.RawUI
$WideDimensions = $PSWindow.BufferSize
$WideDimensions.Width = 400
$PSWindow.BufferSize = $WideDimensions

try {
    Get-NSLicenseDetails -NSIP $args[0] -NSUserName $args[1] -NSUserPW $args[2]
}
catch [System.Management.Automation.ParameterBindingException] {
    Write-Error "Couldn't bind parameter exception, Please make sure to provide all necessary parameters"
}