Learn › BMC & Server Management › Modern Management
Meet Redfish, the modern management API. Walk a live BMC's REST tree with curl, authenticate, extract values with jq, and map Systems, Chassis, and Managers on a real machine.
It is 07:52 at the DC-EAST facility in Ashburn, Virginia. Next month a new expansion rack lands in Row 12, and the spec sheet has one line the NOC keeps rereading: the BMCs in those machines speak only Redfish. No IPMI. Every power check, every sensor poll, every script the fleet tooling team runs today would bounce off them.
Work Order DC-EAST-WO-1011: pilot the new protocol on a machine everyone trusts. That machine is the Dell PowerEdge R750xs in Bay 14, Row 7, the same server you have managed over IPMI since it arrived. Its iDRAC has spoken Redfish this whole time. Nobody has ever asked.
Your job: authenticate to the Redfish API, walk it end to end, and deliver a resource map the fleet team can port their tooling against.
The twist that carries this lesson: the client for this job is not some vendor download. It is curl, and it is already on practically every Linux box you have ever touched.
This is a Practice Zone. The diagrams below react to you: click the boxes, flip the switches. The real machine comes at the end, under Ready to practice.
Redfish is the management standard the DMTF (Distributed Management Task Force, the standards body for hardware management) published in 2015 as the planned successor to IPMI. The difference is not what you can do. It is how you ask.
IPMI is binary packets over UDP port 623, readable only by a purpose-built tool. Redfish is a REST API: you request a URL over plain HTTP, and the answer comes back as JSON, structured text that humans can read and every programming language can parse. Same controller, same sensors, same power control. New language at a new door.
{ "height": 320, "caption": "One controller, two protocols. Click any box, then flip the era.", "nodes": [ { "id": "you", "label": "dc-east-ws01", "kind": "admin", "x": 0, "y": 170, "detail": "Your workstation, where curl and jq already live. No vendor client needed for Redfish." }, { "id": "ipmi-door", "label": "UDP 623 (IPMI)", "kind": "nic", "x": 420, "y": 40, "detail": "Binary packets, cipher suites, a special client tool: ipmitool. Born 1998." }, { "id": "rf-door", "label": "HTTP :5000 (Redfish)", "kind": "nic", "x": 420, "y": 300, "detail": "Plain HTTP requests carrying JSON. Any HTTP client works: curl, Python, even a browser. DMTF standard, born 2015. This lab BMC serves it on port 5000." }, { "id": "bmc", "label": "BMC (iDRAC)", "kind": "bmc", "x": 800, "y": 170, "detail": "One iDRAC-style controller answering both protocols. Same sensors, same power control, two languages." } ], "edges": [ { "from": "you", "to": "ipmi-door", "label": "ipmitool -I lanplus -C 3", "kind": "oob" }, { "from": "ipmi-door", "to": "bmc", "kind": "oob" }, { "from": "you", "to": "rf-door", "label": "curl + jq", "kind": "mgmt" }, { "from": "rf-door", "to": "bmc", "kind": "mgmt" } ], "toggle": { "label": "Tooling era:", "on": "Redfish (REST + JSON)", "off": "Legacy IPMI", "dimOn": ["ipmi-door", "e:you-ipmi-door", "e:ipmi-door-bmc"], "dimOff": ["rf-door", "e:you-rf-door", "e:rf-door-bmc"] } }
Click both doors, then flip the era. Notice what does not change: the BMC. Redfish is not new hardware or a new wire. It is a new language on the always-on controller you already know.
>>> An ordinary HTTP request. That is the whole point: no special client, no cipher-suite flags, any language with an HTTP library can manage a server. Your monitoring stack, your Python scripts, even a browser can speak it.
A management API that answered strangers would be a disaster, so Redfish refuses to say anything without credentials. Try knocking without any and read the refusal. $BMC_IP is preset here, exactly like the lab.
prompt: ops@dc-east-ws01:~$ answer: curl -s http://$BMC_IP:5000/redfish/v1/ output: {"error": {"code": "Base.1.0.AccessDenied", "message": "Authentication required"}} hint: Type it exactly: curl -s http://$BMC_IP:5000/redfish/v1/
That one line of JSON is the API saying no. On the wire it arrived with HTTP status 401 Unauthorized: the server understood you perfectly and refused anyway. The -s flag just keeps curl quiet about progress meters; the missing piece is identity.
The fix is one flag. -u ADMIN:ADMIN attaches a username and password to the request using HTTP Basic authentication, the simplest auth scheme on the web. They are the same credentials the IPMI side of this controller has used all track long.
{ "height": 300, "caption": "Same URL, same GET. Credentials alone decide which answer comes back.", "nodes": [ { "id": "you", "label": "dc-east-ws01", "kind": "admin", "x": 0, "y": 170, "detail": "Every request starts here: curl on your workstation." }, { "id": "api", "label": "Redfish API :5000", "kind": "bmc", "x": 420, "y": 170, "detail": "Every path under /redfish/v1 demands credentials before it says anything at all." }, { "id": "denied", "label": "401 AccessDenied", "kind": "sensor", "x": 820, "y": 40, "detail": "The exact body this BMC returns: error code Base.1.0.AccessDenied, message Authentication required." }, { "id": "granted", "label": "200 + JSON", "kind": "host", "x": 820, "y": 300, "detail": "With -u ADMIN:ADMIN the same GET returns the resource as JSON, ready for jq." } ], "edges": [ { "from": "you", "to": "api", "label": "GET /redfish/v1/", "kind": "mgmt" }, { "from": "api", "to": "denied", "label": "no -u flag", "kind": "plain" }, { "from": "api", "to": "granted", "label": "-u ADMIN:ADMIN", "kind": "oob" } ], "toggle": { "label": "Credentials:", "on": "-u ADMIN:ADMIN", "off": "None", "dimOn": ["denied", "e:api-denied"], "dimOff": ["granted", "e:api-granted"] } }
>>> The same 401, verified against this very BMC. Wrong key and no key look identical. A well-behaved API never hints at which half of the credentials you got wrong, because that hint is exactly what an attacker wants.
Knock again, credentials in hand. This time the door opens.
prompt: ops@dc-east-ws01:~$ answer: curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/ output: {"@odata.id":"/redfish/v1/","@odata.type":"#ServiceRoot.v1_11_0.ServiceRoot","AccountService":{"@odata.id":"/redfish/v1/AccountService"},"Chassis":{"@odata.id":"/redfish/v1/Chassis"},"Id":"RootService","Managers":{"@odata.id":"/redfish/v1/Managers"},"Name":"Root Service","Product":"Integrated Dell Remote Access Controller","RedfishVersion":"1.13.0","Systems":{"@odata.id":"/redfish/v1/Systems"},"UUID":"92384634-2938-2342-8820-489239905423","Vendor":"Dell Inc."} hint: Same GET as before, plus -u ADMIN:ADMIN before the URL.
There is the resource: one compressed line, every byte accounted for. Machines love that format. Humans do not, and the fix is jq, the JSON processor, already on this workstation and one package install away anywhere else. Its simplest filter, a lone ., means "the whole document", so piping through jq . pretty-prints whatever arrives:
ops@dc-east-ws01:~$ curl -s -u ADMIN:ADMIN http://$BMC_IP:5000/redfish/v1/ | jq .
{
"@odata.id": "/redfish/v1/",
"@odata.type": "#ServiceRoot.v1_11_0.ServiceRoot",
"AccountService": {
"@odata.id": "/redfish/v1/AccountService"
},
"Chassis": {
"@odata.id": "/redfish/v1/Chassis"
},
"Id": "RootService",
"Managers": {
"@odata.id": "/redfish/v1/Managers"
},
"Name": "Root Service",
"Product": "Integrated Dell Remote Access Controller",
"RedfishVersion": "1.13.0",
"Systems": {
"@odata.id": "/redfish/v1/Systems"
},
"UUID": "92384634-2938-2342-8820-489239905423",
"Vendor": "Dell Inc."
}
Now read it like an operator. Systems, Chassis, and Managers each carry a single field named @odata.id, and that field is a link: a path you can request next. The whole API works like a book where every chapter ends with pointers to the next one. You never memorize deep URLs; you start here, at the service root, and follow links. The rest is the cover page: Vendor Dell Inc., RedfishVersion 1.13.0, and a Product string naming the iDRAC. This document is the table of contents for the entire machine.
Everything you will ever ask this BMC lives under one of the three links you just found. The map below is the whole walk for this work order. Click every node, then flip the branch toggle.
{ "height": 420, "caption": "The API is a book of links. Flip the branch to compare the logical and physical views. Managers stays lit both ways: the BMC is always there, watching.", "nodes": [ { "id": "root", "label": "/redfish/v1/", "kind": "bmc", "x": 0, "y": 190, "detail": "The service root: the table of contents. Every walk starts here." }, { "id": "syscol", "label": "Systems", "kind": "net", "x": 260, "y": 40, "detail": "/redfish/v1/Systems, the logical computers this BMC manages. [email protected]: 1" }, { "id": "sys1", "label": "Systems/1", "kind": "host", "x": 540, "y": 40, "detail": "The machine as software sees it: Model PowerEdge R750xs, Serial SVC1234567, PowerState On, 2 CPUs with 32 cores total, 128 GiB of memory, plus the Actions object." }, { "id": "chcol", "label": "Chassis", "kind": "net", "x": 260, "y": 190, "detail": "/redfish/v1/Chassis, the physical sheet metal." }, { "id": "ch1", "label": "Chassis/1", "kind": "psu", "x": 540, "y": 190, "detail": "RackMount enclosure in Bay 14, Row 7: part number 0CNCJWA08, with links to Thermal and Power." }, { "id": "thermal", "label": "Thermal", "kind": "sensor", "x": 820, "y": 120, "detail": "4 temperatures and 6 fans, live readings with thresholds attached." }, { "id": "power", "label": "Power", "kind": "psu", "x": 820, "y": 260, "detail": "PowerControl: 500 W consumed of 2200 W capacity, plus both power supplies." }, { "id": "mgrcol", "label": "Managers", "kind": "net", "x": 260, "y": 340, "detail": "/redfish/v1/Managers, the BMCs themselves." }, { "id": "mgr1", "label": "Managers/1", "kind": "bmc", "x": 540, "y": 340, "detail": "The iDRAC itself: ManagerType BMC, firmware 6.10.30.00. The API describing its own brain." } ], "edges": [ { "from": "root", "to": "syscol", "label": "@odata.id", "kind": "mgmt" }, { "from": "syscol", "to": "sys1", "label": "Members[0]", "kind": "mgmt" }, { "from": "root", "to": "chcol", "kind": "mgmt" }, { "from": "chcol", "to": "ch1", "label": "Members[0]", "kind": "mgmt" }, { "from": "ch1", "to": "thermal", "label": ".Thermal", "kind": "mgmt" }, { "from": "ch1", "to": "power", "label": ".Power", "kind": "mgmt" }, { "from": "root", "to": "mgrcol", "kind": "mgmt" }, { "from": "mgrcol", "to": "mgr1", "label": "Members[0]", "kind": "mgmt" } ], "toggle": { "label": "Branch:", "on": "Logical (the computer)", "off": "Physical (the enclosure)", "dimOn": ["chcol", "ch1", "thermal", "power", "e:root-chcol", "e:chcol-ch1", "e:ch1-thermal", "e:ch1-power"], "dimOff": ["syscol", "sys1", "e:root-syscol", "e:syscol-sys1"] } }
The mental model that makes Redfish click: Systems is the computer as software sees it (model, serial, CPUs, memory, power state). Chassis is the sheet metal (temperatures, fans, power supplies, part numbers). Managers is the BMC itself, the API describing its own brain, firmware version and all. One machine, three honest answers to the question "what are you?".
>>> Chassis. Redfish splits logical from physical: a fan cools an enclosure, so it lives with the sheet metal at /redfish/v1/Chassis/1/Thermal, even though the BMC (the Managers branch) is the thing doing the measuring.
Walk down to the system record and look at one section you have not decoded yet: Actions. This is the API declaring its levers. Here is exactly what this BMC returns for it:
{
"#ComputerSystem.Reset": {
"[email protected]": [
"On",
"ForceOff",
"ForceRestart",
"GracefulShutdown",
"PushPowerButton"
],
"target": "/redfish/v1/Systems/1/Actions/ComputerSystem.Reset"
}
}
Read it like an operator. #ComputerSystem.Reset is the one lever this system exposes. The target is the URL a POST request would go to; POST is the HTTP verb that changes things, where GET only reads. And the AllowableValues list is the exact set of parameters the lever accepts: five ways to push the power button, from a hard ForceOff to a polite GracefulShutdown.
Today is discovery. Every request in this work order is a GET, strictly read-only. Pulling those levers is a later work order, and when it lands you will already know exactly where the target is.
This BMC is a standards-faithful emulator: real Redfish JSON over HTTP on port 5000 with Basic auth. A production iDRAC serves the identical API over HTTPS on port 443, adds session-token login for scripts, and exposes a far larger resource tree. Every URL, flag, and jq move you learn here transfers unchanged.
Time to do it for real. Work Order DC-EAST-WO-1011 closes when the Bay 14 iDRAC is walked, read, and mapped. The API lives at http://$BMC_IP:5000/redfish/v1/, credentials ADMIN / ADMIN, and $BMC_IP is preset on your workstation.
Six objectives stand between this pilot and the fleet team porting their tooling:
1. Read the table of contents. Pull the service root, authenticated and formatted for human eyes. 2. File the machine record. The full system record, saved to ~/redfish-system.json. 3. Capture the thermal readout. The enclosure's temperatures and fans, saved to ~/redfish-thermal.json. 4. One number for the NOC. The live power draw in watts, the number only, in ~/redfish-watts.txt. 5. Document the levers. The power actions this API exposes, saved to ~/redfish-actions.json. 6. The challenge. Deliver the resource map ~/redfish-map.txt covering all three branches. No hints on this one.
Here is the deal: the workspace shows no commands. It hands you one objective at a time, and you recall the move. That recall is the whole point; it is how last hour's reading becomes your skill.
Stuck is normal. Hit Request a signal on any objective for a nudge, or ask Daemon. It knows exactly which task you are on and will nudge, not spoil.
Your workstation dc-east-ws01 is booting in the bay below, with the Bay 14 iDRAC beside it on the management network. curl and jq are installed, $BMC_IP is preset, and the API answers on port 5000. Launch it and map the machine.
Practice Redfish Discovery in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.