API Interactions are designed to be easy
Believe it or not, the IT infrastructure industry is trying to make things easier by building API access out.
Programmatic interfaces are a new mental model competing for brain-space with GUI and CLI implementations; we need to play to its strengths:
- Parsing output from a computer automatically
- Easy batch entry
- Ensuring that a thing configured matches the thing requested
- (Usually) easy pass/fail responses based on HTTP response codes
API Conversation Structure
RESTful, SOAP, and NetCONF interfaces all interleave the concept of a conversation with the Hypertext Transfer Protocol (HTTP) standards:
- Identify Yourself
- Ask for things
- Get a Response
NB: Most API implementers (vendors) will implement API standards very loosely!
NB: RESTful interfaces will be used for the examples in this post, as it's quickly becoming the most common.
Authentication
Authentication is where most new users get stuck. It's complicated, but usually an API provider will also leverage an SDK to simplify the authentication process when you "graduate" to a programming language.
This only covers what a client has to do to perform API work - implementing an API (and authorization with it) is considerably more complex.
Basic Authentication
The title says it all, this authentication schema just uses Base64 encoding (ASCII-formatted binary) to place your username and password in an HTTP header:
1Authorization: Basic {{ Base64 String }}
If this approach makes you feel a little uncomfortable, it should. This is not a secure way to execute commands; it puts your credentials at risk. There are a few ways to mitigate the security risks:
- Ensure that any endpoint you interact with uses strong cryptography and has a valid certificate
- Postman and
cURL
do half of that by default - If it's an API you manage, issue it a client-recognizable certificate and tune cryptography upwards
- Postman and
- Try using a "read-only" account unless a change is required
- Use Basic Authentication as a method to establish a session token
Most new API sessions will at least start using Basic authentication, so these guidelines will apply unless client certificate authentication is used.
Here are some examples of client authentication use:
cURL
1curl -u {{ username }} -p {{ password }} https://{{ api_endpoint }}/get_stuff
2curl --header 'Authorization: Basic {{ string }}' https://{{ api_endpoint }}/get_stuff
Python 3
1import requests
2import sys
3
4try:
5 # This example is to generate a bearer token with Cisco's Firepower Threat Defense
6 do_api_url = "https://{{fmc_ip}}/api/fmc_platform/v1/auth/generatetoken"
7 # The Requests library supports converting to Base64 from a tuple to keep things simple
8 do_api_request = requests.request(
9 "POST",
10 url= do_api_url,
11 auth=(username, password)
12 )
13 do_api_request.raise_for_status()
14except requests.Timeout:
15 sys.exit("TCP Timeout!")
16except HTTPError as e:
17 sys.exit("HTTP Error Found! " + do_api_request.status_code + " " + str(e))
Token Authentication
Most API Providers will require you to use safer authentication for continued requests. This is a good thing - but it does add of work. Usually, Basic or Certificate authentication is used to establish a timeboxed token for future authentication.
These tokens have several forms:
-
Bearer Token: Simple. They'll use the
Authorization
header per the HTTP standard:- `Authorization: Bearer '{{ token }}'
- JSON Web Token: Standardized and much more robust. Base64 encodes a JSON payload. It supports signing of all requests and provides context in all future requests, which makes things easier to parse on the server side
- I'll just call this third category weird stuff. Vendors loosely follow standards, so they'll typically have headers that are specific to their platform. The mechanics remain the same, but the header name won't be
Authorization
Here are some examples:
cURL
vmware-api-session-id
1# GitHub follows the Bearer standard
2curl --request GET \
3--url "https://api.github.com/octocat" \
4--header "Authorization: Bearer YOUR-TOKEN" \
5--header "X-GitHub-Api-Version: 2022-11-28"
6# VMware vSphere usesas an API key
X-auth-access-token` as a custom header
7curl --location --globoff 'https://{{vsphere_vcenter}}/api/content/library/{{vsphere_base_images_library}}' \
8--header 'vmware-api-session-id: {{vsphere_key}}'
9# Cisco FirePower uses
10curl --location --globoff 'https://{{fmc_ip}}/api/fmc_config/v1/domain/{{domain_uuid}}/devices/devicerecords' \
11--header 'X-auth-access-token: {{auth_token}}'
`
Python 3
X-Auth-Token` as a custom header
1# Cisco DNA Center uses
2import requests
3import json
4import sys
5
6url = "https://sandboxdnac2.cisco.com/dna/intent/api/v1/site"
7
8payload = {}
9headers = {
10 'Content-Type': 'application/json',
11 'X-Auth-Token': '{{ token }}'
12}
13
14try:
15 response = requests.request("GET", url, headers=headers, data=payload)
16 response.raise_for_status()
17 print(response.text)
18except requests.Timeout:
19 sys.exit("TCP Timeout!")
20except HTTPError as e:
21 sys.exit("HTTP Error Found! " + do_api_request.status_code + " " + str(e))
`
Verbs
In API Terminology, clients (and servers) should identify what type of operation they intend to execute with a matching HTTP Method:
-
GET
: Read only actions, typically without a submitted payload. -
POST
: Frequently (mis)used. Can be read only, can be a non-idemopotent change, or it could be an idempotent change. By standard,POST
methods create an object in a tree or change the state machine - but nearly every vendor defaults to this method. -
PUT
: Meant to be a "safe" method that either updates an existing record, or creates a new object. Usually, if an API provider uses this verb, they're using it properly. -
PATCH
:PUT
is idempotent, which is safe from an API perspective, but not from a production service perspective. It will wipe and recreate a service - thePATCH
verb indicates a messier but production safe action. -
DELETE
: Idempotent, but it does delete a resource, so I'd be careful considering it production-safe.
Why?
Infrastructure operators benefit from programmatic interface usage, but the pattern differs.
Researching secure, well-managed authentication methods leaves a lot of room for improvement with the commodity resources available today, and a security engineer with even some basic API knowledge can quickly and easily secure resources with these rules. It's easy to imagine how firewalling an API service can quickly become secure:
`
1allow user any GET under /api/v3/healthcheck
2allow user admin PUT under /*
3deny user off-net any under /*
4deny user any DELETE under /*
`
Essentially, any load balancer can become a highly granular firewall for an API.
APIs are easy to parse due to their dictionary formats. Prior to their inception, network engineers had to write screen scrapers like Scrapli and "guess" what value in a given table has what meaning. YAML
and JSON
formats allow language-native association between values not normally present in a tab-separated table like a routing table.
The most important advantage to API automation, though, is for change safety. No matter what discipline you follow, invasive IT work is completed at night and with a strict schedule - one that does not promote thoroughness. Leverage APIs to check if your system is healthy - only you as the engineer know how to do that - and make change windows less stressful.
Some Tips
-
jq
is a command-line utility that parses JSON - and lets you navigate or prune it to relevant data. Think of it likegrep
for JSON. - If you do complex or scaled work with Python, check out
tqdm
to build progress bars for your work.
Top comments (0)