Check for Citrix ADC CVE-2019-19781 Vulnerability mitigation

this Script Action checks if the suggested mitigation responder policy is configured and globally bound on the Citrix ADC or Citrix Gateway appliance as described in Citrix knowledgebase article CTX267679 (https://support.citrix.com/article/CTX267679).

Note: This Script Action does not perform the suggested mitigation for the management interfaces as it may break administration access.
Version 2.2.9
Created on 2020-01-01
Modified on 2020-01-08
Created by ebarthel
Downloads: 304

The Script Copy Script Copied to clipboard
<#
.SYNOPSIS
    Check for the Citrix ADC and Gateway mitigation steps for CVE-2019-19781.
.DESCRIPTION
    Check for the Citrix ADC and Gateway mitigation steps for CVE-2019-19781, using NITRO.
.EXAMPLE
    Check-CVE-2019-19781-Mitigation -NSIP 192.168.0.101 -ApplyMitigation Yes 
.CONTEXT
    NetScalers
.MODIFICATION_HISTORY
    Esther Barthel, MSc - 28/12/19 - Original code
    Esther Barthel, MSc - 28/12/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    Esther Barthel, MSc - 08/01/20 - Adjusted the filter to account for additional spaces in the Responder Policy Expression to prevent false negatives.
.LINK
    https://support.citrix.com/article/CTX267679
.NOTES
    Version:        0.5
    Author:         Esther Barthel, MSc
    Creation Date:  2019-12-28
    Updated:        2019-12-28
                    Standardized the function, based on the ControlUp Standards (v0.2)
                    2019-12-31
                    Fixed multiple authentication popups
                    2020-01-08
                    Adjusted the filter to account for additional spaces in the Responder Policy Expression to prevent false negatives.

    Purpose:        Script Action, created for ControlUp Citrix ADC Management
        
    Copyright (c) cognition IT. All rights reserved.
#>

function Get-CUStoredCredential {
    param (
        [parameter(Mandatory = $true,
            HelpMessage = "The system the credentials will be used for.")]
        [string]$System
    )

    # Get the stored credential object
    $strCUCredFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
    
    try {
        Import-Clixml $strCUCredFolder\$($env:USERNAME)_$($System)_Cred.xml
    }
    catch {
        Write-Error ("The required PSCredential object could not be loaded. " + $_)
    }
}

function Get-ADCCredentials()
{
    <#
    .SYNOPSIS
        Retrieve the Citrix ADC Credentials.
    .DESCRIPTION
        Retrieve the Citrix ADC Credentials from either a stored credentials file or Get-Credential popup.
    .EXAMPLE
        Get-ADCCredentials
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 31/12/19 - Original code
        Esther Barthel, MSc - 31/12/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-31
        Updated:        2019-12-31
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param()

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # Declare ADC Credentials object
        [System.Management.Automation.PSCredential]$adcCredentials = $null
    #endregion

    Write-Verbose ""
    Write-Verbose "------------------------ "
    Write-Verbose "| Get ADC Credentials: | "
    Write-Verbose "------------------------ "
    Write-Verbose ""

    #region Load ADC Credentials either trough XML file import or Get-Credentials
        # Check for Stored Credentials
        If (Test-Path -Path $credTarget)
        # Stored credentials found, import credentials
        {
            try
            {
                $adcCredentials = Get-CUStoredCredential -System $systemName
            }
            catch
            {
                Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
                Exit
            }
            Write-Verbose "* ADC Credentials: Stored $systemName credentials XML file found. ADC credentials imported for Automated Action support."
        }
        Else
        # No Stored Credentials Found, ask for credentials
        {
            Write-Verbose "* ADC Credentials: Stored $systemName credentials XML file NOT found, using Get-Credential to retrieve ADC credentials."
            $adcCredentials = Get-Credential -Message "Enter your credentials for Citrix ADC $NSIP"
        }
    #endregion

    # Return the ADC Credentials (PSCredential object) for future use in the NITRO functions
    If (!($adcCredentials -eq $null))
    {
        Write-Verbose "* ADC Credentials: credentials returned."
        return $adcCredentials
    }
    Else
    {
        Write-Verbose "* ADC Credentials: NO credentials returned."
        Write-Error "No ADC Credentials retrieved, cannot perform NITRO actions."
        Exit
    }
}






function Get-ADCResponderPolicy ()
{
    <#
    .SYNOPSIS
        Retrieve the Citrix ADC configured Responder Policies.
    .DESCRIPTION
        Retrieve the Citrix ADC configured Responder Policies.
    .EXAMPLE
        Get-ADCRunningConfig -NSIP 192.168.0.101
    .EXAMPLE
        Get-ADCRunningConfig -NSIP 192.168.0.101 -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/ns/nsrunningconfig/nsrunningconfig/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$false, 
            HelpMessage='Specify the filter string if applicable'
        )]
        [string] $Filter,

        [Parameter(
            Position=2, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "------------------------------------------------- "
    Write-Verbose "| Get Citrix ADC Responder policies with NITRO: | "
    Write-Verbose "------------------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # --------------------------
    # | Get Responder policies |
    # --------------------------
    #region Get responderpolicy
        # start with clean response variable
        $adcResponderPolicy = $null
            
        # Create the Invoke-RestMethod params
        If ($Filter)
        {
            $uri = "https://$NSIP/nitro/v1/config/responderpolicy?filter=" + [System.Web.HttpUtility]::UrlEncode($Filter)
        }
        else
        {
            $uri = "https://$NSIP/nitro/v1/config/responderpolicy"
        }

        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "GET"
                WebSession  = $NSSession
                ContentType = $ContentType
            }
            $adcResponderPolicy = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }

        If ( -not ($adcResponderPolicy.errorcode -eq 0))
        # NITRO errorcode found (or results is empty)
        {
            Write-Error "NITRO: errorcode (" + $adcResponderPolicy.errorcode + ") " + $adcResponderPolicy.message + "."
            Exit
        }

        Write-Verbose "* NITRO: responder policies retrieved successful"
        if ($adcResponderPolicy.responderpolicy)
        {
            $results = $adcResponderPolicy.responderpolicy
            return $results
        }
        else
        {
            Write-Warning "No responder policies found."
        }
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}

