Using JSONSchema to Validate input


There are a lot of REST APIs out there. Quite a few of them use JSON as the data structure which allows us to get data in and out of these devices. There are a lot of network focused blogs that detail how to send and receive data in and out of these devices, but I wasn’t able to find anything that specifically talked about validating the input and output of the data to make sure we’re sending and receiving the expected information.

Testing is a crucial, and IMO too often overlooked, part of the Infrastructure as Code movement. Hopefully this post will help others start to think more about validating input and output of these APIs, or at the very least, spend just a little more time thinking about testing your API interactions before you decide to automate the massive explosion of your infrastructure with a poorly tested script. 🙂

What is JSONSchema

I’m assuming that you already know what JSON is, so let’s skip directly to talking about JsonSchema. This is a pythonlibrary which allows you to take your input/output  and verify it against a known schema which defined the data types you’re expecting to see.

For example, consider this snippet of a schema which defines what a valid VLAN object looks like

"vlan_id":
{
    "description": "The unique ID of the VLAN. IEEE 802.1Q VLAN identifier (VID)", 
    "minimum": 1, 
    "maximum": 4094, 
    "type": "integer", 
    "sql.not_null": true
}

You can see that this is a small set of rules that defines what is a valid entry for the vlan_id property of a VLAN.  As a network professional, it’s obvious to us that a valid VLAN ID  must be between 1 and 4094. We know this because we deal with it every day. But our software doesn’t know this. We have to teach it what a valid vlan_id property looks like and that’s what the schema does.

our software doesn’t know this. We have to teach it

Why do we care?

Testing is SUPER important. By being able to test the input/output of what you’re feeding into your automation/orchestration framework, it can help you to avoid, at worst, a total meltdown, or, at best, a couple of hours trying to figure out why your code doesn’t work.

Using JSONSchema

So the two things you’re going to need to use JSONSchema are

  • The JSON Schema for a specific API endpoint
  • The input/output that you want to validate.

In this case, we’ll use a VLAN object that is coming out of an ArubaOS-Switch REST API.

You did know the ArubaOS-Switches have a REST API, right?

Step1 – Loading the VLAN object

We’re going to gather the output from the VLANS API. Instead of writing custom code, we’ll just use the pyarubaoss library. I’ll leave you to check out the GitHub repo and just paste the contents of the output of a single VLAN JSON output here. I’m also going to create a second VLAN with a VLAN_ID of 5000. Just to show how this works. 5000 of course, is not valid and we’d like to prove that. Right?


vlan_good = json.loads('''{
"uri": "/vlans/1",
"vlan_id": 1,
"name": "DEFAULT_VLAN",
"status": "VS_PORT_BASED",
"type": "VT_STATIC",
"is_voice_enabled": false,
"is_jumbo_enabled": false,
"is_dsnoop_enabled": false,
"is_dhcp_server_enabled": false
}
''')
vlan_bad = json.loads('''{
"uri": "/vlans/1",
"vlan_id": 5000,
"name": "DEFAULT_VLAN",
"status": "VS_PORT_BASED",
"type": "VT_STATIC",
"is_voice_enabled": false,
"is_jumbo_enabled": false,
"is_dsnoop_enabled": false,
"is_dhcp_server_enabled": false
}
''')

Step 2 – Loading the JSON Schema Definition

Now we have the output, we want to make sure that the output here complies with the JSON Schema definition that we’ve been provided.

Loading the JSON schema

Here’s a sub-set of the JSON schema that defines what a valid VLAN looks like


schema = json.loads('''{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "VLAN configuration data.",
"title": "Vlan",
"type": "object",
"sql.max_rows": 4094,
"properties": {
"uri": {
"description": "The URI of the configuration entity",
"type": "string",
"readonly": true
},
"vlan_id": {
"description": "The unique ID of the VLAN. IEEE 802.1Q VLAN identifier (VID)",
"minimum": 1,
"maximum": 4094,
"type": "integer",
"sql.not_null": true
}
},
"additionalProperties": true
}''')

Step 3 – Importing the JSON Schema Library and Validating

Now we’re going to load the JSON Schema library into our python session and use it to validate the VLAN object using the Schema we defined above.

First we’ll look at the vlan_good object and run it through the validate function


from jsonschema import validate
validate(vlan_good, schema)

As you can see, there’s nothing to see here. Basically this means that the vlan_good object is conforming properly to the provided JSON Schema. The VLAN ID is valid as it’s a integer value between 1 and 4094

Now let’s take a look at the vlan_bad object and run it through the same validate function


validate(vlan_bad, schema)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/jsonschema/validators.py", line 541, in validate
cls(schema, *args, **kwargs).validate(instance)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/jsonschema/validators.py", line 130, in validate
raise error
jsonschema.exceptions.ValidationError: 5000 is greater than the maximum of 4094
Failed validating 'maximum' in schema['properties']['vlan_id']:
{'description': 'The unique ID of the VLAN. IEEE 802.1Q VLAN '
'identifier (VID)',
'maximum': 4094,
'minimum': 1,
'sql.not_null': True,
'type': 'integer'}
On instance['vlan_id']:
5000

We can see that the validate function now raises an exception because and let’s us know very specifically that the VLAN ID 5000 is not valid

jsonschema.exceptions.ValidationError: 5000is greater than the maximum of 4094

Pretty cool right? We can still definitely shoot ourselves in the foot, but at least we know the input/output data that we’re using for our API is valid. To me this is important for two reasons

  • I can validate that the data I’m trying to send to a given API conforms to what that API is expecting
  • I can validate that the vendor didn’t suddenly change their API which is going to break my code

Wrap Up

There are a lot of networking folk who have started to take on the new set of skills required to automate their infrastructure. One of the most crucial parts of this is testing and validating the code to ensure that you’re not just blowing up your network more efficiently. JSON Schema is one of the tools in your tool box that can help you do that.

Comments, questions? Let me know

@netmanchris

Leave a comment