Working with REST API on Junos OS

Tomasz Schwiertz
5 min readJan 2, 2020


I want to thank you for your interest in automation/scripting, and I want to welcome you to my first LinkedIn publication. In this article — We will take a closer look at the REST method, the Application Programmable Interface (API) of a Juniper Junos OS router and an off-box Python script that makes use of the both above.

Let’s approach this topic by solving a real-world problem. The Directive — local database of users, MUST not contain any of the private usernames of Network Engineers. The only two usernames allowed are remoteNOC and backup. Network Engineers are meant to pass authentication/authorisation and log in via RADIUS. A manual audit showed that some of the routers have the following users configured:

set system login user backup uid 2001
set system login user backup class super-user
set system login user backup authentication encrypted-password

set system login user remoteNOC uid 2002
set system login user remoteNOC class super-user
set system login user remoteNOC authentication encrypted-password

set system login user j.doe uid 3000
set system login user j.doe class super-user
set system login user j.doe authentication encrypted-password

set system login user alice uid 32343
set system login user alice class super-user
set system login user alice authentication encrypted-password

In a small network like our — applying automation would be just for the sake of having automation rolled out. But once the device count exceeds 50 devices — this task becomes a chore. Let’s automate!

The Network

The Plan

We will make our script to visit every router in our network. Each router’s local user database will be checked against the above directives. If the script finds disallowed usernames — it will list them. For this PoC, the following simplifications will be made:

  • login/pass data will be stored in the script file
  • we assume that the whole network consists of Juniper devices
  • no error handling will be implemented
  • the transport protocol will be HTTP (less secure than HTTPs)


Let’s make sure that all our Juniper devices have REST API (along with REST API Explorer) configured. Let’s change the default TCP/3000 port to TCP/3001 and secure the API to be accessible from a list of allowed IP’s, allowing no more than five simultaneous sessions.

set system services rest http port 3001
set system services rest control allowed-sources [ ]
set system services rest control connection-limit 5
set system services rest enable-explorer

Let’s put the theory into practice. Let’s source an API call (HTTP GET method) request from a Web browser to test the REST API service.

Crafting an RPC call

To get a router to reply — we have to craft an inquiry in the first place. But what are the inquiries available to us? Junos OS comes to the rescue. We can view instructions as RPC calls for operational status by adding a modifier to the operational show command.

root@CORE1-LON> show version | display xml rpc 
<rpc-reply xmlns:junos="">

Let’s put the RPC request into a browser to get an XML reply from the router.

Looks good, service is reachable and responsive.

REST API Explorer

We only want to query the active configuration for configured users. In other words — we don’t want to have the full device configuration, just the section where usernames are configured. To be able to craft such an inquiry (with a filter) — we can make use of the REST API Explorer functionality. To open the explorer — let’s go to

The explorer allows us to experiment with the RPC calls and output data without building a front/back end to acquire, parse and display data. The REST API Explorer is a tool for fast prototyping and to get a definite Proof of Concept.

After querying our router — we get a detailed reply. This is precisely the Proof of Concept that we expected.

Let’s use the URL and BODY of the RPC query as the request parameters in our Python script.

import requests
from xml.etree import ElementTree as ET

DEVICES = ["", "", ""]

FILTER = """
<filter type="subtree">

for device in DEVICES:
reply ="http://{}:3001/rpc".format(device),data=FILTER,
auth=requests.auth.HTTPBasicAuth(USER, PWD),
headers={"Accept": "application/xml","Content-Type": "application/xml"})

XML_lines = "\n".join(reply.text.splitlines()[3:-1])
root = ET.fromstring(XML_lines)

print("\nDevice : {} has the following usernames in its local DB:"
names = root.findall('.//user')
for name in names:
username = name.find('name').text

The script loops over every device from the DEVICES list, executing a POST HTTP method with our source/filter/XPath commands as message payload. Every router reply is saved, distilled and processed, so we get only the XML data we need. Finally, that XML tree is searched for all name values. The below snippet shows the findings of the executed script.

Device : has the following usernames in its local DB:

Device : has the following usernames in its local DB:

Device : has the following usernames in its local DB:

As we see — the first two routers had disallowed usernames configured. The script was able to obtain this information within seconds, saving the Network Engineer a lot of repeatable and dull work.

And that’s a wrap on our first REST API call to extract and process data from a set of Junos OS routers. If you enjoyed reading this article as much as I while writing, then like, share and subscribe ;) This would mean the world to me and would motivate me to pump out more content like that!



Tomasz Schwiertz

ISP Network Engineer, Architect, CCIE Candidate London based CISCO Trained Professional | follow me on IG: @tomaszschwiertz