function Get-ADCResponderPolicyBinding ()
{
    <#
    .SYNOPSIS
        Retrieve the Citrix ADC configured Responder Policy bindings.
    .DESCRIPTION
        Retrieve the Citrix ADC configured Responder Policy bindings.
    .EXAMPLE
        Get-ADCResponderPolicyBinding -NSIP 192.168.0.101
    .EXAMPLE
        Get-ADCResponderPolicyBinding -NSIP 192.168.0.101 -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/responder/responderpolicy_binding/responderpolicy_binding/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$false, 
            HelpMessage='Specify the policy name to retrieve bindings for'
        )]
        [string] $PolicyName,

        [Parameter(
            Position=2, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "-------------------------------------------------------- "
    Write-Verbose "| Get Citrix ADC Responder Policy Bindings with NITRO: | "
    Write-Verbose "-------------------------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ---------------------------------
    # | Get Responder Policy Bindings |
    # ---------------------------------
    #region Get responderpolicy_binding
        # start with clean response variable
        $adcResponderPolicyBinding = $null
            
        # Create the Invoke-RestMethod params
        If ($PolicyName)
        {
            # get
            $uri = "https://$NSIP/nitro/v1/config/responderpolicy_binding/" + $PolicyName
        }
        else
        {
            # get all)
            $uri = "https://$NSIP/nitro/v1/config/responderpolicy_binding?bulkbindings=yes"
        }

        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "GET"
                WebSession  = $NSSession
                ContentType = $ContentType
            }
            $adcResponderPolicyBinding = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }

        If ( -not ($adcResponderPolicyBinding.errorcode -eq 0))
        # NITRO errorcode found (or results is empty)
        {
            Write-Error "NITRO: errorcode (" + $adcResponderPolicyBinding.errorcode + ") " + $adcResponderPolicyBinding.message + "."
            Exit
        }

        Write-Verbose "* NITRO: responder policy responder global bindings retrieved successful"
        if ($adcResponderPolicyBinding.responderpolicy_binding)
        {
            $results = $adcResponderPolicyBinding.responderpolicy_binding
            return $results
        }
        else
        {
            Write-Warning "No responder policy responder global bindings found."
        }
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}


