jq Session 06: Infrastructure Patterns

Production patterns. This session applies all jq skills to real infrastructure data from ISE, Kubernetes, Vault, and monitoring systems.

Pre-Session State

  • Can sort, group, aggregate

  • Understand reduce pattern

  • Can build complex queries

Pattern 1: ISE Session Analysis

Sample Data

cat > /tmp/ise-sessions.json << 'EOF'
[
  {"calling_station_id": "AA:BB:CC:11:22:33", "framed_ip_address": "10.50.10.100",
   "user_name": "evanusmodestus", "nas_ip_address": "10.50.1.10",
   "auth_method": "EAP-TLS", "posture_status": "Compliant"},
  {"calling_station_id": "DD:EE:FF:44:55:66", "framed_ip_address": "10.50.10.101",
   "user_name": "guest", "nas_ip_address": "10.50.1.10",
   "auth_method": "MAB", "posture_status": "Unknown"},
  {"calling_station_id": "11:22:33:AA:BB:CC", "framed_ip_address": "10.50.20.50",
   "user_name": "contractor", "nas_ip_address": "10.50.1.11",
   "auth_method": "PEAP", "posture_status": "NonCompliant"}
]
EOF

Exercise: Sessions by Auth Method

cat /tmp/ise-sessions.json | jq 'group_by(.auth_method) |
  map({method: .[0].auth_method, count: length, users: [.[].user_name]})'

Exercise: Non-Compliant Endpoints

cat /tmp/ise-sessions.json | jq -r '.[] |
  select(.posture_status != "Compliant") |
  "\(.calling_station_id) - \(.user_name) - \(.posture_status)"'

Exercise: CSV Export for SIEM

cat /tmp/ise-sessions.json | jq -r '
  ["mac","ip","user","switch","auth","posture"],
  (.[] | [.calling_station_id, .framed_ip_address, .user_name,
          .nas_ip_address, .auth_method, .posture_status]) | @csv'

Pattern 2: Kubernetes Pod Analysis

Sample Data

cat > /tmp/k8s-pods.json << 'EOF'
{"items": [
  {"metadata": {"name": "nginx-abc123", "namespace": "web", "labels": {"app": "nginx"}},
   "status": {"phase": "Running", "containerStatuses": [{"ready": true, "restartCount": 0}]}},
  {"metadata": {"name": "api-def456", "namespace": "backend", "labels": {"app": "api"}},
   "status": {"phase": "Running", "containerStatuses": [{"ready": true, "restartCount": 5}]}},
  {"metadata": {"name": "db-ghi789", "namespace": "backend", "labels": {"app": "postgres"}},
   "status": {"phase": "Pending", "containerStatuses": [{"ready": false, "restartCount": 0}]}}
]}
EOF

Exercise: Pods Not Running

cat /tmp/k8s-pods.json | jq -r '.items[] |
  select(.status.phase != "Running") |
  "\(.metadata.namespace)/\(.metadata.name): \(.status.phase)"'

Exercise: High Restart Pods

cat /tmp/k8s-pods.json | jq '.items[] |
  select(.status.containerStatuses[0].restartCount > 3) |
  {name: .metadata.name, restarts: .status.containerStatuses[0].restartCount}'

Exercise: Pods by Namespace

cat /tmp/k8s-pods.json | jq '.items | group_by(.metadata.namespace) |
  map({namespace: .[0].metadata.namespace, pods: length})'

Pattern 3: Vault Secret Listing

Sample Data

cat > /tmp/vault-list.json << 'EOF'
{"data": {"keys": ["db/", "api/", "tls/"]}}
EOF

cat > /tmp/vault-secret.json << 'EOF'
{"data": {"data": {"username": "admin", "password": "secret123"},
          "metadata": {"created_time": "2026-03-01T10:00:00Z", "version": 3}}}
EOF

Exercise: List Secret Paths

cat /tmp/vault-list.json | jq -r '.data.keys[]'

Exercise: Extract Secret (KV v2)

cat /tmp/vault-secret.json | jq -r '.data.data | to_entries[] | "\(.key)=\(.value)"'

Exercise: Secret Metadata

cat /tmp/vault-secret.json | jq '{version: .data.metadata.version,
  created: .data.metadata.created_time}'

Pattern 4: Alert Routing

Sample Data

cat > /tmp/alerts.json << 'EOF'
[
  {"host": "kvm-01", "severity": "critical", "metric": "cpu", "value": 98},
  {"host": "vault-01", "severity": "warning", "metric": "memory", "value": 85},
  {"host": "db-01", "severity": "critical", "metric": "disk", "value": 95},
  {"host": "web-01", "severity": "info", "metric": "requests", "value": 1000}
]
EOF

Exercise: Route to Sentinel (Critical/Warning only)

cat /tmp/alerts.json | jq '[.[] | select(.severity == "critical" or .severity == "warning")]'

Exercise: Build PagerDuty Payload

cat /tmp/alerts.json | jq '.[] | select(.severity == "critical") |
  {routing_key: "abc123", event_action: "trigger",
   payload: {summary: "\(.host): \(.metric) at \(.value)%",
             severity: .severity, source: .host}}'

Summary: Infrastructure Patterns

Use Case Pattern

ISE sessions by auth

group_by(.auth_method) | map({method, count})

Non-compliant endpoints

select(.posture_status != "Compliant")

k8s unhealthy pods

select(.status.phase != "Running")

High restart pods

select(.containerStatuses[0].restartCount > N)

Vault KV extraction

.data.data | to_entries

Alert routing

select(.severity == "critical")

SIEM CSV export

@csv with header row

Exercises to Complete

  1. [ ] Parse netapi ise -f json mnt sessions output for failed auths

  2. [ ] Parse kubectl get pods -o json for crashlooping pods

  3. [ ] Build a Slack webhook payload from alert data

  4. [ ] Create a summary report: hosts, alerts by severity, top issues

  • Drill 06 - Practice these patterns

  • netapi output formats all support -f json

Session Log

Timestamp Notes

Start

<Record when you started>

End

<Record when you finished>