Help us improve your experience.

Let us know what you think.

Do you have time for a two-minute survey?

header-navigation
keyboard_arrow_up
list Table of Contents

Automation Tools

date_range 02-Apr-25

This topic talks about a few automation tools that you can use with Juniper Mist™. We make no reccommendation regarding any of the tools discussed below. We provide the information and examples for informational purposes only.

Automation Tools Overview

The entire Juniper Mist GUI is built on top of the robust Mist API. This architecture makes Mist administration highly customizable, flexible, and scalable. Using automation tools, you can perform tasks or groups of tasks not available in the GUI.

Automation begins by identifying and understanding the tasks to be performed. Most automation tools are designed for machine-to-machine transactions. Because of this design, automation tools are not always intuitive for humans to understand and configure. Thankfully, many tools exist that help you interact with machine-based interfaces and even create your own automation scripts. The Juniper Mist API is just such a tool.

Postman

Postman is a tool to help you automate Juniper Mist management tasks. Postman can do many things, but you will use it as an API client. According to the Postman web site (www.postman.com), the Postman API client is the foundational tool of Postman. This client enables you to easily explore, debug, and test your APIs while also enabling you to define complex API requests for HTTP, REST, SOAP, GraphQL, and WebSockets.

Postman provides its own API GUI client to interact with a REST API interface, and many others. Postman allows users to set up reusable environments and use variables for consistency and efficiency when testing. You can visually organize each individual request into an order, inspect and store responses for reuse, and even have Postman help generate programmatic code such as Python.

Here is a short video on using variables in Postman to interact with the Juniper Mist API.

Video 1: Automation for Access Switching
Show Transcript

Postman is an excellent development tool. You can use it to test individual configuration changes and then put them together into collections. This video is an excellent example of using Postman and a web browser to put together API requests to configure 802.1x in a switching template.

With the popularity of Postman, Juniper developers have published collections in the public Postman workspaces. Collections are a method of organizing API requests and documentation into groups. You can import, export, and share collections.

Here is a short video demonstrating the use of Postman collections and the Juniper Mist API.

The Postman collections incorporate many Juniper Mist capabilities. They also include collections for gathering client information, Mist Edge devices, switching, software-defined WAN (SD-WAN), and many other objects. You can find these collections, which include the Juniper Mist cloud APIs, Mist cloud WebSocket, and Mist Runner Collections, from this link: https://www.postman.com/juniper-mist/workspace/mist-systems-s-public-workspace.

Python

Python is an object-oriented programming language. It’s a popular language for many reasons. One reason is that Python is highly flexible and extensible. Compared to other programming languages, it is easy to learn and work with. Python is used for web development, data sciences, networking, and the Internet of Things (IoT), to name a few uses. It is open source and works on multiple platforms.

For more information about getting started with Python, check out the Python Software Foundation at: https://www.python.org/about/gettingstarted/

Juniper Networks supports Python use in many forms, such as direct script execution and toolkit scripts: https://www.juniper.net/documentation/us/en/software/junos/automation-scripting/topics/concept/junos-script-automation-python-scripts-overview.html

Python Script Examples

Leveraging the robust API library in Juniper Mist, you can automate tasks using Python. In this section, you will see some simple Python scripts that make a series of calls to the Mist API to gather information or make changes to Mist.

These scripts are meant to serve only as examples and may or may not work in your environment due to possible variances in your environment.

Display WLANs on a Specific Site

This is a simple example script that connects to the Mist API and displays all the wireless LANs (WLANs) for a specific site:

content_copy zoom_out_map
import requests 
import json 
url = 'https://api.mist.com/api/v1/sites/00000000-0000-0000-0000-000000000000/wlans' 
 
##Set the API request headers 
headers = { 
    'Content-Type': 'application/json', 
    'Authorization': 'Token a7c61a9ca25b4c27a14ea7c61a9ca7c61a9ca25b4c27a14e653b5af5db02a25ba7c61a9ca25b4c27a14e653b5af5db024c27a14e653b5af5db026xxxxxxxxxxx' 
} 
  
results = requests.get{url, headers=headers} 
wlans = json.loads{results.text} 
 
##Print each wlan and wlan_id  
for wlan in wlans: 
    print{wlan["ssid"], ">", wlan ["id"]} 