function Enable-ADCFeature ()
{
    <#
    .SYNOPSIS
        Enable the provided Citrix ADC feature(s).
    .DESCRIPTION
        Enable the provided Citrix ADC feature(s), using REST API.
    .EXAMPLE
        Enable-ADCFeature -NSIP 192.168.0.101 -Features
    .EXAMPLE
        Enable-ADCFeature -NSIP 192.168.0.101 -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/responder/responderpolicy_binding/responderpolicy_binding/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$true, 
            HelpMessage='Feature to be enabled. Multiple features can be specified by providing a blank space between each feature.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $Feature,

        [Parameter(
            Position=2, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "-------------------------------------------------------- "
    Write-Verbose "| Get Citrix ADC Responder Policy Bindings with NITRO: | "
    Write-Verbose "-------------------------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ---------------------
    # | Enable NS Feature |
    # ---------------------
    #region Enable nsfeature
        # start with clean response variable
        $adcFeature = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/nsfeature?action=enable"

        # json payload
        $jsonPayload = ConvertTo-Json @{
            "nsfeature"=@{
                "feature"=@($($Feature));
                }
        } -Depth 5

        Write-Verbose ("json payload: " + $jsonPayload)
        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "POST"
                WebSession  = $NSSession
                ContentType = $ContentType
                Body        = $jsonPayload
            }
            $adcFeature = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}


function New-ADCResponderAction ()
{
    <#
    .SYNOPSIS
        Add Citrix ADC Responder Action.
    .DESCRIPTION
        Add Citrix ADC Responder Action, using REST API.
    .EXAMPLE
        New-ADCResponderAction -NSIP 192.168.0.101 -Name <name> -Type <type> -Target <target> -Comment <comment> -ResponseStatusCode <responsestatuscode> -ReasonPhrase <reasonphrase>
    .EXAMPLE
        New-ADCResponderAction -NSIP 192.168.0.101 -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/responder/responderpolicy_binding/responderpolicy_binding/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$true, 
            HelpMessage='Name for the responder action.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $Name,

        [Parameter(
            Position=2, 
            Mandatory=$true, 
            HelpMessage='Type of responder action.'
        )]
        [ValidateSet("noop", "respondwith", "redirect", "respondwithhtmlpage", "sqlresponse_ok", "sqlresponse_error")]
        [string] $Type,

        [Parameter(
            Position=3, 
            Mandatory=$true, 
            HelpMessage='Expression specifying what to respond with. Typically a URL for redirect policies or a default-syntax expression.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $Target,

        [Parameter(
            Position=4, 
            Mandatory=$false, 
            HelpMessage='Comment.'
        )]
        [string] $Comment,

        [Parameter(
            Position=5, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "----------------------------------------------- "
    Write-Verbose "| Add Citrix ADC Responder Action with NITRO: | "
    Write-Verbose "----------------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ------------------------
    # | Add Responder Action |
    # ------------------------
    #region responderaction
        # start with clean response variable
        $adcResponderAction = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/responderaction"

        # json payload
        $jsonPayload = ConvertTo-Json @{
            "responderaction"=@{
                "name"=$Name;
                "type"=$Type;
                "target"=$Target;
                "comment"=$Comment;
                }
        } -Depth 5

        Write-Verbose ("json payload: " + $jsonPayload)
        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "POST"
                WebSession  = $NSSession
                ContentType = $ContentType
                Body        = $jsonPayload
            }
            $adcResponderAction = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }

        Write-Verbose "* NITRO: responder action created successful"
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}

function New-ADCResponderPolicy ()
{
    <#
    .SYNOPSIS
        Add Citrix ADC Responder Policy.
    .DESCRIPTION
        Add Citrix ADC Responder Policy, using REST API.
    .EXAMPLE
        New-ADCResponderPolicy -NSIP 192.168.0.101 -Name <name> -Rule <rule> -Action <action> -Comment <comment>
    .EXAMPLE
        New-ADCResponderPolicy -NSIP 192.168.0.101 -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/responder/responderpolicy_binding/responderpolicy_binding/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$true, 
            HelpMessage='Name for the responder policy.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $Name,

        [Parameter(
            Position=2, 
            Mandatory=$true, 
            HelpMessage='Expression specifying what to respond with. Typically a URL for redirect policies or a default-syntax expression.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $Rule,

        [Parameter(
            Position=3, 
            Mandatory=$true, 
            HelpMessage='Name of the responder action to perform if the request matches this responder policy.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $Action,

        [Parameter(
            Position=4, 
            Mandatory=$false, 
            HelpMessage='Comment.'
        )]
        [string] $Comment,

        [Parameter(
            Position=5, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "----------------------------------------------- "
    Write-Verbose "| Add Citrix ADC Responder Policy with NITRO: | "
    Write-Verbose "----------------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ------------------------
    # | Add Responder Action |
    # ------------------------
    #region responderpolicy
        # start with clean response variable
        $adcResponderPolicy = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/responderpolicy"

        # json payload
        $jsonPayload = ConvertTo-Json @{
            "responderpolicy"=@{
                "name"=$Name;
                "rule"=$Rule;
                "action"=$Action;
                "comment"=$Comment;
                }
        } -Depth 5

        Write-Verbose ("json payload: " + $jsonPayload)
        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "POST"
                WebSession  = $NSSession
                ContentType = $ContentType
                Body        = $jsonPayload
            }
            $adcResponderPolicy = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }

        Write-Verbose "* NITRO: responder policy created successful"
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}

function New-ADCResponderGlobalResponderPolicyBinding ()
{
    <#
    .SYNOPSIS
        Add Citrix ADC Responder Global Responder Policy Binding.
    .DESCRIPTION
        Add Citrix ADC Responder Global Responder Policy Binding, using REST API.
    .EXAMPLE
        New-ADCResponderGlobalResponderPolicyBinding -NSIP 192.168.0.101 -PolicyName <policyname> -Priority <prio> -GoToPriorityExpression <gotopriorityexpression> -Type <type>
    .EXAMPLE
        New-ADCResponderGlobalResponderPolicyBinding -NSIP 192.168.0.101 -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/responder/responderpolicy_binding/responderpolicy_binding/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$true, 
            HelpMessage='Name of the responder policy.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $PolicyName,

        [Parameter(
            Position=2, 
            Mandatory=$true, 
            HelpMessage='Specifies the priority of the policy.'
        )]
        [ValidateNotNullorEmpty()]
        [int] $Priority,

        [Parameter(
            Position=3, 
            Mandatory=$false, 
            HelpMessage='Expression specifying the priority of the next policy which will get evaluated if the current policy rule evaluates to TRUE.'
        )]
        [string] $GoToPriorityExpression,

        [Parameter(
            Position=4, 
            Mandatory=$false, 
            HelpMessage='Specifies the bind point whose policies you want to display.'
        )]
        [ValidateSet("REQ_OVERRIDE", "REQ_DEFAULT", "OVERRIDE", "DEFAULT", "OTHERTCP_REQ_OVERRIDE", "OTHERTCP_REQ_DEFAULT", "SIPUDP_REQ_OVERRIDE", "SIPUDP_REQ_DEFAULT", "SIPTCP_REQ_OVERRIDE", "SIPTCP_REQ_DEFAULT", "MSSQL_REQ_OVERRIDE", "MSSQL_REQ_DEFAULT", "MYSQL_REQ_OVERRIDE", "MYSQL_REQ_DEFAULT", "NAT_REQ_OVERRIDE", "NAT_REQ_DEFAULT", "DIAMETER_REQ_OVERRIDE", "DIAMETER_REQ_DEFAULT", "RADIUS_REQ_OVERRIDE", "RADIUS_REQ_DEFAULT", "DNS_REQ_OVERRIDE", "DNS_REQ_DEFAULT")]
        [string] $Type,

        [Parameter(
            Position=5, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "-------------------------------------------------------------- "
    Write-Verbose "| Add Citrix ADC Responder Policy Global Binding with NITRO: | "
    Write-Verbose "-------------------------------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ---------------------------------------
    # | Add Responder Policy Global Binding |
    # ---------------------------------------
    #region responderglobal_responderpolicy_binding
        # start with clean response variable
        $adcResponderGlobalBinding = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/responderglobal_responderpolicy_binding"

        # json payload
        $jsonPayload = ConvertTo-Json @{
            "responderglobal_responderpolicy_binding"=@{
                "policyname"=$PolicyName;
                "priority"=$Priority;
                "gotopriorityexpression"=$GoToPriorityExpression;
                "type"=$Type;
                }
        } -Depth 5

        Write-Verbose ("json payload: " + $jsonPayload)
        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "PUT"
                WebSession  = $NSSession
                ContentType = $ContentType
                Body        = $jsonPayload
            }
            $adcResponderGlobalBinding = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }

        Write-Verbose "* NITRO: responder policy global binding created successful"
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}



function Get-ADCSystemfile ()
{
    <#
    .SYNOPSIS
        Retrieve a system file from the Citrix ADC.
    .DESCRIPTION
        Retrieve a system file from the Citrix ADC, using REST API.
    .EXAMPLE
        Get-ADCSystemfile -NSIP 192.168.0.101 -FileName <filename> -FileLocation <filelocation>
    .EXAMPLE
        Get-ADCSystemfile -NSIP 192.168.0.101 -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/system/systemfile/systemfile/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$true, 
            HelpMessage='Name of the file. It should not include filepath.'
        )]
        [string] $FileName,

        [Parameter(
            Position=2, 
            Mandatory=$true, 
            HelpMessage='Location of the file on NetScaler.'
        )]
        [string] $FileLocation,

        [Parameter(
            Position=3, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "----------------------------------------- "
    Write-Verbose "| Get Citrix ADC systemfile with NITRO: | "
    Write-Verbose "----------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ------------------
    # | Get systemfile |
    # ------------------
    #region Get systemfile
        # start with clean response variable
        $adcSystemfile = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/systemfile?args=filename:" + [System.Web.HttpUtility]::UrlEncode($FileName) + ",filelocation:" + [System.Web.HttpUtility]::UrlEncode($FileLocation)

        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "GET"
                WebSession  = $NSSession
                ContentType = $ContentType
            }
            $adcSystemfile = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }

        If ( -not ($adcSystemfile.errorcode -eq 0))
        # NITRO errorcode found (or results is empty)
        {
            Write-Error "NITRO: errorcode (" + $adcSystemfile.errorcode + ") " + $adcSystemfile.message + "."
            Exit
        }

        Write-Verbose "* NITRO: responder policies retrieved successful"
        if ($adcSystemfile.systemfile)
        {
            $results = $adcSystemfile.systemfile
            return $results
        }
        else
        {
            Write-Warning "No systemfile found."
        }
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}



function Invoke-ADCSaveConfig ()
{
    <#
    .SYNOPSIS
        Save the Citrix ADC configuration.
    .DESCRIPTION
        Save the Citrix ADC configuration, using REST API.
    .EXAMPLE
        Invoke-ADCSaveConfig -NSIP 192.168.0.101 
    .EXAMPLE
        Invoke-ADCSaveConfig -NSIP 192.168.0.101 -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/system/systemfile/systemfile/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "-------------------------------------- "
    Write-Verbose "| Save Citrix ADC config with NITRO: | "
    Write-Verbose "-------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # -----------------
    # | Post nsconfig |
    # -----------------
    #region Post nsconfig
        # start with clean response variable
        $adcSaveConfig = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/nsconfig?action=save"

        #JSON payload
        $jsonPayload = ConvertTo-Json @{"nsconfig" = @{}}

        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "POST"
                WebSession  = $NSSession
                ContentType = $ContentType
                Body        = $jsonPayload
            }
            $adcSaveConfig = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }
        Write-Verbose "Citrix ADC configuration saved."

    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}

function Invoke-ADCReboot ()
{
    <#
    .SYNOPSIS
        Reboot the Citrix ADC.
    .DESCRIPTION
        Reboot the Citrix ADC, using REST API.
    .EXAMPLE
        Invoke-ADCReboot -NSIP 192.168.0.101 -Warm "false"
    .EXAMPLE
        Invoke-ADCSaveConfig -NSIP 192.168.0.101 -Warm "true" -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/system/systemfile/systemfile/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$true, 
            HelpMessage='Restarts the NetScaler software without rebooting the underlying operating system. The session terminates and you must log on to the appliance after it has restarted.'
        )]
        [ValidateSet("false","true")]
        [string] $Warm,
            
        [Parameter(
            Position=2, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "--------------------------------- "
    Write-Verbose "| Reboot Citrix ADC with NITRO: | "
    Write-Verbose "--------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ---------------------
    # | Reboot Citrix ADC |
    # ---------------------
    #region Reboot Citrix ADC
        # start with clean response variable
        $adcReboot = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/reboot"

        #JSON payload
        $jsonPayload = ConvertTo-Json @{"reboot" = @{"warm"=$Warm}}

        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "POST"
                WebSession  = $NSSession
                ContentType = $ContentType
                Body        = $jsonPayload
            }
            $adcReboot = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }
        Write-Verbose "Citrix ADC rebooted."

    #endregion
}


function Remove-ADCResponderGlobalResponderPolicyBinding ()
{
    <#
    .SYNOPSIS
        Remove Citrix ADC Responder Global Responder Policy Binding.
    .DESCRIPTION
        Remove Citrix ADC Responder Global Responder Policy Binding, using REST API.
    .EXAMPLE
        Remove-ADCResponderGlobalResponderPolicyBinding -NSIP 192.168.0.101 -PolicyName <policyname>
    .EXAMPLE
        Remove-ADCResponderGlobalResponderPolicyBinding -NSIP 192.168.0.101 -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/responder/responderpolicy_binding/responderpolicy_binding/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$true, 
            HelpMessage='Name of the responder policy.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $PolicyName,

        [Parameter(
            Position=2, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "----------------------------------------------------------------- "
    Write-Verbose "| Remove Citrix ADC Responder Policy Global Binding with NITRO: | "
    Write-Verbose "----------------------------------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ------------------------------------------
    # | Remove Responder Policy Global Binding |
    # ------------------------------------------
    #region responderglobal_responderpolicy_binding
        # start with clean response variable
        $adcResponderGlobalBinding = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/responderglobal_responderpolicy_binding?args=policyname:" + [System.Web.HttpUtility]::UrlEncode($PolicyName)

        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "DELETE"
                WebSession  = $NSSession
                ContentType = $ContentType
            }
            $adcResponderGlobalBinding = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }

        If ( -not ($adcResponderGlobalBinding.errorcode -eq 0))
        # NITRO errorcode found (or results is empty)
        {
            Write-Error ("NITRO: errorcode (" + $adcResponderPolicyBinding.errorcode + ") " + $adcResponderPolicyBinding.message + ".")
            Exit
        }
        Write-Verbose "* NITRO: responder policy responder global bindings removed successful"
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}

function Remove-ADCResponderPolicy ()
{
    <#
    .SYNOPSIS
        Remove Citrix ADC Responder Policy.
    .DESCRIPTION
        Remove Citrix ADC Responder Policy, using REST API.
    .EXAMPLE
        Remove-ADCResponderPolicy -NSIP 192.168.0.101 -Name <name>
    .EXAMPLE
        Remove-ADCResponderPolicy -NSIP 192.168.0.101 -Name <name> -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/responder/responderpolicy_binding/responderpolicy_binding/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.1
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$true, 
            HelpMessage='Name for the responder policy.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $Name,

        [Parameter(
            Position=2, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "-------------------------------------------------- "
    Write-Verbose "| Remove Citrix ADC Responder Policy with NITRO: | "
    Write-Verbose "-------------------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ---------------------------
    # | Remove Responder Policy |
    # ---------------------------
    #region responderpolicy
        # start with clean response variable
        $adcResponderPolicy = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/responderpolicy/" + [System.Web.HttpUtility]::UrlEncode($Name)

        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "DELETE"
                WebSession  = $NSSession
                ContentType = $ContentType
            }
            $adcResponderPolicy = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }

        If ( -not ($adcResponderPolicy.errorcode -eq 0))
        # NITRO errorcode found (or results is empty)
        {
            Write-Error ("NITRO: errorcode (" + $adcResponderPolicy.errorcode + ") " + $adcResponderPolicy.message + ".")
            Exit
        }
        Write-Verbose "* NITRO: responder policy removed successful"
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}

function Remove-ADCResponderAction ()
{
    <#
    .SYNOPSIS
        Remove Citrix ADC Responder Action.
    .DESCRIPTION
        Remove Citrix ADC Responder Action, using REST API.
    .EXAMPLE
        Remove-ADCResponderAction -NSIP 192.168.0.101 -Name <name>
    .EXAMPLE
        Remove-ADCResponderAction -NSIP 192.168.0.101 -Name <name> -NSCredentials $PSCredentialsObject
    .CONTEXT
        NetScalers
    .MODIFICATION_HISTORY
        Esther Barthel, MSc - 30/09/19 - Original code
        Esther Barthel, MSc - 30/09/19 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2)
    .LINK
        https://developer-docs.citrix.com/projects/netscaler-nitro-api/en/12.0/configuration/responder/responderpolicy_binding/responderpolicy_binding/
    .COMPONENT
        Get-CUStoredCredential - to retreive the XML Credentials file for non-interactive/automated use of this script
    .NOTES
        Version:        0.2
        Author:         Esther Barthel, MSc
        Creation Date:  2019-12-28
        Updated:        2019-12-28
                        Standardized the function, based on the ControlUp Standards (v0.2)
                        2020-01-08
                        Adjusted the filter to account for additional spaces in the Responder Policy Expression to prevent false negatives.
        Purpose:        Script Action, created for ControlUp NetScaler Monitoring
        
        Copyright (c) cognition IT. All rights reserved.
    #>
    [CmdletBinding()]
    Param
    (
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            HelpMessage='Enter the Citrix ADC IP address to run the script on'
        )]
        [ValidateScript({$_ -match [IPAddress]$_ })]
        [string] $NSIP,
            
        [Parameter(
            Position=1, 
            Mandatory=$true, 
            HelpMessage='Name for the responder action.'
        )]
        [ValidateNotNullorEmpty()]
        [string] $Name,

        [Parameter(
            Position=2, 
            Mandatory=$false, 
            HelpMessage='Enter a PSCredential object, containing the username and password'
        )]
        [System.Management.Automation.CredentialAttribute()] $ADCCredentials
    )    

    #region ControlUp Script Standards - version 0.2
        #Requires -Version 3.0

        # Configure a larger output width for the ControlUp PowerShell console
        [int]$outputWidth = 400
        # Altering the size of the PS Buffer
        $PSWindow = (Get-Host).UI.RawUI
        $WideDimensions = $PSWindow.BufferSize
        $WideDimensions.Width = $outputWidth
        $PSWindow.BufferSize = $WideDimensions

        # Ensure Debug information is shown, without the confirmation question after each Write-Debug
        If ($PSBoundParameters['Debug']) {$DebugPreference = "Continue"}
        If ($PSBoundParameters['Verbose']) {$VerbosePreference = "Continue"}
        $ErrorActionPreference = "Stop"
    #endregion

    #region script settings
        # Stored ADC Credentials XML file
        $systemName = "ADC"
        $credTargetFolder = "$([environment]::GetFolderPath('CommonApplicationData'))\ControlUp\ScriptSupport"
        $credTarget = "$credTargetFolder\$($Env:Username)_$($systemName)_Cred.xml"
        # NITRO Constants
        $ContentType = "application/json"
        # turn Verbose mode on
        #$VerbosePreference = "Continue"
        # turn Verbose mode off
        #$VerbosePreference="SilentlyContinue"
    #endregion

    Write-Verbose ""
    Write-Verbose "-------------------------------------------------- "
    Write-Verbose "| Remove Citrix ADC Responder Action with NITRO: | "
    Write-Verbose "-------------------------------------------------- "
    Write-Verbose ""

    #region Load NSCredentials either trough XML file import or Get-Credentials
    If ($null -eq $ADCCredentials)
    {
        $ADCCredentials = Get-ADCCredentials
    }
    #endregion

    # Retieving username and password from PSCredentials for use with NITRO
    $NSUserName = $ADCCredentials.UserName
    $NSUserPW = $ADCCredentials.GetNetworkCredential().Password

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

        #JSON payload
        $LoginJSON = ConvertTo-Json @{
            "login" = @{
                "username"=$NSUserName;
                "password"=$NSUserPW
            }
        }
        try
        {
            # Login to the NetScaler and create a session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/login"
                Body            = $LoginJSON
                Method          = "Post"
                SessionVariable = "NSSession"
                ContentType     = $ContentType
            }
            $loginresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            If (($_.Exception.Message -like "*Unauthorized*") -and (Test-Path -Path $XMLFile))
            {
                Write-Warning "XML Stored NSCredentials were used, check if the stored NSCredentials are correct for this Citrix ADC (" + $NSIP + ")."
            }
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($loginresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: login successful"
        }
    #endregion Start NITRO Session

    # ---------------------------
    # | Remove Responder Action |
    # ---------------------------
    #region responderaction
        # start with clean response variable
        $adcResponderAction = $null
            
        # Create the Invoke-RestMethod params
        $uri = "https://$NSIP/nitro/v1/config/responderaction/" + [System.Web.HttpUtility]::UrlEncode($Name)

        try
        {
            $invokeRestMethodParams = @{
                Uri         = $uri
                Method      = "DELETE"
                WebSession  = $NSSession
                ContentType = $ContentType
            }
            $adcResponderAction = Invoke-RestMethod @invokeRestMethodParams
        }
        catch
        {
            Write-Error $error[0] 
            Exit          
        }

        If ( -not ($adcResponderAction.errorcode -eq 0))
        # NITRO errorcode found (or results is empty)
        {
            Write-Error ("NITRO: errorcode (" + $adcResponderAction.errorcode + ") " + $adcResponderAction.message + ".")
            Exit
        }
        Write-Verbose "* NITRO: responder action removed successful"
    #endregion

    #region End NetScaler NITRO Session
        #Disconnect from the NetScaler (cleanup session)
        $LogOut = @{
            "logout" = @{}
        } | ConvertTo-Json

        try
        {
            # Loout of the NetScaler and remove the session (stored in $NSSession)
            $invokeRestMethodParams = @{
                Uri             = "https://$NSIP/nitro/v1/config/logout"
                Body            = $LogOut
                Method          = "Post"
                WebSession      = $NSSession
                ContentType     = $ContentType
            }
            $logoutresponse = Invoke-RestMethod @invokeRestMethodParams
        }
        catch [System.Management.Automation.ParameterBindingException]
        {
            Write-Error ("A parameter binding ERROR occurred. Please provide the correct NetScaler IP-address. " + $_.Exception.Message)
            Exit
        }
        catch
        {
            # Debug: 
            Write-Debug $_.Exception | Format-List -Force
            # Error:
            Write-Error ("A [" + $_.Exception.GetType().FullName + "] ERROR occurred. " + $_.Exception.Message)
            Exit
        }
        # Check for REST API errors
        If ($logoutresponse.errorcode -eq 0)
        {
            Write-Verbose "* NITRO: logout successful"
        }
    #endregion End NetScaler NITRO Session
}


