Getting Started with the Cato API

This article introduces the Cato API and analyzes a sample Python application.

Introduction

The Cato API is implemented according to the GraphQL specification. Even though the GraphQL is intended to produce easy to use APIs, learning how to use any new technology still requires an investment of time from the developer. The goal of this document is to reduce the level of this investment and walks through a small Python application that executes the admins Cato API call and simply returns the number of admins that have been defined for an account. In doing so, the most important elements of a Cato GraphQL API application are introduced to the reader.

Note

Notes:

It is expected that the reader has a basic understanding of the following:

  • Scripting or programming (e.g. you are familiar with concepts like variables and code libraries)

  • The JSON specification (e.g. you have worked with JSON documents)

  • Networking (e.g. you know of the existence of the HTTP protocol and what a server is)

Some experience with the Python language would be of benefit, but it should still be possible to understand the article without this.

Walkthrough of a Basic Cato API Application

The application presented here has been written in Python and uses the Cato API admins call to retrieve the total number of admins defined for an account.  Python and the admins API call have been chosen because:

  • Python is a very common language that is easy to read and understand

  • The admins API call can be used to create a very simple example of calling the Cato GraphQL API

The sample program is basic and contains no error checking.  The program does no more than print the total number of admins defined for the account. 

Note

Note: The Cato API is not tied to any specific programming language.  It is possible to implement an application using any language that can use the HTTP POST function and process JSON documents.  

Overview of the Sample Program

This sample program is short and doesn't include any decision making logic or code to repeat actions.  It could have been kept even shorter by combining some of the lines of code into a single line.  The extra lines of code have been included to make it easier to explain what is going on.

# Import Python library code
import os
import urllib.request
import ssl
import json

# Obtain the Cato API Key from an environment variable
cato_api_key = os.getenv("CATO_API_KEY")

# Create the GraphQL request to be sent
get_total_admins = '''{
    admins (accountID: 12345) {
        total        
    }
}'''
graphql_query = {'query': get_total_admins}

# Build the http request
cato_api_url = "https://api.catonetworks.com/api/v1/graphql2"
headers = {'x-api-key': cato_api_key,
           'Content-Type':'application/json'}
unverified_ctx = ssl._create_unverified_context()
json_post = json.dumps(graphql_query)
json_post_encoded = json_post.encode()
request = urllib.request.Request(url=cato_api_url, data=json_post_encoded, headers=headers)

# Send the query and convert the response into a Python dictionary
response = urllib.request.urlopen(request, context=unverified_ctx, timeout=30)
json_response_encoded = response.read()
json_response = json_response_encoded.decode()
get_admins_total_result = json.loads(json_response)

# Extract the total from the returned data and print it out
total = get_admins_total_result['data']['admins']['total']
print('The total number of admins defined with your account is: {}'.format(total))

Note

IMPORTANT! This program is supplied as a demonstration of how to access the Cato API with Python. It is not an official Cato release and is provided with no guarantees of support. Error handling is restricted to the bare minimum required for the script to work with the API, and may not be sufficient for production environments.

All questions or feedback should be sent to api@catonetworks.com

The diagram provided below shows the sequence of events that take place when the program is run:

  1. The program creates a JSON document which is sent to the Cato API GraphQL server.

  2. The Cato API GraphQL server checks to ensure the API call defined in the JSON document is correct and obtains the requested data from the Cato service.

  3. The Cato API GraphQL server returns the data to the program in a JSON file.

Cato_API_FLow.jpeg

Importing Python Library Code

One of the reasons for using Python for the example program is the availability of a rich set of libraries.  These libraries provide functions and objects that can handle a vast range of tasks.  We will now go through each imported library and provide notes to explain why it is needed.

import os
  • The os library provides a function that will allow the code to access data contained in the operating system's environment variables.

import urllib.request
  • The request module from the urllib library defines the Request class that creates objects that can handle communication with remote servers accessed via a URL.

  • This will make it possible to send the Cato API request to the Cato GraphQL API server

import ssl
  • The ssl library is required to create a custom unverified context for the requests sent to the Cato GraphQL API server.

import json
  • This library contains functions that will make it possible to convert a Python dictionary into a JSON string and vice versa.

  • This ability to convert between the two different formats makes it much easier to write code that can work with JSON documents.

Obtaining the Cato API Kkey

This line of code uses the getenv library function to read the API key from an environment variable and assign it to a variable.

cato_api_key = os.getenv("CATO_API_KEY")

The Cato GraphQL server expects to receive this key in a nHTTP header.  The key is not provided in the JSON document because the GraphQL specification does not include authorisation as part of the standard.  Including authorisation in the JSON document would be a violation of the specification.  The Cato API key is generated via the Cato Management Application.  For more information about creating an API key, see Generating API Keys for the Cato API.

Note

WARNING! Although it is possible to hard-code the Cato API key into your code, it is highly recommended that this is not done.

Creating the GraphQL Request to be Sent

The next couple of lines of code create a Python directory containing one key/value pair.  The value of the entry is built using a Python multi-line string that defines the query that will be sent to the GraphQL server.

get_total_admins = '''{
    admins (accountID: 12345) {
        total    
    }
}'''
graphql_query = {'query': get_total_admins}

