Python Script for Reporting on Juniper Pulse Secure Connected Users

We use a pair of Juniper MAG-2600’s for the majority of VPN connections into our environment. Limited by licensing, I was asked to generate a daily report on connected users, so that senior management can have visibility of and review users that are working from home due to the Covid-19 pandemic.

As far as I could tell (please correct me if I’m wrong!) there is no way to schedule such a report automatically from the Pulse Secure admin page.

So, looking for an excuse to do some scripting, I wrote the below Python script to send an email report which simply provides a list of staff members who have connected via Pulse Secure VPN for that day.

It ain’t pretty. It’s not the most efficient. It’s not particularly secure. But it was fun to write!

It uses Selenium to log into the Pulse Secure admin page and download the User Summary Report in CSV format.

While I could have just dumped this into an email and be done with it, this was too much information for the people requesting this, they just wanted a list of names.

In our environment we don’t use any identifiable information in the samAccountName, it is a random string, for a certain amount of security through obscurity. So the rest of the script deals with converting the username field of the Pulse Secure CSV into the readable display name for the email. This unfortunately relies on a pre-dump of current domain users from PowerShell to compare the Pulse Secure samaccountnames against, so it’s not quite a completely self contained script.

Bit of a niche script, but maybe somebody out there will find something of use in it!

''' A script that pulls User Summary CSV report from Pulse Secure, parses it to list of Display Names, and emails this list to recipients. '''

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.keys import Keys
import csv
import smtplib
import glob, os
from datetime import datetime

def getUserLogFromPulseSecure():

    # Function logs into Pulse Secure and downloads User Activity log for the past 24 hours

    # ChomeDriver for Chrome 80 downloaded from https://chromedriver.storage.googleapis.com/index.html?path=80.0.3987.106/
    # and placed in C:\Windows\System32. Confirm in PATH by running chromedriver in CMD
    driver = webdriver.Chrome()

    # URL for Secure Remote login page
    url = 'https://x.x.x.x/dana-na/auth/url_admin/welcome.cgi'
    driver.get(url)

    # Click Advanced/Proceed on SSL Certificate warning screen
    driver.find_element_by_id("details-button").click()
    driver.find_element_by_id("proceed-link").click()

    # Find username field and enter username
    username = driver.find_element_by_id("username")
    username.clear()
    username.send_keys("admin")

    # Find password field and enter password
    password = driver.find_element_by_id("password")
    password.clear()
    password.send_keys("YourPassword")

    # Find Sumbit button and click
    driver.find_element_by_name("btnSubmit").click()

    # If admin account is already logged in, there may be a warning. If so, click "Read only access", otherwise proceed
    try:
        driver.find_element_by_name("btnReadOnly").click()
    except:
        pass

    # Fix to open a new tab, allowing a direct URL to be entered without starting a new session
    driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't')

    # Direct link to downloaded the CSV log file of active sessions
    driver.get("https://x.x.x.x/dana-admin/reporting/report_user_summary.cgi?download=1&format=csv&date_range=24hours&username=&realm=&sort_column=username&sort_order=2")
    # Small pause to allow CSV file to complete download
    sleep(3)

def getSamAccountNameFromPulseSecureLog(pathToCSV):

    # Empty array to hold user samaccountname ID strings
    users_by_samaccountname = []

    # Count to skip first line of CSV file (headings)
    count = 0

    with open(pathToCSV) as csv_file:
        csv_reader = csv.reader(csv_file)
        for line in csv_reader:
            # Skip first blank line
            if count == 0:
                count += 1
            else:
                users_by_samaccountname.append(str(line[0][8:]))
                count += 1

    # Return an array of samaccountname IDs
    return users_by_samaccountname

def getUsersOnPulseSecureLast24Hr(users_by_samaccountname):

    # Create a blank dictionary to hold samaccountname:displayname string pairs
    allUserDict = {}

    # Read all current samaccountnames from a pre-made list generated from Powershell
    # get-aduser -filter * | select samaccountname, name | out-file c:\allusers.txt
    # Replace spaces with commas in text editor, import the text file into Excel CSV using commas as delimiter
    with open(r'c:\Scripts\allusers.csv') as csv_file:
        csv_reader = csv.reader(csv_file)
        for line in csv_reader:
            allUserDict[line[0].lower()] = line[1]

    # Blank list to hold string of user samaccountnames from Secure Pulse log
    usersLast24Hr = []

    for user in users_by_samaccountname:
        if user in allUserDict:
            usersLast24Hr.append(allUserDict[user])

    # Return a list of user samaccountname ID strings
    return usersLast24Hr

def getPathToLatestReport():

    # The CSV downloaded from Pulse Secure automatically downloads to Downloads folder. This function selects the
    # latest CSV file. Small chance if will pick up a non-Pulse Secure related CSV file!

    list_of_files = glob.glob(r'c:\users\xxxxx\downloads\*.csv')
    latest_file = max(list_of_files, key=os.path.getctime)
    print(f"Using file: {latest_file}")

    # Returns full path to the CSV file
    return latest_file

def sendMailReport(users_last_24hr):

    # Send email report to emails in 'recipients' list

    dateString = "{:%B %d, %Y}".format(datetime.now())

    sender = 'pulse_secure_user_report@example.com'
    recipients = ['admin@example.com', 'manager@examples.com']
    server = smtplib.SMTP('YOUR_SMTP_SERVER', 25)

    subject = f'Pulse Secure User Report for {dateString}'
    msg = f'Subject: {subject}\n\nThe following users were connected to Pulse Secure in the past 24 hours: \n\n'

    for user in users_last_24hr:
        msg += user + "\n"

    server.sendmail(sender, recipients, msg)

getUserLogFromPulseSecure()

users_by_samaccountname = getSamAccountNameFromPulseSecureLog(getPathToLatestReport())

users_last_24hr = getUsersOnPulseSecureLast24Hr(users_by_samaccountname)

sendMailReport(users_last_24hr)



Leave a Reply

Your email address will not be published. Required fields are marked *