#------------------------#
# Script Action workflow #
#------------------------#
Write-Host ""

## Retrieve input parameters
$NSIP = $args[0]
$configMitigation = $args[1]
$performRollback = $args[2]
$rebootAppliance = $args[3]

## Testing Script
#$NSIP = "192.168.0.99"
#$configMitigation = "No"
#$performRollback = "No"
#$rebootAppliance = "No"

# Initiate variables
$responderPolicyName = $null
$responderActionName = $null
[System.Management.Automation.PSCredential]$adcCreds = $null
$vulnerableMessage = ""

# Step 0: Retrieve ADC Credentials
$adcCreds = Get-ADCCredentials #-Verbose

# Show note for not performing the nsapimgr shell mitigation action.
Write-Output "NOTE: this Script Action does not perform the suggested mitigation for the management interfaces (nsapimgr) as it may break administration access. Check https://support.citrix.com/article/CTX267679 for further details."
Write-Output ""
Write-Output ""

# Step 1: Check for mitigation responder policy
Write-Host "* Step 1: Check for an existing mitigation responder policy: " -ForegroundColor Yellow -NoNewline
$responderPolicyArray = Get-ADCResponderPolicy -NSIP $NSIP -ADCCredentials $adcCreds #-Verbose -Debug
Write-Host "SUCCESS" -ForegroundColor Green