The Cato GraphQL server will interpret this string to mean: execute the function get_total_admins, passing two arguments to it (accountID and type) and returning only the "total" number of entities .  Or stated more directly, "Return the total number of entities of admins that are defined for example account # 12345".  This specific example of the admins API call  illustrates an important advantage of a GraphQL API

  • The server only returns the data that the application requested

The fact is, the admins call can return a lot more data.  For example, it is possible for an application to request that admins return details about each admin.  However, this application only needs to know the total number of admins.  This characteristic of GraphQL avoids what is referred to as over-fetching and can greatly simplify the code needed to implement the application.

Building the HTTP Request

In this section of the program a request object is constructed.  This object will be used to send the API call to the GraphQL server using HTTPS. This request object requires information that is provided by several other objects that need to be created first.   First of all, a simple string object is constructed to contain the URL of the GraphQL server that the request object will send the query to.

cato_api_url = "https://api.catonetworks.com/api/v1/graphql2"

Note

Note: A GraphQL API uses only one URL for all API calls.  The details of the call, such as arguments, are provided in the JSON document.  This is in contrast to a REST API which would use a different URL for each API call and pass arguments to the call by appending them to the URL.  This use of a just one URL that is not cluttered with arguments is considered to be another advantage of a GraphQL API. 

Next a dictionary is created that defines two HTTP headers.  These headers are used by the request object to construct a HTTP POST request that the GraphQL server will accept.  Without these headers the HTTP POST requests would be rejected by the server.

headers = {'x-api-key': cato_api_key,           
           'Content-Type':'application/json'}

The next line of code creates an SSL context object. Python uses this object to determine how it should encrypt HTTP requests and send them using Transport Level Security (TLS). Here we are creating an SSL context object that does not verify certificates. This has been done to avoid certificate errors in networks subject to upstream TLS inspection.

unverified_ctx = ssl._create_unverified_context()

Note

IMPORTANT! Using an unverified SSL context object means that no checks will be made to sure that certificates are valid. Cato Networks recommends that you never use such an approach in production. Details of how to harden security are beyond the scope of this document.

The next two lines of code convert the Python dictionary containing the Cato API call into a string and encode that string into bytes.  The second step is required to allow the string to be transmitted over the network.

json_post = json.dumps(graphql_query)
json_post_encoded = json_post.encode()

Finally the request object is created and the program is now ready to send the get_total_admins call to the server.

request = urllib.request.Request(url=cato_api_url, data=json_post_encoded, headers=headers)

Sending the Query and Processing the Response

Here the program sends the request to the GraphQL server by calling the urlopen function of the urllib library.  Callling this function will result in the return of a  HTTPResponse object.  

response = urllib.request.urlopen(request, context=unverified_ctx, timeout=30)

Note

IMPORTANT! Calling the urlopen function could result in the generation of an error.  For example, the GraphQL server could reject the request due to syntax error or network issues could result in a timeout (i.e. no response after 30 seconds).  These errors are not handled here.

The object returned by the urlopen function includes a body field which holds the JSON document returned by the server.  This can be extracted from the object by executing its read method which returns a bytes object.  This bytes object is then converted into a string object by calling the decode method of the bytes object.

json_response_encoded = response.read()
json_response = json_response_encoded.decode()

This decoded string contains a JSON document which will look like this:

{    
    "data" : {
         "admins" : {
              "total": 4
         }
    }
}

As you will see, the format of the returned data looks very like the format of the request that was sent to the server.  This is intentional and another advantage of using the GraphQL specification to implement an API.  This approach simplifies the coding of the application by keeping the returned data in the same shape as the request.

The final line of code in this section of the program uses the json library function 'loads' to convert the returned JSON string into a Python nested dictionary.  

get_total_admin_result = json.loads(json_response)

Extracting the Total from the Returned Data and printing it out

The last two lines of the code extract the value from the total field that was returned by the server and print it out to the console. 

total = get_total_admins_result['data']['get_total_admins']['total']
print('The total number of admins defined for your account is: {}'.format(total)) 

The output will look like this:

The total number of admins defined for your account is: 4

Summary

This goal of this document was to illustrate to the reader just how easy it is to use the Cato API.  Exhaustive details about the Cato API have not been included and no code has been written to handle errors.  Instead,  a simple Python program has been used to highlight the most important elements of a Cato API application.  These are:

  • Creating a Cato API call and adding it to a JSON document

  • Obtaining the Cato API key

  • Creating HTTP headers that contain the Cato API key and define the data format (JSON) of the data being sent

  • Sending the JSON document (encoded in bytes) to the Cato GraphQl API server using the HTTP POST command encrypted with TLS

  • Converting the response object returned by the server into to a JSON document

  • Converting the JSON document into a format that can be used by the program

Was this article helpful?

2 out of 2 found this helpful

1 comment

  • Comment author
    Dermot - Community Manager Only 42 of these badges will be awarded.  They are reserved for people who have played a key role in helping build the Cato Community through their contributions! Community Pioneer The chief of community conversations. Community manager

    Hello All!

    If you wish to comment on this article, please do so by posting in the Cato Online Community by following this link to the Cato API topic.

    Kind Regards,

    Dermot Doran - Cato Networks Community Manager

Add your comment