Skill: eddygk/idrac (version 1.1.0)

--- name: idrac description: | Monitor and manage Dell PowerEdge servers via iDRAC Redfish API (iDRAC 8/9). Use when asked to: - Check server hardware status, health, or temperatures - Query CPU, memory, storage/RAID details - Monitor system sensors (fans, voltage, thermal) - Perform power operations (status, on, off, graceful shutdown, force restart) - Check BIOS/firmware versions or system inventory - View system event logs (SEL) or lifecycle controller logs - Get hardware inventory or serial numbers Requires: curl, jq. Optional: 1Password CLI (op) for credential hydration. Writes: ~/.config/idrac-skill/config (user-created), ~/.idrac-credentials (cached credentials, mode 600). Network: connects to user-configured iDRAC IP only (HTTPS, TLS verification disabled for self-signed certs). Helper script: scripts/idrac.sh (relative to this skill) Configuration: ~/.config/idrac-skill/config metadata: { "openclaw": { "emoji": "🖥️", "requires": { "bins": ["curl", "jq"] }, "os": ["darwin", "linux"] } } --- # iDRAC Skill Monitor and manage Dell PowerEdge servers via iDRAC Redfish API. ## First-Time Setup Create a config file at `~/.config/idrac-skill/config`: ```bash mkdir -p ~/.config/idrac-skill cat > ~/.config/idrac-skill/config <<'EOF' # iDRAC connection settings IDRAC_IP="<your-idrac-ip>" # Credential source: "1password" | "file" | "env" CREDS_SOURCE="file" # For CREDS_SOURCE="1password": # OP_ITEM="<1password-item-name>" # # For CREDS_SOURCE="file": # Create ~/.idrac-credentials with contents: username:password # chmod 600 ~/.idrac-credentials # # For CREDS_SOURCE="env": # Export IDRAC_USER and IDRAC_PASS EOF ``` ## Authentication The helper script supports three credential sources: | Source | Config | How It Works | |--------|--------|--------------| | **1password** | `OP_ITEM="item-name"` | Pulls username:password via `op` CLI, caches to `~/.idrac-credentials` | | **file** | (default) | Reads `~/.idrac-credentials` (format: `user:pass`, mode 600) | | **env** | — | Uses `$IDRAC_USER` and `$IDRAC_PASS` environment variables | ## Helper Script Location: `scripts/idrac.sh` (relative to this skill directory) ```bash idrac.sh test # Test connectivity and authentication idrac.sh status # System summary (model, power, CPU, memory) idrac.sh health # Health checks (temps, fans, power) idrac.sh power # Current power state idrac.sh inventory # Full hardware inventory idrac.sh logs # Recent system event log entries (last 10) idrac.sh thermal # Detailed temperature and fan status idrac.sh storage # RAID/disk status idrac.sh reset-types # Available power reset types ``` ## Workflow 1. **Load config** from `~/.config/idrac-skill/config` 2. **Hydrate credentials** (JIT pattern) if needed 3. **Determine operation type:** - **Read-only** (status, health, logs, inventory) → Execute directly - **Destructive** (power off, restart, BIOS changes) → Confirm with user first 4. **Query Redfish API** via curl + Basic Auth (or session token for batch ops) 5. **Parse JSON** with jq 6. **Surface findings** to user in natural language 7. **Never expose credentials** in responses ## Endpoint Reference For raw Redfish API endpoints (system info, thermal, storage, network, logs, power ops, BIOS, firmware, session auth, Dell OEM attributes): → See [references/endpoints.md](references/endpoints.md) ## Security Notes - **Never log or display credentials** — use `--silent` and pipe to jq - **Credential file** must be mode 600 (`chmod 600 ~/.idrac-credentials`) - **TLS verification disabled** (`-k`) — iDRAC uses self-signed certs (acceptable for private networks) - **Power operations are destructive** — confirm with user before executing shutdown/restart ## Compatibility Works with Dell iDRAC 8 (Redfish 1.0–1.4) and iDRAC 9 (Redfish 1.6+). Covers PowerEdge 13th gen (R630/R730) through current gen. See endpoints reference for version-specific notes. **Note:** iDRAC 8 API responses can take 5–10s per call. The `test` command makes 4 sequential calls (~30–40s total). Set exec timeouts accordingly. iDRAC 9 is significantly faster.