# filter for the specific mitigation responder policy rule
$filter = "HTTP.REQ.URL.DECODE_USING_TEXT_MODE.CONTAINS(""/vpns/"") && (!CLIENT.SSLVPN.IS_SSLVPN || HTTP.REQ.URL.DECODE_USING_TEXT_MODE.CONTAINS(""/../""))"
$mitigationPolicyResults = $responderPolicyArray | Where-Object {$_.rule -like "$filter*"}

if ($mitigationPolicyResults)
{
    # a CVE-2019-19781 Mitigation Responder Policy exists
    $responderPolicyName = $mitigationPolicyResults.name 
    $responderActionName = $mitigationPolicyResults.action 

    Write-Host "`t => CVE-2019-19781 Mitigation Responder Policy found." -ForegroundColor Green
    Write-Host "`t`t name: " -ForegroundColor Yellow -NoNewline
    Write-Host $responderPolicyName
    Write-Host "`t`t action: " -ForegroundColor Yellow -NoNewline
    Write-Host $responderActionName
    Write-Host "`t`t hits: " -ForegroundColor Yellow -NoNewline
    Write-Host $mitigationPolicyResults.hits

    # Step 2: Check for global binding for the given responder policyname
    Write-Host "* Step 2: Check for responder policy global binding: " -ForegroundColor Yellow -NoNewline
    $mitigationPolicyBindingResults = Get-ADCResponderPolicyBinding -NSIP $NSIP -PolicyName $responderPolicyName -ADCCredentials $adcCreds #-Verbose -Debug
    Write-Host "SUCCESS" -ForegroundColor Green

    if ($mitigationPolicyBindingResults.responderpolicy_responderglobal_binding)
    {
        # a Global binding for the CVE-2019-19781 Mitigation responder policy exists
        Write-Host "`t => CVE-2019-19781 Mitigation Responder Policy Binding found." -ForegroundColor Green
        Write-Host "`t`t name: " -ForegroundColor Yellow -NoNewline
        Write-Host $mitigationPolicyBindingResults.responderpolicy_responderglobal_binding.name
        Write-Host "`t`t type: " -ForegroundColor Yellow -NoNewline
        Write-Host $mitigationPolicyBindingResults.responderpolicy_responderglobal_binding.boundto
        Write-Host "`t`t priority: " -ForegroundColor Yellow -NoNewline
        Write-Host $mitigationPolicyBindingResults.responderpolicy_responderglobal_binding.priority
        $vulnerableMessage = "This Citrix NetScaler ADC is NOT vulnerable."
        $PushMitigationConfig="AllDone"
    }
    else
    {
        # a Global binding for the CVE-2019-19781 Mitigation responder policy exists NOT
        Write-Output ""
        Write-Warning "=> CVE-2019-19781 Mitigation Responder Policy Binding NOT found."
        Write-Output ""
        $vulnerableMessage = "This Citrix NetScaler ADC is vulnerable."
        # Policy exists, global binding is missing
        $PushMitigationConfig="GlobalBinding"
    }
}
else
{
    # a CVE-2019-19781 Mitigation Responder Policy exists NOT
    Write-Output ""
    Write-Warning "=> CVE-2019-19781 Mitigation Responder Policy NOT found."
    Write-Output ""
    Write-Host "* Step 2: Check for responder policy global binding: " -ForegroundColor Yellow -NoNewline
    Write-Host "SKIPPED (no policy found)" -ForegroundColor Yellow
    $vulnerableMessage = "This Citrix NetScaler ADC is vulnerable."
    # Create the Mitigation Responder policy and global binding
    $PushMitigationConfig="ResponderPolicy"
}


