REST APIs, JSON, Configuration Management and AI
Exam topics covered
6.5 Describe characteristics of REST-based APIs (authentication types, CRUD, HTTP verbs, and data encoding)
6.6 Recognize the capabilities of configuration management mechanisms, such as Ansible and Terraform
6.7 Recognize components of JSON-encoded data
6.4 (applied) Using generative AI to assist automation work
Foundation. Chapter 33 showed that controllers expose northbound APIs and that devices increasingly offer model-driven interfaces such as RESTCONF. This chapter is about actually using them. You will learn how a REST API call is built, which HTTP verb maps to which CRUD action, what the status codes mean and how clients authenticate. You will learn to read JSON fluently, because the exam shows JSON exhibits and asks you to identify objects, arrays, keys and values or spot invalid syntax. Finally you will meet the configuration management tools Ansible and Terraform (plus Puppet and Chef in brief) and see where generative AI fits into an automation workflow.
34.1 APIs and REST
An application programming interface (API) is a defined way for one piece of software to ask another for data or to perform an action. A REST (Representational State Transfer) API is an API that follows a set of architectural constraints described by Roy Fielding in 2000 and normally uses HTTP or HTTPS as its transport. REST is popular because it reuses the web's existing machinery: URLs to name things, HTTP methods to act on them, status codes to report results, and text formats such as JSON to carry data. Any language that can make an HTTP request (Python, JavaScript, Go, even a command-line tool such as curl) can use a REST
Api.
The REST constraints you should recognize are: client-server (client and server are separate and evolve independently); stateless (each request carries everything the server needs, including authentication, and the server keeps no session state); cacheable (responses say whether they may be reused); uniform interface (resources identified by URIs and manipulated with a consistent set of methods); layered system (the client cannot tell whether proxies or load balancers sit in between); and optional code on demand.
Stateless is the REST characteristic most often tested: the server does not remember previous requests, so every request must carry its own credentials or token. REST is an architectural style, not a protocol, and it usually (not necessarily) uses HTTP and JSON.
34.2 Anatomy of a REST Request and Response
A REST interaction is one HTTP request followed by one HTTP response. Figure 34-1 shows the parts.
- HTTP request (client to server)
- GET /api/v1/network-devices?family=Switches HTTP/1.1
- Host: controller.example.com
- Accept: application/json
X-Auth-Token: eyJhbGciOiJSUzI1NiIs...
- (no body for GET; POST/PUT/PATCH carry JSON here)
- request line
- headers
- body
- HTTP response (server to client)
Http/1.1 200 ok
Figure 34-1 An HTTP request (method, URI, headers, optional body) and the response (status code, headers, body).
34.2.1 The URI
Every resource in a REST API has a Uniform Resource Identifier (URI). Figure 34-2 breaks one down. The path identifies the resource (often a collection such as network-devices , or one member of it), and the optional query string after ? filters or modifies the request with key=value pairs joined by & .
https://controller.example.com:443/api/v1/network-devices?family=Switches&limit=10 scheme host (authority) port path (resource) query parameters
api / version / collection
Figure 34-2 Structure of a REST URI. The port is usually omitted because HTTPS defaults to 443.
34.2.2 HTTP verbs and CRUD
Software that manages data performs four basic operations, remembered as CRUD: Create, Read, Update and Delete. REST maps them onto HTTP methods (verbs).
Table 34-1 HTTP verbs and CRUD operations
Http
verb
CRUD action Typical use and notes
POST Create Create a new resource in a collection (add a VLAN, request an auth token). Not idempotent: repeating it may create duplicates.
GET Read Retrieve a resource or collection. Never changes data; no body.
PUT Update
(replace)
Replace the entire resource with the representation sent (can also create at a known URI). Idempotent.
PATCH Update
(modify)
Change only the fields sent, such as one interface description.
DELETE Delete Remove the resource. Idempotent.
Exam alert
Memorize the pairs: POST = Create, GET = Read, PUT/PATCH = Update, DELETE = Delete. A favourite trick is to offer “PUT = Create” or “POST = Update”; the standard CCNA answer is POST for create and PUT or PATCH for update.
34.2.3 Response codes
The status line of every response carries a three-digit code. The first digit gives the class: 2xx success, 3xx redirection, 4xx client error (you sent something wrong), 5xx server error (the server failed).
Table 34-2 Common HTTP status codes in REST APIs
- Code Meaning Typical cause
- 200 OK Success GET returned data; PUT/PATCH succeeded
- with a body
- 201 Created Resource created Successful POST
- 204 No Content Success, no body Successful DELETE or PATCH
400 Bad Request Malformed request Invalid JSON or a missing field 401 Unauthorized Not authenticated Missing, wrong or expired credentials/token 403 Forbidden Authenticated but not
Data encoding. REST does not mandate a data format, but the request and response bodies must use one both sides understand. The common choices are JSON (by far the most common), XML and occasionally YAML. Two headers negotiate the format: Content-Type says what the body you are sending is encoded as, and Accept says what format you want back. Typical values are application/json , application/xml , and for RESTCONF application/yang-data+json or application/yang-data+xml .
34.3 REST API Authentication
Because REST is stateless, the server must authenticate every request. Always use HTTPS so credentials and tokens are encrypted in transit. The methods you need to know: Basic authentication: the client sends Authorization: Basic <base64(username:password)> . Base64 is an encoding, not encryption: anyone who captures it can decode the password, so it is only acceptable over HTTPS. RESTCONF on IOS XE commonly uses basic auth. API key: a long secret string issued by the service, sent in a header (for example X-API-Key: 7f3a... ) or, less safely, in the query string. It identifies the application rather than a user and usually does not expire unless revoked.
Bearer token: the client first authenticates once (often with basic auth) to a token endpoint and receives a time-limited token, then sends Authorization: Bearer <token> (or a vendor header such as Catalyst Center's X-Auth-Token ) on each subsequent request. Tokens are frequently JSON Web Tokens (JWT).
OAuth 2.0: an authorization framework in which an authorization server issues access tokens to a client application, often on behalf of a user who approves the access, without the application ever seeing the user's password. The resulting access token is presented as a bearer token. Common with cloud services.
Client script Controller API
- 1. POST /api/v1/auth/token Authorization: Basic bmV0YWRtaW46...
- 2. 200 OK { "token": "eyJhbGciOi..." } (valid 60 minutes)
- 3. GET /api/v1/network-devices X-Auth-Token: eyJhbGciOi...
- 4. 200 OK { "response": [ ...device list... ] }
Later requests reuse the token; once expired, the server returns 401.
Figure 34-3 Token-based authentication: credentials are sent once to obtain a token, and the token authenticates each subsequent stateless request.
34.4 Calling a REST API
curl is the quickest way to experiment with an API (Postman is a GUI equivalent; Python scripts use the requests library). Figure 34-4 shows the token flow from Figure 34-3 against a generic controller API. The -u option supplies basic-auth credentials, -X sets the method, -H adds a header, and -k accepts the lab controller's self-signed certificate (never use it in production).
- netops@automation-host: ~
- $ curl -k -s -X POST -u netadmin:Str0ngP@ss \
- https://controller.example.com/api/v1/auth/token
{"token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2NWE3..."} $ export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2NWE3...
$ curl -k -s -X GET -H "X-Auth-Token: $TOKEN" -H "Accept: application/json" \ "https://controller.example.com/api/v1/network-devices?family=Switches"
Figure 34-4 Obtaining a token with POST, then reading the switch inventory with GET. The JSON response is an object containing an array of device objects.
Creating something uses POST with a JSON body, so the request must also declare Content-Type: application/json . A controller that runs the change asynchronously replies 202 Accepted with a task ID you can poll; a simpler API replies 201 Created .
netops@automation-host: ~
$ curl -k -i -X POST -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" \ -d '{"siteName": "HQ-Bldg-1", "vlanId": 30, "name": "PRINTERS"}' \ https://controller.example.com/api/v1/vlans
- HTTP/1.1 201 Created
- Content-Type: application/json
- Location: /api/v1/vlans/7c1e2b90-4d3a-4f61-9b0e-2f6d8a1c55e4
{"id":"7c1e2b90-4d3a-4f61-9b0e-2f6d8a1c55e4","vlanId":30,"name":"PRINTERS","status":"created"}
Figure 34-5 A POST that creates a VLAN returns 201 Created and the new resource. The same request without the token would fail with 401 Unauthorized.
34.5 JSON: JavaScript Object Notation
JSON (RFC 8259) is a lightweight, human-readable text format for structured data. Despite the name it is language-independent; every modern language can read and write it. It is the default encoding for REST APIs and RESTCONF, and the CCNA expects you to identify its components.
34.5.1 Syntax rules and data types
Data is written as key/value pairs (also called name/value pairs) separated by a colon: "hostname": "R1" .
Keys are always strings in double quotes. Single quotes are not allowed anywhere. Pairs are separated by commas; there is no comma after the last item.
Curly braces { } enclose an object: an unordered set of key/value pairs.
Square brackets [ ] enclose an array: an ordered list of values separated by commas. Whitespace (spaces, tabs, line breaks) outside strings is ignored; indentation is only for humans. JSON has no comments.
Table 34-3 JSON data types
- Type Example Notes
- String "GigabitEthernet0/1" Double quotes only
- Number 1500 , -3 , 99.9 No quotes; "1500" would be a string
- Boolean true , false Lowercase, no quotes
- Null null Empty value; lowercase, no quotes
Object {"vlan": 10, "name": "USERS"} Unordered key/value pairs in braces Array [10, 20, 30] Ordered values in brackets; may hold objects 34.5.2 Reading a nested JSON document
Objects and arrays nest inside each other to any depth. Figure 34-6 annotates a typical document. Read it from the outside in: the whole thing is one object; its interfaces key holds an array; each element of that array is an object; and the ipv4 key inside each interface holds another object.
Figure 34-6 An annotated JSON document: one object containing strings, a number, a boolean, a null, an array of objects (with a nested object) and an array of strings.
Counting is a common exam task. In Figure 34-6 the outer object has six key/value pairs (hostname, uptime_days, ssh_enabled, location, interfaces, ntp_servers). There are two arrays (interfaces and ntp_servers) and four objects in total (the outer object, two interface objects and one ipv4 object). In Python, after parsing, you would reach the first interface's address with data["interfaces"][0]["ipv4"]["address"] : keys for objects, zero-based indexes for arrays.
34.5.3 Spot the invalid JSON
Try each snippet before reading the verdict in the right-hand column (cover it with a card).
Table 34-4 JSON validity exercises
- # Snippet Verdict
- 1 {"hostname": 'R1'} Invalid: strings need double quotes
- 2 {"vlans": [10, 20, 30,]} Invalid: trailing comma after 30
- 3 {hostname: "R1"} Invalid: key must be a quoted string
- 4 {"enabled": True} Invalid: booleans are lowercase true
5 {"name": "Gi0/1" "speed": 1000} Invalid: missing comma between pairs 6 {"mtu": "1500"} Valid, but the value is a string, not a number 7 ["R1", "R2"} Invalid: array opened with [ but closed with }
8 [{"id": 1}, {"id": 2}] Valid: an array of two objects
Know the punctuation cold: { } = object, [ ] = array, : separates key and value, , separates items. Keys are double-quoted strings; true , false and null are lowercase and unquoted.
34.5.4 JSON compared with XML and YAML
XML (Extensible Markup Language) uses opening and closing tags like HTML; it is verbose but supports namespaces and schemas, and it is NETCONF's encoding. YAML (YAML Ain't Markup Language) uses indentation instead of brackets, making it the most human-friendly; Ansible playbooks are written in it. Figure 34-7 encodes the same data three ways. JSON allows no comments; XML uses <!-- --> and YAML uses # .
Json xml yaml
<interface> <name>Gi0/1</name> <enabled>true</enabled> <vlans>10</vlans> <vlans>20</vlans> </interface>
Figure 34-7 The same interface data encoded in JSON, XML and YAML.
34.6 Configuration Management Tools
REST calls and scripts are great for one-off tasks, but managing hundreds of devices over years calls for configuration management tools. You declare the desired configuration in text files kept in version control (Git); the tool pushes or enforces it everywhere, detects and corrects drift, and can be rerun safely. Three properties distinguish the tools: agent-based or agentless (must software be installed on the managed device? network devices generally cannot run third-party agents, so agentless tools dominate in networking); push or pull (does a central node push changes, or do agents pull them?); and declarative or procedural (do you describe the end state, or the steps?). Closely related is idempotency: running the same automation twice changes nothing the second time if the device is already correct.
34.6.1 Ansible
Ansible (Red Hat, written in Python) is the most widely used network configuration management tool. It is agentless: it reaches devices over SSH (or NETCONF, or a REST API) with normal credentials, installing nothing on them. It uses a push model: you run it on a Linux control node and it pushes changes when you execute a playbook. An inventory file (INI or YAML) lists managed hosts in groups, with variables. Playbooks, written in YAML, contain plays that map a group of hosts to an ordered list of tasks; each task calls a module such as cisco.ios.ios_config or cisco.ios.ios_vlans , most of which are idempotent. Jinja2 templates generate configurations from variables.
Figure 34-8 Ansible architecture: an agentless control node pushes configuration defined in playbooks to the hosts listed in the inventory.
- name: Ensure NTP server is configured # a task using a module cisco.ios.ios_config:
Figure 34-9 An Ansible inventory (INI) and playbook (YAML). Note the YAML list items marked with dashes and the variable substituted with {{ }} .
- netops@automation-host: ~/ansible
- $ ansible-playbook -i inventory.ini site.yml --ask-pass
- SSH password:
PLAY [Standardize access switches] ******************************************** TASK [Ensure NTP server is configured] **************************************** changed: [sw1]
ok: [sw2]
TASK [Ensure VLANs exist] ***************************************************** changed: [sw1]
changed: [sw2]
PLAY RECAP ******************************************************************** sw1 : ok=2 changed=2 unreachable=0 failed=0 skipped=0
sw2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0
Figure 34-10 Running the playbook. sw2 already had the NTP server, so that task reports ok (no change): idempotency in action. A second run would report changed=0 for both.
34.6.2 Terraform
Terraform (HashiCorp) is an infrastructure as code tool best known for provisioning cloud resources (virtual networks, VMs, firewalls) and increasingly used for network devices and controllers. It is declarative: you describe the desired end state in .tf files written in HCL (HashiCorp Configuration Language), and Terraform works out what to create, change or destroy. Providers are plugins that talk to each platform's API (AWS, Azure, Cisco IOS XE, Catalyst Center, ACI, Meraki and hundreds more), so Terraform is agentless. Terraform records what it has built in a state file ( terraform.tfstate ) and compares configuration with state to compute changes; protect it, because it can contain secrets. The workflow is terraform init (download providers), plan (preview), apply (make the changes) and destroy (remove what it manages).
Figure 34-11 The Terraform workflow. The state file is how Terraform knows what already exists. main.tf and terraform plan
# main.tf
terraform {
required_providers { iosxe = { source = "CiscoDevNet/iosxe" } } }
Plan: 1 to add, 0 to change, 0 to destroy.
Figure 34-12 A Terraform configuration in HCL declaring one VLAN, and the plan that previews the change before terraform apply .
34.6.3 Puppet and Chef in brief
Puppet and Chef are older configuration management tools from the server world and are no longer named in the v1.1 blueprint, but you may still see them. Both are traditionally agent-based and pull-based: an agent on each managed node periodically contacts a central server and enforces its assigned configuration. Puppet uses manifests written in its own declarative language (agents talk to the Puppet server on TCP 8140); Chef uses recipes grouped into cookbooks, written in a Ruby-based language. Because most network devices cannot run agents, both have seen limited use for network gear.
Table 34-5 Configuration management tools compared
Exam alert
Ansible: agentless, push, YAML playbooks, inventory, modules. Terraform:
declarative, HCL, providers, plan/apply, state file. If a question says “requires no agent on the network device and uses SSH”, think Ansible; if it mentions “plan before apply” or a state file, think Terraform.
34.7 Generative AI in the Automation Workflow
Chapter 33 introduced predictive and generative AI. In day-to-day automation, generative AI assistants are now often used to draft a playbook, an HCL file, a Python script or a curl command from a plain-English description; to explain an unfamiliar JSON response or API error; and to convert data between formats (CLI output to JSON, JSON to YAML). Treat every such output as a first draft from an untested colleague. Validate it with tools ( ansible-playbook --syntax-check and --check dry runs, terraform validate and plan , a JSON linter); confirm that modules, resources and API paths really exist, since invented ones are a common hallucination; never paste credentials, tokens or full production configurations into an unapproved AI service (keep secrets in variables or Ansible Vault); and put the result through the same version control, peer review and lab testing as human-written code.
LAB Read and modify an interface with RESTCONF
Goal: use curl to read an interface from R1 through RESTCONF, change its description with PATCH, and confirm the change in the CLI. Use the topology and configuration from the Chapter 33 lab (Figure 33-11): automation host 192.168.10.50, R1 G1 192.168.10.1, NETCONF/RESTCONF enabled, user netadmin . (Output is illustrative of IOS XE 17.x.) Steps: (1) GET the interface using the IETF interfaces YANG model, asking for JSON with Accept: application/yang-data+json ; (2) PATCH a new description, sending JSON with the matching Content-Type ; (3) verify with show interfaces description on R1. netops@automation-host: ~
$ curl -k -s -u netadmin:Str0ngP@ss -H "Accept: application/yang-data+json" \ https://192.168.10.1/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet2 {
"address": [ { "ip": "10.0.12.1", "netmask": "255.255.255.252" } ] }
}
}
$ curl -k -s -o /dev/null -w "%{http_code}\n" -X PATCH -u netadmin:Str0ngP@ss \ -H "Content-Type: application/yang-data+json" \
-d '{"ietf-interfaces:interface": {"name": "GigabitEthernet2", "description": "UPLINK-TO-SW1"}}' \ https://192.168.10.1/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet2 204
R1# show interfaces description
Figure 34-13 A RESTCONF GET returns YANG-modelled JSON; a PATCH returns 204 No Content, and the CLI confirms the new description.
Expected results: the GET returns HTTP 200 with the JSON shown; the PATCH returns 204; the CLI shows the new description. A wrong password returns 401, and a misspelled interface name returns 404.
Chapter review
Key terms
Api
Rest
stateless
Uri
query parameter
Crud
Json
- object
- array
- key/value pair
Xml
Yaml
- idempotent
- Ansible
- playbook
- inventory
- Terraform
Hcl
state file
Review questions
- 1. Which HTTP verb corresponds to the CRUD Create operation in a REST API?
- A. GET
- B. PUT
- C. POST
- D. PATCH
- 2. Which two HTTP verbs are used for the CRUD Update operation? (Choose two.)
- A. POST
- B. PUT
- C. GET
- D. PATCH
- E. DELETE
- 3. What does it mean that REST APIs are stateless?
- A. The server stores session data between requests.
- B. Each request contains all the information needed to process it, including authentication.
- C. Responses can never be cached.
- D. Only GET requests are allowed.
- 4. A script receives HTTP status code 401 from a controller. What is the most likely cause?
- A. The URI does not exist.
- B. The server crashed.
- C. The token is missing or expired.
- D. The resource was created successfully.
- 5. Which statement about HTTP basic authentication is true?
- A. It encrypts the password with AES.
- B. It sends Base64-encoded credentials and should be used only over HTTPS.
- C. It requires an OAuth authorization server.
- D. It sends a one-time token issued by the server.
- 6. Refer to Figure 34-6. What type of value is associated with the key interfaces ?
- A. Object
- B. String
- C. Array
- D. Boolean
- 7. Which JSON snippet is valid?
- A. {'vlan': 10}
- B. {"vlan": 10,}
- C. {"vlan": 10, "active": true}
- D. {"active": TRUE}
- 8. In JSON, what do square brackets enclose?
- A. An object of key/value pairs
- B. An ordered list of values
- C. A comment
- D. A string
- 9. Which two characteristics describe Ansible? (Choose two.)
- A. It requires an agent on every managed device.
- B. Playbooks are written in YAML.
- C. It uses a pull model with a central server.
- D. It is agentless and typically connects over SSH.
- E. Configuration is written in HCL.
- 10. Which Terraform command previews the changes it will make without applying them?
- A. terraform init
- B. terraform plan
- C. terraform apply
- D. terraform show-run
- 11. What does Terraform use to track the resources it manages?
- A. An inventory file
- B. A state file
- C. A cookbook
- D. An SNMP MIB
- 12. Which HTTP header tells the server the format of the data in the request body?
- A. Accept
- B. Content-Type
- C. Authorization
- D. Host
Answers
- 1. C. POST creates a resource. GET reads, PUT/PATCH update.
- 2. B, D. PUT replaces a resource and PATCH modifies part of it; both are updates.
- 3. B. The server keeps no client session state, so each request carries its own context and credentials.
- 4. C. 401 Unauthorized means authentication failed or was missing. 404 is a wrong URI; 5xx is a server failure; 201 is created.
- 5. B. Base64 is reversible encoding, not encryption, so basic auth must be protected by
Https.
- 6. C. The value of interfaces begins with [ , so it is an array (of objects).
- 7. C. A uses single quotes, B has a trailing comma, D uses uppercase TRUE.
- 8. B. Brackets enclose an array, an ordered list. Braces enclose objects; JSON has no comments.
- 9. B, D. Ansible is agentless, pushes over SSH (or APIs) and uses YAML playbooks. HCL belongs to Terraform.
- 10. B. terraform plan shows the additions, changes and deletions that apply would make.
- 11. B. The state file (terraform.tfstate) records managed resources. Inventories are Ansible; cookbooks are Chef.
- 12. B. Content-Type describes the body being sent; Accept states the format wanted in the response.