How to limit concurrent GlobalProtect connections per user

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements

How to limit concurrent GlobalProtect connections per user

L7 Applicator

Hi communit

 

So far it isn't possible to limit the concurrent GlobalProtect connections per user directly in PAN-OS. There is a feature request #4603 for which you can vote and wait/hope that this will be implemented.

 

If you need a solution (workaround) right now, once more the PAN-OS API is your friend. Because we (like probably some or a lot og admins here) had the problem, that we had users, specially from external suppliers, who shared their accounts and so they logged in multiple times. So I wrote this little powershell script. The script needs to be configured as scheduled task to run every minute for example. Every time the script runs it checks the connected Global Protect users and then kicks out users that are logged in multiple times. If you want, you can also specify the number of allowed concurrent logins per user with the variable $maxlogins. This way you're able to kick out users that are logged in more than 3 times for example.

 

[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;

$apikey = "INSERT_API_KEY_HERE"
$firewall = "FIREWALL_HOSTNAME_OR_IP"
$gpgateway = "GLOBAL_PROTECT_GATEWAY_NAME"
$maxlogins = 1

Function callApiOp ($firewall, $param) {
    $request = New-Object System.Net.WebClient
    $apiurl = "https://" + $firewall + "/api/?key=" + $apikey + "&type=op&cmd=" + $param
    return [xml]$request.DownloadString($apiurl)
}

$param = "<show><global-protect-gateway><current-user><gateway>" + $gpgateway + "</gateway></current-user></global-protect-gateway></show>"
$logins = callApiOp $firewall $param
$logins = $logins.response.result.entry | sort 'login-time-utc'
$loginevents = @{}
foreach ($event in $logins) {
    $username = $event.username
    if ($loginevents.ContainsKey($username)) {
        $loginevents.($username) = $loginevents.($username) + 1

    }
    else {
        $loginevents.Add($username,1)
    }
}
foreach ($user in $loginevents.GetEnumerator()) {
    $forcelogout = $logins | Where-Object {$_.username -eq $user.key}
    $userstologout = $user.Value - $maxlogins
    for ($i=0;$i -lt $userstologout; $i++) {
        if ($forcelogout.count -eq $null) {
            $domain = $forcelogout.domain
            $computer = $forcelogout.computer
            $username = $forcelogout.username
        }
        else {
            $domain = $forcelogout[$i].domain
            $computer = $forcelogout[$i].computer
            $username = $forcelogout[$i].username
        }
        $logoutparam = "<request><global-protect-gateway><client-logout><gateway>" + $gpgateway + "-N</gateway><reason>force-logout</reason><user>" + $username + "</user><computer>" + $computer + "</computer>"
        if ($domain -ne "") {
            $logoutparam += "<domain>" + $domain + "</domain>"
        }
        $logoutparam += "</client-logout></global-protect-gateway></request>"

        $status = callApiOp $firewall $logoutparam
        if ($status.response.result.response.status -eq "success") {
            write-host "Logged out user $username from computer $computer"
        }
        else {
            $msg = "Could not logout " + $username + " from computer " + $computer + " because of the following error: " + $status.response.result.response.error
            Write-Host $msg
        }

    }
}

 

 

Maybe this helps at least some of you, or at least gives another idea for the almost countless use cases of the PAN-OS API.

 

Feedback is appreciated 😉

 

Regards,

Remo

 

39 REPLIES 39

Hey Remo:

 

Where should this run, exactly?

 

Hi @bernardo.hernandez

 

On a server/computer that has acces to the API of the firewall where you have globalprotect configured.

 

Regards,

Remo

Thanks Remo

 

I'm having a lot of trouble trying to get my API key. I've tried sending a GET request to the FW per this article https://www.paloaltonetworks.com/documentation/80/pan-os/xml-api/get-started-with-the-pan-os-xml-api... using powershell, however I've had no luck yet. 

 

Any pointers?

 

 

 

Simply try it in the browser with this url (wher you replace the hostname, username and password to actual values):

https://HOSTNAME/api/?type=keygen&user=USERNAME&password=PASSWORD

Great. I've got my API key. 

 

I had to change the execution policy for the currentuser on my machine so that I could run the script however I get the following errors. One per every one of the first $variables on the script, meaning $apikey, and $firewall.

 

"The term $variable is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name , or if a path was included, verify that the path is correct and try again."

 

😞

Hmn ... you copied the script exactly how I posted it in this topic and you only replaces the values between the "" ?

Yes. 

 

 

Something like this: 

 

$firewall = 192.168.0.1

$gpgateway =GP_test

 

You need to enclose the values of variables in "". So if you do it like this it should work:

$firewall = "192.168.0.1"
$gpgateway = "GP_test"

All right. I'm getting there... 

 

Just one more hiccup

 

hiccup.PNG

You probably use a self signed cert on the firewall right?

 

Try this to disable certificate checks (add it as second line of the script):

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

Cool!

 

It does run. Now, I'm not sure what output should I expect. 

 

I get:

 

 

response.PNG

 

So far the script does not really show an output yet. I will add a new line to script that will show which users were logged out.

 

Awesome! 

 

Looking forward to it. 

 

Thank you for sharing and taking the time to walk me thru it all. I appreciate it.

 

Regards

Hi @bernardo.hernandez

 

The script should now show you the users and computers where the global protect connection was terminated.

  • 42862 Views
  • 39 replies
  • 16 Likes
Like what you see?

Show your appreciation!

Click Like if a post is helpful to you or if you just want to show your support.

Click Accept as Solution to acknowledge that the answer to your question has been provided.

The button appears next to the replies on topics you’ve started. The member who gave the solution and all future visitors to this topic will appreciate it!

These simple actions take just seconds of your time, but go a long way in showing appreciation for community members and the LIVEcommunity as a whole!

The LIVEcommunity thanks you for your participation!