If ($configMitigation -eq "Yes")
{
    # Step 3: Configure CVE-2019-19781 Mitigation
    Write-Verbose "* configMitigation: Mitigation configuration actions requested."
    If ($PushMitigationConfig -eq "ResponderPolicy")
    {
        #enable ns feature responder
        Write-Host "* Step 3a: Configuring mitigation action - Enable nsfeature: " -ForegroundColor Yellow -NoNewline
        Enable-ADCFeature -NSIP $NSIP -Feature "responder" -ADCCredentials $adcCreds #-Verbose -Debug # no response returned
        Write-Host "SUCCESS" -ForegroundColor Green

        #add responder action respondwith403 respondwith "HTTP/1.1 403 Forbidden\r\n\r\n\"
        Write-Host "* Step 3b: Configuring mitigation action - Add responder action: " -ForegroundColor Yellow -NoNewline
        New-ADCResponderAction -NSIP $NSIP -Name "res_act_cve-2019-19781_mitigation" -Type "respondwith" -Target """HTTP/1.1 403 Forbidden`r`n`r`n""" -Comment "CVE-2019-19781 mitigation configured by ControlUp Script Action" -ADCCredentials $adcCreds #-Verbose -Debug
        Write-Host "SUCCESS" -ForegroundColor Green

        #add responder policy ctx267027 "HTTP.REQ.URL.DECODE_USING_TEXT_MODE.CONTAINS(\"/vpns/\") && (!CLIENT.SSLVPN.IS_SSLVPN || HTTP.REQ.URL.DECODE_USING_TEXT_MODE.CONTAINS(\"/../\"))" respondwith403
        Write-Host "* Step 3c: Configuring mitigation action - Add responder policy: " -ForegroundColor Yellow -NoNewline
        New-ADCResponderPolicy -NSIP $NSIP -Name "res_pol_cve-2019-19781_mitigation" -Rule "HTTP.REQ.URL.DECODE_USING_TEXT_MODE.CONTAINS(""/vpns/"") && (!CLIENT.SSLVPN.IS_SSLVPN || HTTP.REQ.URL.DECODE_USING_TEXT_MODE.CONTAINS(""/../""))" -Action "res_act_cve-2019-19781_mitigation" -Comment "CVE-2019-19781 mitigation configured by ControlUp Script Action" -ADCCredentials $adcCreds #-Verbose -Debug
        Write-Host "SUCCESS" -ForegroundColor Green

        # Perform next step
        $responderPolicyName = "res_pol_cve-2019-19781_mitigation"
        $responderActionName = "res_act_cve-2019-19781_mitigation"
        $PushMitigationConfig="GlobalBinding"
    }

    If ($PushMitigationConfig -eq "GlobalBinding")
    {
        # Bind CVE-2019-19781 Mitigation responder policy Globally
        Write-Host "* Step 3d: Configuring mitigation action - Globally bind responder policy $($responderPolicyName): " -ForegroundColor Yellow -NoNewline
        #bind responder global ctx267027 1 END -type REQ_OVERRIDE
        New-ADCResponderGlobalResponderPolicyBinding -NSIP $NSIP -PolicyName $responderPolicyName -Priority 1 -GoToPriorityExpression "END" -Type REQ_OVERRIDE -ADCCredentials $adcCreds #-Verbose -Debug
        Write-Host "SUCCESS" -ForegroundColor Green

        Write-Host "* Step 3e: Configuring mitigation action - Save configuration: " -ForegroundColor Yellow -NoNewline
        #save config 
        Invoke-ADCSaveConfig -NSIP $NSIP -ADCCredentials $adcCreds #-Verbose -Debug
        Write-Host "SUCCESS" -ForegroundColor Green
        $PushMitigationConfig="AllDone"
    }
    $vulnerableMessage = "This Citrix NetScaler ADC is NOT vulnerable."
}
Else
{
    Write-Verbose "* ConfigMitigation: CVE-2019-19781 mitigation configuration action skipped. Parameter configMitigation set to $($configMitigation)"
}