content_copy zoom_out_map
user:$ python3 simple-script.py 
mist-prod > a7c61a9c-a25a-274c-a7c61a9c-a25b 
mist-test > a7c61a9c-a25b-4c27-a7c61a9c-a25b 

Comparing RSSI (Windows)

You execute this Python script on a Windows laptop. The script gathers the current signal quality percentage, not received signal strength indicator (RSSI), from a Windows laptop. The script then gets the RSSI from the access point (AP) to which the laptop is connected by parsing for the wireless adapter’s MAC. The script makes these requests simultaneously and displays the client’s signal quality on the same line as the AP’s RSSI. The script runs until you send a Ctrl+c command from your keyboard to break out of the script execution.

The script makes use of the netsh wlan show interface Windows command. This is the command’s output:

content_copy zoom_out_map
C:\Users\user>netsh wlan show interface 
  
There is 1 interface on the system: 
  
    Name                   : Wi-Fi 
    Description            : Intel(R) Wi-Fi 6E AX210 160MHz 
    GUID                   : aa7a439e-fe66-494c-xxxx-xxxxxxxxxxxx 
    Physical address       : 70:cd:xx:xx:xx:xx 
    State                  : connected 
    SSID                   : wi-fi 
    BSSID                  : d4:20:xx:xx:xx:xx 
    Network type           : Infrastructure 
    Radio type             : 802.11ax 
    Authentication         : WPA2-Personal 
    Cipher                 : CCMP 
    Connection mode        : Auto Connect 
    Channel                : 149 
    Receive rate (Mbps)    : 516 
    Transmit rate (Mbps)   : 574 
    Signal                 : 83% 
    Profile                : hoth 
  
    Hosted network status  : Not available 

This is the script itself:

content_copy zoom_out_map
import requests 
import json 
import os 
import time 
import random 
import string 
import subprocess 
  
##Set the API request headers 
headers = { 
        'Content-Type': 'application/json', 
        'Authorization': 'Token <YOUR_API_TOKEN>' 
} 
  
##Function to get (strip) the "Signal" quality percentage from Windows from the "netsh wlan show interface" command 
def get_clientsignal{}: 
  
    results = subprocess.check_output(["netsh", "wlan", "show", "interface"]).decode() 
    lines = results.split('\r\n') 
  
    d = {} 
    for line in lines: 
        if ':' in line: 
                vals = line.split(':') 
                if vals[0].strip() != ''and vals[1].strip() != '': 
                     d[vals[0].strip()] = vals[1].strip() 
                     
    for key in d.keys(): 
        if key == "Signal": 
              
             return (d[key]) 
         
##Function to get (strip) the "Physical address" MAC from Windows from the "netsh wlan show interface" command 
def get_windowsmac(): 
      
     results = subprocess.check_output(["netsh", "wlan", "show", "interface",]).decode() 
     lines = results.split('\r\m') 
  
     d = {} 
     for line in lines: 
          inf ': ' in line: 
                vals = line.split(':') 
                print(vals) 
                if vals[0].strip() != '' and vals[1].strip() != '': 
                    d[vals[0].strip()] = vals[1].strip() 
  
    for key in d.keys(): 
        if key == "Physical address": 
            client_mac = (d[key]) 
  
            return (client_mac) 
  
  
##Main Section 
###Define variables 
client_mac = get_windowsmac() 
client_mac = client_mac.replace(":", "") 
###input your site_id in the API URL 
url = ('https://api.mist.com/api/v1/sites/<YOUR_SITE_ID>/{}'.format(client_mac)) 
  
client_rssi = 0 
my_rssi = 0 
  
###Loop through every 3 seconds and print the results to the terminal 
while True: 
        results = requests.get(url, headers=headers) 
        client = json.loads(results.text) 
        client_rssi = get_clientsignal() 
        my_rssi = client['rssi'] 
        print('Windows Signal', '=', client_rssi, '   ', my_rssi, '=', 'AP rssi') 
        time.sleep(3) 

When you run the python script, the resulting output should look like this:

content_copy zoom_out_map
C:\Users\user>python client-signal.py 
Windows Signal = 83%	-59 = AP rssi 
Windows Signal = 83%	-59 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-62 = AP rssi 
Windows Signal = 83%	-58 = AP rssi 
Traceback (most recent call last): 
  File “client-signal.py, line 71, in <module> time.sleep(3) 