path: references/endpoints.md
content: # iDRAC Redfish API Endpoint Reference

All examples use the helper script's `api_get` pattern. For raw curl:
```bash
curl -k -s -u "$(cat "$CREDS_FILE")" "https://${IDRAC_IP}/redfish/v1${ENDPOINT}"
```

## Table of Contents

- [System Information](#system-information)
- [Thermal & Power](#thermal--power)
- [Storage](#storage)
- [Network](#network)
- [Logs & Events](#logs--events)
- [Managers (iDRAC itself)](#managers-idrac-itself)
- [BIOS Settings](#bios-settings)
- [Firmware Inventory](#firmware-inventory)
- [Dell OEM Attributes](#dell-oem-attributes)
- [Session-Based Authentication](#session-based-authentication)
- [Power Operations](#power-operations)

---

## System Information

```bash
# Root service
api_get "/" | jq

# Systems collection
api_get "/Systems" | jq

# Main system
api_get "/Systems/System.Embedded.1" | jq

# Quick summary
api_get "/Systems/System.Embedded.1" | \
  jq '{Model, Manufacturer, SerialNumber, PowerState, ProcessorSummary, MemorySummary}'
```

## Thermal & Power

```bash
# Thermal (temps, fans)
api_get "/Chassis/System.Embedded.1/Thermal" | jq

# Power (supplies, voltage, consumption)
api_get "/Chassis/System.Embedded.1/Power" | jq

# Current power consumption
api_get "/Chassis/System.Embedded.1/Power" | \
  jq '.PowerControl[0].PowerConsumedWatts'
```

## Storage

```bash
# Storage controllers
api_get "/Systems/System.Embedded.1/Storage" | jq

# Specific controller (e.g., RAID.Integrated.1-1)
api_get "/Systems/System.Embedded.1/Storage/RAID.Integrated.1-1" | jq

# Physical disks
api_get "/Systems/System.Embedded.1/Storage/RAID.Integrated.1-1" | \
  jq '.Drives[]'
```

## Network

```bash
# Network adapters
api_get "/Systems/System.Embedded.1/NetworkAdapters" | jq

# Network interfaces
api_get "/Systems/System.Embedded.1/EthernetInterfaces" | jq
```

## Logs & Events

```bash
# System Event Log (SEL)
api_get "/Managers/iDRAC.Embedded.1/Logs/Sel" | jq

# Lifecycle Controller Log (LCLog)
api_get "/Managers/iDRAC.Embedded.1/Logs/Lclog" | jq
```

## Managers (iDRAC itself)

```bash
# iDRAC manager info
api_get "/Managers/iDRAC.Embedded.1" | jq

# iDRAC firmware version
api_get "/Managers/iDRAC.Embedded.1" | \
  jq '{Firmware: .FirmwareVersion, Model: .Model, Status: .Status}'
```

## BIOS Settings

```bash
# BIOS configuration
api_get "/Systems/System.Embedded.1/Bios" | jq

# Pending BIOS changes
api_get "/Systems/System.Embedded.1/Bios/Settings" | jq
```

## Firmware Inventory

```bash
# All firmware versions (BIOS, iDRAC, NICs, RAID, etc.)
api_get "/UpdateService/FirmwareInventory" | jq

# Filter by component name
api_get "/UpdateService/FirmwareInventory" | \
  jq '.Members[] | select(.Name | contains("BIOS"))'
```

## Dell OEM Attributes

```bash
# Dell-specific attributes (boot state, POST codes, etc.)
api_get "/Managers/iDRAC.Embedded.1/Attributes" | jq

# System boot progress
api_get "/Managers/iDRAC.Embedded.1/Attributes" | \
  jq '.Attributes | with_entries(select(.key | contains("ServerBoot")))'
```

## Session-Based Authentication

For multiple API calls, session tokens are more efficient than Basic Auth per-request:

```bash
# Create session (returns X-Auth-Token in headers)
SESSION_RESPONSE=$(curl -k -i -X POST \
  -H "Content-Type: application/json" \
  -d "{\"UserName\":\"${IDRAC_USER}\",\"Password\":\"${IDRAC_PASS}\"}" \
  "https://${IDRAC_IP}/redfish/v1/SessionService/Sessions")

# Extract session token
SESSION_TOKEN=$(echo "$SESSION_RESPONSE" | grep -i "X-Auth-Token:" | awk '{print $2}' | tr -d '\r')

# Use session token for subsequent calls
curl -k -H "X-Auth-[REDACTED_SECRET]" \
  "https://${IDRAC_IP}/redfish/v1/Systems/System.Embedded.1" | jq

# Delete session when done
SESSION_URI=$(echo "$SESSION_RESPONSE" | grep -i "Location:" | awk '{print $2}' | tr -d '\r')
curl -k -X DELETE -H "X-Auth-[REDACTED_SECRET]" "${SESSION_URI}"
```

## Power Operations

```bash
# Power state
api_get "/Systems/System.Embedded.1" | jq -r '.PowerState'

# Power on (if off)
curl -k -s -u "$(cat "$CREDS_FILE")" \
  -X POST -H "Content-Type: application/json" \
  -d '{"ResetType":"On"}' \
  "https://${IDRAC_IP}/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset"

# Graceful shutdown
curl -k -s -u "$(cat "$CREDS_FILE")" \
  -X POST -H "Content-Type: application/json" \
  -d '{"ResetType":"GracefulShutdown"}' \
  "https://${IDRAC_IP}/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset"

# Force restart
curl -k -s -u "$(cat "$CREDS_FILE")" \
  -X POST -H "Content-Type: application/json" \
  -d '{"ResetType":"ForceRestart"}' \
  "https://${IDRAC_IP}/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset"

# Available reset types
api_get "/Systems/System.Embedded.1" | \
  jq '.Actions."#ComputerSystem.Reset"."[REDACTED_SECRET]"'
```

## Common Queries

```bash
# Is the server healthy?
api_get "/Systems/System.Embedded.1" | \
  jq '{Health: .Status.Health, State: .Status.State, PowerState}'

# CPU/Memory summary
api_get "/Systems/System.Embedded.1" | \
  jq '{Processors: .ProcessorSummary, Memory: .MemorySummary}'

# Current temperatures
api_get "/Chassis/System.Embedded.1/Thermal" | \
  jq '.Temperatures[] | {Name, ReadingCelsius, Status}'

# Fan speeds
api_get "/Chassis/System.Embedded.1/Thermal" | \
  jq '.Fans[] | {Name, Reading, Units, Status}'
```

## Compatibility

| iDRAC Version | Redfish | Notes |
|---------------|---------|-------|
| iDRAC 8 (v2.40+) | 1.0–1.4 | R630/R730/R930 era. OEM Dell extensions. |
| iDRAC 9 (v3.x+) | 1.6+ | R640/R740/R940 era. Richer Redfish, Telemetry support. |

Most endpoints above work on both. iDRAC 9 adds:
- `/redfish/v1/TelemetryService` — streaming metrics
- Expanded `/Managers/iDRAC.Embedded.1/Oem/Dell/` namespace
- SSE (Server-Sent Events) for real-time alerts

## References

- [DMTF Redfish Specification](https://www.dmtf.org/standards/redfish)
- [Dell iDRAC Redfish Scripting (GitHub)](https://github.com/dell/iDRAC-Redfish-Scripting)


path: scripts/idrac.sh
content: #!/usr/bin/env bash
# iDRAC Redfish API Helper Script
# Supports iDRAC 8/9 on Dell PowerEdge servers

set -euo pipefail

CONFIG_FILE="${IDRAC_CONFIG:-$HOME/.config/idrac-skill/config}"
CREDS_FILE="$HOME/.idrac-credentials"

# Load configuration
load_config() {
  if [ ! -f "$CONFIG_FILE" ]; then
    echo "Error: Config not found at $CONFIG_FILE" >&2
    echo "Create it with:" >&2
    echo "  mkdir -p ~/.config/idrac-skill" >&2
    echo "  cat > ~/.config/idrac-skill/config <<EOF" >&2
    echo '  IDRAC_IP="<your-idrac-ip>"' >&2
    echo '  CREDS_SOURCE="file"  # or "1password" or "env"' >&2
    echo "  EOF" >&2
    exit 1
  fi
  # shellcheck source=/dev/null
  source "$CONFIG_FILE"

  if [ -z "${IDRAC_IP:-}" ]; then
    echo "Error: IDRAC_IP not set in $CONFIG_FILE" >&2
    exit 1
  fi

  IDRAC_BASE="https://${IDRAC_IP}/redfish/v1"
  CREDS_SOURCE="${CREDS_SOURCE:-file}"
}

# Hydrate credentials based on configured source
hydrate_creds() {
  case "${CREDS_SOURCE}" in
    1password)
      if [ ! -f "$CREDS_FILE" ]; then
        local op_item="${OP_ITEM:?OP_ITEM not set in config}"
        echo "Hydrating credentials from 1Password ($op_item)..." >&2
        op item get "$op_item" --fields username,password --format json | \
          jq -r '"\(.[0].value):\(.[1].value)"' > "$CREDS_FILE"
        chmod 600 "$CREDS_FILE"
      fi
      ;;
    env)
      if [ -z "${IDRAC_USER:-}" ] || [ -z "${IDRAC_PASS:-}" ]; then
        echo "Error: IDRAC_USER and IDRAC_PASS must be set for CREDS_SOURCE=env" >&2
        exit 1
      fi
      # Write ephemeral creds file for curl
      echo "${IDRAC_USER}:${IDRAC_PASS}" > "$CREDS_FILE"
      chmod 600 "$CREDS_FILE"
      ;;
    file)
      if [ ! -f "$CREDS_FILE" ]; then
        echo "Error: Credentials file not found at $CREDS_FILE" >&2
        echo "Create it: echo 'username:password' > $CREDS_FILE && chmod 600 $CREDS_FILE" >&2
        exit 1
      fi
      ;;
    *)
      echo "Error: Unknown CREDS_SOURCE '$CREDS_SOURCE' (use: 1password, file, env)" >&2
      exit 1
      ;;
  esac
}

# API call wrapper
api_get() {
  local endpoint="$1"
  hydrate_creds
  curl -k -s -u "$(cat "$CREDS_FILE")" "${IDRAC_BASE}${endpoint}"
}

# Load config before any command
load_config

# Commands
case "${1:-help}" in
  status)
    echo "=== System Status ==="
    api_get "/Systems/System.Embedded.1" | jq '{
      Model,
      Manufacturer,
      ServiceTag: .SKU,
      PowerState,
      Health: .Status.Health,
      State: .Status.State,
      BiosVersion,
      Processors: .ProcessorSummary.Count,
      LogicalProcessors: .ProcessorSummary.LogicalProcessorCount,
      MemoryGB: .MemorySummary.TotalSystemMemoryGiB
    }'
    ;;

  health)
    echo "=== Health Status ==="
    api_get "/Systems/System.Embedded.1" | jq -r '
      "Overall Health: \(.Status.Health)",
      "State: \(.Status.State)",
      "Power: \(.PowerState)"
    '
    echo ""
    echo "=== Thermal Status ==="
    api_get "/Chassis/System.Embedded.1/Thermal" | jq -r '
      "Temperatures:",
      (.Temperatures[] | "  \(.Name): \(.ReadingCelsius)°C [\(.Status.Health)]"),
      "",
      "Fans:",
      (.Fans[] | "  \(.Name): \(.Reading) \(.Units) [\(.Status.Health)]")
    '
    ;;

  power)
    api_get "/Systems/System.Embedded.1" | jq -r '.PowerState'
    ;;

  inventory)
    echo "=== Hardware Inventory ==="
    api_get "/Systems/System.Embedded.1" | jq '{
      System: {
        Model,
        Manufacturer,
        SerialNumber,
        ServiceTag: .SKU,
        BiosVersion
      },
      Processors: .ProcessorSummary,
      Memory: .MemorySummary
    }'
    ;;

  logs)
    echo "=== System Event Log (last 10) ==="
    api_get "/Managers/iDRAC.Embedded.1/Logs/Sel" | \
      jq -r '.Members[:10][] | "\(.Created) [\(.Severity)]: \(.Message)"'
    ;;

  thermal)
    echo "=== Thermal Details ==="
    api_get "/Chassis/System.Embedded.1/Thermal" | jq '{
      Temperatures: [.Temperatures[] | {
        Name,
        Reading: .ReadingCelsius,
        Upper: .UpperThresholdCritical,
        Status: .Status.Health
      }],
      Fans: [.Fans[] | {
        Name,
        Speed: .Reading,
        Units,
        Status: .Status.Health
      }]
    }'
    ;;

  storage)
    echo "=== Storage Controllers ==="
    api_get "/Systems/System.Embedded.1/Storage" | \
      jq -r '.Members[]."@odata.id"' | while read -r controller; do
        echo ""
        echo "Controller: $controller"
        api_get "$controller" | jq '{
          Name,
          Model: .StorageControllers[0].Model,
          Status: .StorageControllers[0].Status,
          Drives: [.Drives[]."@odata.id"]
        }'
      done
    ;;

  reset-types)
    echo "=== Available Reset Types ==="
    api_get "/Systems/System.Embedded.1" | \
      jq -r '.Actions."#ComputerSystem.Reset"."[REDACTED_SECRET]"[]'
    ;;

  test)
    echo "Testing iDRAC connectivity and authentication..."
    echo "Target: ${IDRAC_IP}"
    echo "Credential source: ${CREDS_SOURCE}"
    echo ""

    # Test 1: Network connectivity
    echo -n "1. Network connectivity... "
    if curl -k -s --connect-timeout 5 "https://${IDRAC_IP}/redfish/v1/" > /dev/null 2>&1; then
      echo "✅ OK"
    else
      echo "❌ FAILED (cannot reach ${IDRAC_IP})"
      exit 1
    fi

    # Test 2: Authentication
    echo -n "2. Credential hydration (${CREDS_SOURCE})... "
    hydrate_creds
    if [ -f "$CREDS_FILE" ]; then
      echo "✅ OK"
    else
      echo "❌ FAILED"
      exit 1
    fi

    # Test 3: API access
    echo -n "3. API access (Redfish root)... "
    RESPONSE=$(api_get "/" 2>&1)
    if echo "$RESPONSE" | jq -e '.RedfishVersion' > /dev/null 2>&1; then
      VERSION=$(echo "$RESPONSE" | jq -r '.RedfishVersion')
      echo "✅ OK (Redfish ${VERSION})"
    else
      echo "❌ FAILED (invalid response or auth failure)"
      exit 1
    fi

    # Test 4: System query
    echo -n "4. System data... "
    SYSTEM=$(api_get "/Systems/System.Embedded.1" 2>&1)
    if echo "$SYSTEM" | jq -e '.Model' > /dev/null 2>&1; then
      MODEL=$(echo "$SYSTEM" | jq -r '.Model')
      HEALTH=$(echo "$SYSTEM" | jq -r '.Status.Health')
      echo "✅ OK (${MODEL}, Health: ${HEALTH})"
    else
      echo "❌ FAILED"
      exit 1
    fi

    echo ""
    echo "All tests passed! iDRAC API is fully accessible."
    ;;

  help|*)
    cat <<EOF
iDRAC Redfish API Helper

Usage: $0 <command>

Commands:
  test          Test connectivity and authentication
  status        System summary (model, power, CPU, memory)
  health        Health checks (overall, temps, fans, power)
  power         Current power state
  inventory     Full hardware inventory
  logs          Recent system event log entries (last 10)
  thermal       Detailed temperature and fan status
  storage       Storage controllers and drives
  reset-types   Available power reset types
  help          Show this help

Config: ${CONFIG_FILE}
Credentials: ${CREDS_SOURCE} → ${CREDS_FILE}
EOF
    ;;
esac


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)