If ($performRollback -eq "Yes")
{
    # Step 4: Rollback CVE-2019-19781 Mitigation
    Write-Verbose "* performRollback: Rollback mitigation configuration actions requested."
    If ($PushMitigationConfig -eq "AllDone")
    {
        # Unbind CVE-2019-19781 Mitigation responder policy Globally
        Write-Host "* Step 4a: Rollback mitigation action - Globally unbind responder policy $($responderPolicyName): " -ForegroundColor Yellow -NoNewline
        #bind responder global ctx267027 1 END -type REQ_OVERRIDE
        Remove-ADCResponderGlobalResponderPolicyBinding -NSIP $NSIP -PolicyName $responderPolicyName -ADCCredentials $adcCreds #-Verbose -Debug
        Write-Host "SUCCESS" -ForegroundColor Green

        # Perform next step
        $PushMitigationConfig="GlobalBinding"
    }

    If ($PushMitigationConfig -eq "GlobalBinding")
    {
        #rm responder policy ctx26702
        Write-Host "* Step 4b: Rollback mitigation action - Remove responder policy $($responderPolicyName)`: " -ForegroundColor Yellow -NoNewline
        Remove-ADCResponderPolicy -NSIP $NSIP -Name $responderPolicyName -ADCCredentials $adcCreds #-Verbose -Debug
        Write-Host "SUCCESS" -ForegroundColor Green

        #rm responder action respondwith403 respondwith "HTTP/1.1 403 Forbidden\r\n\r\n\"
        Write-Host "* Step 4c: Rollback mitigation action - Remove responder action $($responderActionName)`: " -ForegroundColor Yellow -NoNewline
        Remove-ADCResponderAction -NSIP $NSIP -Name $responderActionName -ADCCredentials $adcCreds #-Verbose -Debug
        Write-Host "SUCCESS" -ForegroundColor Green
    }
    Write-Host "* Step 4d: Rollback mitigation action - Save configuration: " -ForegroundColor Yellow -NoNewline
    #save config 
    Invoke-ADCSaveConfig -NSIP $NSIP -ADCCredentials $adcCreds #-Verbose -Debug
    Write-Host "SUCCESS" -ForegroundColor Green
    $vulnerableMessage = "This Citrix NetScaler ADC is vulnerable."
}
Else
{
    Write-Verbose "* CVE-2019-19781 mitigation rollback action skipped. Parameter performRollback set to $($performRollback)"
}

If ($rebootAppliance -eq "Yes")
{
    # Step5: Reboot
    Write-Verbose "* rebootAppliance: Reboot of the appliance requested."
    Write-Warning "=> A reboot of the Citrix NetScaler ADC has been issued and will be performed"
    Write-Host "* Step 5: Reboot appliance: " -ForegroundColor Yellow -NoNewline
    Invoke-ADCReboot -NSIP $NSIP -Warm "false" -ADCCredentials $adcCreds #-Verbose -Debug
    Write-Host "SUCCESS" -ForegroundColor Green
}
Else
{
    Write-Verbose "* CVE-2019-19781 mitigation reboot action skipped. Parameter rebootAppliance set to $($rebootAppliance)"
}

Write-Output ""
Write-Output ""
If ($vulnerableMessage -like "*NOT*")
{
    Write-Host $vulnerableMessage -ForegroundColor Green
}
Else
{
    Write-Host $vulnerableMessage -ForegroundColor Red
}