KeyboardInterrupt 
C:\Users\user>

The Juniper Mist AP reports its statistics approximately every 60 seconds. This is the reason the AP RSSI only changed twice during the time the script was running.

Comparing RSSI (MacOS)

This Python script is executed on a MacBook laptop. It is nearly identical to the previous Windows script. The script simultaneously gathers the RSSI from the MacBook and gets the RSSI from the AP to which the laptop is connected by parsing for the wireless adapter’s MAC address. It makes these requests simultaneously and displays the client’s signal quality on the same line as the AP’s RSSI. The script runs until you send a Ctrl+c command to break out of the script execution. To access the command on the Mac OS, you must include the absolute path to the command: /SystemLibrary/PrivateFrameworks/Apple802111.framework/Versions/A/Resources/airport -I.

This is what the airport -I command displays:

content_copy zoom_out_map
Mac:Desktop user$ /SystemLibrary/PrivateFrameworks/Apple802111.framework/Versions/A/Resources/airport -I 
     agrCtlRSSI: -60 
     agrExtRSSI: 0  
    agrCtlNoise: -93 
    agrExtNoise: 0 
          state: running  
        op mode: station  
     lastTxRate: 486 
        maxRate: 450 
lastAssocStatus: 0 
    802.11 auth: open  
      link auth: wpa2-psk  
          BSSID: 5c:5b:xx:xx:xx:xx 
           SSID: SSID-1 
            MCS: 8 
        channel: 120, -1 

This is the script itself:

content_copy zoom_out_map
import requests 
import json 
import os 
import time 
import random 
import string 
  
  
##Set the API request headers 
headers = { 
        'Content-Type': 'application/json', 
        'Authorization': 'Token <YOUR_API_TOKEN>' 
  
  
##Function to get (strip) the "RSSI" quality percentage from MacOS from the "airport -I" command 
def get_clientsignal{}: 
     
    input = os.popen(       	'/SystemLibrary/PrivateFrameworks/Apple802111.framework/Versions/A/Resources/airport -I) 
    return int(**.join([x.split()[1] for x in input if 'agrCtlRSSI' in x]))      
  
  
         
##Function to get (strip) the MAC from MacOS from the "ifconfig" command 
def get_macbookmac(): 
     input = os.popen('ifconfig en0') 
     return ''.join([xsplit()[1]for x in input if 'ether' in x]) 
  
  
##Main Section 
###Define variables 
client_mac = get_macbookmac() 
client_mac = client_mac.replace(":", "") 
###input your site_id in the API URL 
url = ('https://api.mist.com/api/v1/sites/<YOUR_SITE_ID>/{}'.format(client_mac)) 
  
client_rssi = 0 
my_rssi = 0 
  
###Loop through every 3 seconds and print the results to the terminal 
while True: 
        results = requests.get(url, headers=headers) 
        client = json.loads(results.text) 
        client_rssi = get_clientsignal() 
        my_rssi = client['rssi'] 
        print('Macbook rssi', '=', client_rssi, '   ', my_rssi, '=', 'AP rssi') 
        time.sleep(3) 
Note: Replace placeholder values with actual values, such as your API token.

When the script runs, it gathers the RSSI information from the MacBook and the connected AP (through a Mist API call) and prints its output on a single line. The script runs until you cancel it by issuing the Ctrl+c command.

content_copy zoom_out_map
Mac:Desktop user$ python3 client-signal.py 
Macbook rssi = -61		-57 = AP rssi 
Macbook rssi = -61		-57 = AP rssi 
Macbook rssi = -61		-57 = AP rssi 
Macbook rssi = -61		-57 = AP rssi 
Macbook rssi = -61		-57 = AP rssi 
Macbook rssi = -61		-59 = AP rssi 
Macbook rssi = -61		-59 = AP rssi 
Macbook rssi = -63		-59 = AP rssi 
Macbook rssi = -64		-59 = AP rssi 
Macbook rssi = -65		-59 = AP rssi 
Macbook rssi = -63		-59 = AP rssi 

The Juniper Mist AP reports its statistics approximately every 60 seconds. This is why the AP RSSI changes only once in the example output.

Random Password Creation for a Guest Portal

When you configure a WLAN for a guest portal, use the Guest Portalconfiguration to define the landing page. This is the page for guests to log on to their wireless network. This configuration page enables you to gather information about guests such as their full names, e-mail addresses, and company details. You can add custom fields if you need users to gather additional types of information.

You can configure the guest portal to use an alphanumeric passphrase for authorization. This is a manual process, but you can automate it to run regularly, such as daily, to create a new random password that you distribute to guests each day.

This image shows the current configured passphrase for the guest portal:

Random Password Creation for a Guest Portal

Below is a Python script to create a new, random password for a guest portal. This script will send a PUT command to the API to change the passphrase.

Note: Replace placeholder values with actual values, such as your site ID and your API token.
content_copy zoom_out_map
import requests 
import json  
import random  
import string  
  
url = 'https://api.mist.com/api/v1/sites/<YOUR_SITE_ID>/wlans'  
  
##Set the API request headers 
headers = { 
     'Content-Type': 'application/json', 
     'Authorization': 'Token <YOUR_API_TOKEN>' 
} 
  
results = requests.get(url, headers=headers) 
wlans = json.loads(results.text) 
wlanid = None 
portal = None  
##Search for the guest SSID, mist_guest 
for wlan in wlans: 
    print(wlan["ssid"], ">", wlan["id"]) 
    if wlan ["ssid"] == "mist_guest": 
        wlanid = wlan["id"] 
        portal = wlan["portal"] 
    if wlanid: 
##This function generates a 6 alphanumeric random string 
        thisisnew = ''.join(random.choice(string.ascii_letters) for _ in range(6)) 
        print("New Password is:", thisisnew) 
        portal["password"] = thisisnew 
##This takes the results and issues a PUT for the new password in the guest portal configuration 
        results = requests.put(url+"/{}".format(wlanid), headers=headers, data='{"portal": ' + json.dumps(portal) +'}') 

This is the output from the script. It lists the wlan name and the wlan_id until it finds the mist_guest WLAN (defined in the script) and resets the passphrase with the newly generated, random passphrase:

content_copy zoom_out_map
Mac:Desktop user$ python3 client_guest_password.py 
Mist-1 > 38fn03d0f9d-nfd3-xxxx-xxxx-xxxxxxxxxxxx 
Mist-2 > p3j9n30lmsl-nfd3-xxxx-xxxx-xxxxxxxxxxxx 
Mist-3 > 3knlso2k4ls-df9n-xxxx-xxxx-xxxxxxxxxxxx 
mist_guest > 9djn3axc93nn-89sb-xxxx-xxxx-xxxxxxxxxxxx 
New Password is: UiCnPW 
Mac:Desktop user$ 

You can verify the passphrase change by going back to the WLAN configuration, or WLAN template page, and checking the guest portal configuration. When you click Reveal, you will see the new passphrase.

Random Password Creation for a Guest Portal

Additional Automation Resources

For detailed information and examples, use these resources:

Table 1: Juniper Mist Automation Resources
Resource Description Where to Find It

Python scripts demonstrating possibilities of Mist APIs.

https://github.com/tmunzer/mist_library

Examples of Python scripts using the Mist APIs. These scripts are using the mistapi Python package to simplify the authentication process. To view script examples, go to: https://github.com/tmunzer/mist_library and browse the scripts directory.
MISTAPI - Python Package to use Mist APIs This package is built from the Mist OpenAPI specifications and is designed to simplify the use of the Mist APIs with Python scripts.

To learn more about the package, go to: https://pypi.org/project/mistapi/

Mist API Labs Proof-of-Concept and prototype applications and scripts created to demonstrate the possibilities of Juniper-Mist APIs and some of the use cases. Go to: Mist-Lab Demo Apps and in the Search box, enter webhooks.
Mist Postman Webhook Samples Provides preconfigured examples of POST webhook syntax. Browse: https://www.postman.com/juniper-mist/workspace/mist-systems-s-public-workspace
file_download PDF
{ "lLangCode": "en", "lName": "English", "lCountryCode": "us", "transcode": "en_US" }
English
keyboard_arrow_right
footer-navigation
keyboard_arrow_down
file_download
{ "lLangCode": "en", "lName": "English", "lCountryCode": "us", "transcode": "en_US" }
language