diff --git a/rh-sre/skills/cve-impact/references/01-parameter-reference.md b/rh-sre/skills/cve-impact/references/01-parameter-reference.md new file mode 120000 index 00000000..9492963a --- /dev/null +++ b/rh-sre/skills/cve-impact/references/01-parameter-reference.md @@ -0,0 +1 @@ +../../fleet-inventory/references/01-parameter-reference.md \ No newline at end of file diff --git a/rh-sre/skills/fleet-inventory/SKILL.md b/rh-sre/skills/fleet-inventory/SKILL.md index fff3ffa0..e58334c3 100644 --- a/rh-sre/skills/fleet-inventory/SKILL.md +++ b/rh-sre/skills/fleet-inventory/SKILL.md @@ -19,7 +19,7 @@ description: | model: inherit color: blue license: Apache-2.0 -allowed-tools: inventory__get_host_details vulnerability__get_cve_systems +allowed-tools: inventory__list_hosts inventory__find_host_by_name inventory__get_host_details inventory__get_host_system_profile vulnerability__get_cve_systems --- # Fleet Inventory Skill @@ -31,8 +31,11 @@ This skill queries Red Hat Lightspeed to retrieve and display information about **Required MCP Servers**: `lightspeed-mcp` ([setup guide](https://console.redhat.com/)) **Required MCP Tools**: -- `get_host_details` (from lightspeed-mcp) - Retrieve system inventory -- `get_cve_systems` (from lightspeed-mcp) - Find CVE-affected systems +- `inventory__list_hosts` (from lightspeed-mcp) - List and discover registered hosts +- `inventory__find_host_by_name` (from lightspeed-mcp) - Resolve hostname to host UUID +- `inventory__get_host_details` (from lightspeed-mcp) - Retrieve inventory metadata for known host UUIDs +- `inventory__get_host_system_profile` (from lightspeed-mcp) - Retrieve OS version and system profile when needed +- `vulnerability__get_cve_systems` (from lightspeed-mcp) - Find CVE-affected systems **Required Environment Variables**: - `LIGHTSPEED_CLIENT_ID` - Red Hat Lightspeed service account client ID @@ -100,28 +103,38 @@ Proceeding with fleet inventory query... ### Step 1: Retrieve System Inventory **Document Consultation** (REQUIRED - Execute FIRST): -1. **Action**: Read [insights-api.md](docs/insights/insights-api.md) using the Read tool to understand the `get_host_details` response format and pagination handling -2. **Output to user**: "I consulted [insights-api.md](docs/insights/insights-api.md) to understand the `get_host_details` response format and pagination handling." +1. **Action**: Read [insights-api.md](docs/insights/insights-api.md) using the Read tool to understand `inventory__list_hosts` response format and pagination handling +2. **Output to user**: "I consulted [insights-api.md](docs/insights/insights-api.md) to understand the `inventory__list_hosts` response format and pagination handling." -**MCP Tool**: `get_host_details` (from lightspeed-mcp) +**MCP Tool**: `inventory__list_hosts` (from lightspeed-mcp) -**Purpose**: Query Lightspeed for comprehensive system information +**Purpose**: Query Lightspeed for registered hosts. Use for fleet discovery, tag filters, and environment scoping. -**Parameters**: See [references/01-parameter-reference.md](references/01-parameter-reference.md) for get_host_details/get_cve_systems parameters and response fields. +**Parameters**: `per_page=10` on first call, then `page` for pagination. Optional filters: `display_name`, `tags`, `staleness`, `hostname_or_id`. See [references/01-parameter-reference.md](references/01-parameter-reference.md). + +**Optional enrichment**: After host UUIDs are known: +- `inventory__get_host_details(host_ids="uuid-1,uuid-2")` — inventory metadata (similar fields to `list_hosts`) +- `inventory__get_host_system_profile(host_ids="uuid-1")` — OS version and system profile when RHEL version is required (one or two UUIDs at a time; large response) +- `inventory__find_host_by_name(hostname="...")` — resolve a hostname to a UUID **Verification Checklist**: -- ✓ Systems list returned with metadata -- ✓ Total count matches expectation -- ✓ System details include RHEL version, tags, status +- ✓ Response includes `total`, `count`, `page`, `per_page`, and `results` +- ✓ Hosts list returned with metadata +- ✓ Total count matches expectation (paginate with `page` while `count` equals `per_page`) - ✓ No authentication errors (401/403) -**Key Fields to Extract**: +**Key Fields to Extract** (from `results[]` on `list_hosts` / `get_host_details`): - `id`: Unique system identifier (use for remediation workflows) - `display_name` / `fqdn`: Human-readable hostname -- `rhel_version`: OS version (critical for remediation compatibility) -- `tags`: Environment labels (production, staging, dev) -- `stale`: Whether system recently checked in (< 7 days) -- `last_seen`: Last Lightspeed client run timestamp +- `updated`: Last inventory record update +- `last_check_in`: Last reporter check-in (prefer for active/stale display) +- `stale_timestamp`, `stale_warning_timestamp`, `culled_timestamp`: Staleness thresholds +- `per_reporter_staleness`: Per-reporter check-in detail +- `groups`: Inventory groups (when present) + +**When RHEL version or environment tags are required** (not on every `list_hosts` record): +- `system_profile.operating_system.version` or equivalent — from `inventory__get_host_system_profile`; equivalents include `operating_system.major`/`minor`, `os_release`, `operating_system.name` +- `tags`: Environment labels (when present on the host) ### Step 2: Filter and Organize Systems @@ -133,11 +146,11 @@ Apply user-requested filters and grouping. See [references/01-parameter-referenc ### Step 3: Query CVE-Affected Systems -**MCP Tool**: `get_cve_systems` (from lightspeed-mcp) +**MCP Tool**: `vulnerability__get_cve_systems` (from lightspeed-mcp) **Purpose**: Find systems affected by specific CVEs -**Parameters**: `cve_id` (CVE-YYYY-NNNNN, uppercase). See [references/01-parameter-reference.md](references/01-parameter-reference.md). +**Parameters**: `cve` (CVE-YYYY-NNNNN, uppercase). Paginate with `limit` and `offset`. See [references/01-parameter-reference.md](references/01-parameter-reference.md). **Verification Checklist**: - ✓ CVE ID matches request exactly @@ -191,13 +204,25 @@ Examples: - `lightspeed-mcp` - Red Hat Lightspeed platform access for system inventory and CVE data ### Required MCP Tools -- `get_host_details` (from lightspeed-mcp) - Retrieve all registered systems with metadata - - Parameters: Optional filters (system_id, hostname_pattern, tags, operating_system) - - Returns: List of systems with id, display_name, fqdn, rhel_version, tags, stale status +- `inventory__list_hosts` (from lightspeed-mcp) - List and discover registered hosts + - Parameters: `per_page`, `page`, `display_name`, `tags`, `staleness`, etc. + - Returns: `{ total, count, page, per_page, results[] }` with id, display_name, fqdn, updated, last_check_in, staleness timestamps + +- `inventory__find_host_by_name` (from lightspeed-mcp) - Resolve hostname to host record + - Parameters: `hostname` (required) + - Returns: Host record with UUID + +- `inventory__get_host_details` (from lightspeed-mcp) - Retrieve inventory metadata for known host UUIDs + - Parameters: `host_ids` (required, comma-separated UUID string) + - Returns: Same pagination wrapper; host records similar to `list_hosts` (not guaranteed to include `system_profile`) + +- `inventory__get_host_system_profile` (from lightspeed-mcp) - Retrieve OS version and system profile + - Parameters: `host_ids` (comma-separated; one or two UUIDs at a time) + - Returns: `system_profile` with `operating_system` (name, major, minor), `os_release`, packages, services -- `get_cve_systems` (from lightspeed-mcp) - Find systems affected by specific CVEs - - Parameters: cve_id (string, format: CVE-YYYY-NNNNN) - - Returns: List of affected systems with vulnerability and remediation status +- `vulnerability__get_cve_systems` (from lightspeed-mcp) - Find systems affected by specific CVEs + - Parameters: `cve` (string, format: CVE-YYYY-NNNNN), `limit`, `offset` + - Returns: Paginated list of affected systems with vulnerability and remediation status ### Related Skills - `mcp-lightspeed-validator` - **PREREQUISITE** - Validates Lightspeed MCP server configuration and connectivity diff --git a/rh-sre/skills/fleet-inventory/docs/insights/insights-api.md b/rh-sre/skills/fleet-inventory/docs/insights/insights-api.md index daef71c2..8c179603 100644 --- a/rh-sre/skills/fleet-inventory/docs/insights/insights-api.md +++ b/rh-sre/skills/fleet-inventory/docs/insights/insights-api.md @@ -1,11 +1,94 @@ --- -title: TODO -status: draft +title: Lightspeed Inventory API Patterns for Fleet Discovery +category: insights +tags: [lightspeed, inventory, list_hosts, pagination] +last_updated: 2026-06-22 --- -# TODO +# Lightspeed Inventory API Patterns -Placeholder stub created during skill-local docs migration. +Fleet discovery and listing use **`inventory__list_hosts`**, not `inventory__get_host_details`. The latter requires known host UUIDs. -- Keep link targets valid for migration PR review. -- Content will be authored in a follow-up PR. +## Tool routing by intent + +| User intent | Tool | Key parameters | +|-------------|------|----------------| +| List or discover the fleet; filter by tag, name, staleness | `inventory__list_hosts` | `per_page=10` (first call), `page`, `display_name`, `tags`, `staleness` | +| Resolve hostname → UUID | `inventory__find_host_by_name` | `hostname` | +| Inventory metadata for known host(s) | `inventory__get_host_details` | `host_ids` (comma-separated UUIDs) | +| OS version / system profile for known host(s) | `inventory__get_host_system_profile` | `host_ids` (one or two UUIDs at a time) | +| Systems affected by a CVE | `vulnerability__get_cve_systems` | `cve`, `limit`, `offset`; optional `system_uuid` | + +## Response envelope (list_hosts, get_host_details, get_host_system_profile) + +All three inventory tools return the same top-level shape: + +| Field | Meaning | +|-------|---------| +| `total` | Total hosts matching the query | +| `count` | Hosts in this page | +| `page` | Current page number | +| `per_page` | Page size | +| `results` | Array of host records | + +## inventory__list_hosts pagination + +- **First call**: always use `per_page=10` (integer). The MCP tool description requires this default to avoid performance and context issues. +- **Subsequent pages**: increment `page` (`1`, `2`, `3`, …) while keeping the same filters. +- **Stop condition**: when `count` is less than `per_page`, or `results` is empty. + +``` +inventory__list_hosts(per_page=10, page=1, display_name="") +inventory__list_hosts(per_page=10, page=2, display_name="") +``` + +Use `per_page`, not `page_size`. Lightspeed inventory uses different pagination parameter names than AAP MCP. + +## Response fields (list_hosts / get_host_details) + +Extract from each `results[]` host record: + +- `id` — host UUID (use for enrichment and remediation workflows) +- `display_name` / `fqdn` — human-readable hostname +- `updated` — last inventory record update +- `last_check_in` — last reporter check-in (prefer for active/stale display) +- `stale_timestamp`, `stale_warning_timestamp`, `culled_timestamp` — staleness thresholds +- `per_reporter_staleness` — per-reporter check-in detail +- `groups` — inventory groups (when present) +- `facts` — limited rhsm facts when profile data is sparse + +**When present** (not guaranteed on every host): `tags` + +`list_hosts` and `get_host_details` do **not** reliably return `system_profile`. Do not expect RHEL version from fleet listing alone. + +## OS version (get_host_system_profile) + +When the user asks for RHEL version distribution or version-based filtering, call: + +``` +inventory__get_host_system_profile(host_ids="68ce32aa-57da-49b7-8ded-dc4ad54e520a") +``` + +Use **one or two UUIDs at a time** — responses are large. + +Extract RHEL version from `results[].system_profile`: + +- `system_profile.operating_system.version` or equivalent +- Equivalents: `operating_system.major` / `operating_system.minor`, `os_release`, `operating_system.name` + +Example live shape: `"operating_system": {"name": "RHEL", "major": 10, "minor": 1}`, `"os_release": "10.1"` + +## CVE-affected systems pagination + +Use `vulnerability__get_cve_systems` with parameter **`cve`** (not `cve_id`): + +``` +vulnerability__get_cve_systems(cve="CVE-2024-1234", limit=100, offset=0) +``` + +Paginate with `offset += limit` until the page returns fewer records than `limit`. + +## Related references + +- [01-parameter-reference.md](../../references/01-parameter-reference.md) — parameter tables for all fleet-inventory tools +- [lightspeed-mcp-parameters.md](../../../cve-impact/docs/references/lightspeed-mcp-parameters.md) — shared Lightspeed MCP parameter reference (inventory and vulnerability tools) diff --git a/rh-sre/skills/fleet-inventory/references/01-parameter-reference.md b/rh-sre/skills/fleet-inventory/references/01-parameter-reference.md index 6909aa85..70d7af3a 100644 --- a/rh-sre/skills/fleet-inventory/references/01-parameter-reference.md +++ b/rh-sre/skills/fleet-inventory/references/01-parameter-reference.md @@ -1,49 +1,132 @@ # Fleet Inventory Parameter Reference -Read when calling `get_host_details` or `get_cve_systems` to ensure correct parameters. +Read when calling inventory or vulnerability tools to ensure correct parameters. -## get_host_details +## inventory__list_hosts -**Parameters** (based on user query): +**Purpose**: List and discover hosts. Use for fleet queries, tag filters, and environment scoping. -```python -# No filters -get_host_details() +| Parameter | Type | Required | Example | Notes | +|-----------|------|----------|---------|-------| +| `per_page` | integer | No | `10` | **Use 10 on first call.** Not `page_size`. | +| `page` | integer | No | `1` | Increment for pagination. | +| `display_name` | string | No | `""` | Filter by display name. Empty string = no filter. | +| `hostname_or_id` | string | No | `""` | Filter by display_name, fqdn, or id. | +| `fqdn` | string | No | `""` | Filter by FQDN. | +| `tags` | string | No | `"ns1/key1=val1"` | Tag filter string (not an array). | +| `staleness` | string | No | `"fresh"` | One of `fresh`, `stale`, `stale_warning`, `unknown`. | +| `order_by` | string | No | `"display_name"` | Sort field: `display_name`, `updated`, `created`. | +| `order_how` | string | No | `"ASC"` | `ASC` or `DESC`. | -# Specific system -get_host_details(system_id="abc-123") +**Correct**: +``` +inventory__list_hosts(per_page=10, page=1, display_name="") +inventory__list_hosts(per_page=10, page=1, tags="insights-client/owner=staging") +``` + +**Wrong**: +``` +inventory__list_hosts() # Missing per_page guidance; always pass per_page=10 first +inventory__list_hosts(page_size=100) # Use per_page, not page_size +inventory__list_hosts(tags=["production"]) # tags is a string, not an array +``` -# Hostname pattern -get_host_details(hostname_pattern="web-*") +**Response envelope**: `{ total, count, page, per_page, results[] }` -# Tag filter -get_host_details(tags=["production"]) +**Response fields** (per host in `results[]`): `id`, `display_name`, `fqdn`, `updated`, `last_check_in`, `stale_timestamp`, `per_reporter_staleness`, `groups`, `facts`. Tags when present. No `system_profile` — use `get_host_system_profile` for OS version. -# RHEL version filter -get_host_details(operating_system__version__startswith="8") +## inventory__find_host_by_name + +**Purpose**: Resolve a hostname or display name to a host record. + +| Parameter | Type | Required | Example | +|-----------|------|----------|---------| +| `hostname` | string | Yes | `"web-server-01"` | -# Combined -get_host_details(tags=["production", "web-tier"], operating_system__version__startswith="8") +``` +inventory__find_host_by_name(hostname="web-server-01") ``` -**Response fields**: id, display_name, fqdn, rhel_version, last_seen, tags, stale, satellite_managed +## inventory__get_host_details -## get_cve_systems +**Purpose**: Retrieve full details for **known** host UUIDs. Not for fleet enumeration. -**Parameters**: `cve_id` (string, format CVE-YYYY-NNNNN, uppercase) +| Parameter | Type | Required | Example | +|-----------|------|----------|---------| +| `host_ids` | string | Yes | `"uuid-1,uuid-2"` | -```python -get_cve_systems(cve_id="CVE-2024-1234") +``` +inventory__get_host_details(host_ids="68ce32aa-57da-49b7-8ded-dc4ad54e520a") ``` -**Response fields**: cve_id, affected_systems (system_id, display_name, status, remediation_available), total_affected, total_remediated, total_vulnerable +**Response**: Same envelope as `list_hosts`; host shape is similar (inventory metadata, not guaranteed to include `system_profile`). + +**Wrong**: +``` +inventory__get_host_details() # host_ids is required +inventory__get_host_details(system_id="abc-123") # Use host_ids +inventory__get_host_details(hostname_pattern="web-*") # Not supported; use list_hosts +inventory__get_host_details(tags=["production"]) # Not supported; use list_hosts +``` + +## inventory__get_host_system_profile + +**Purpose**: Retrieve OS version and full system profile for **known** host UUIDs. Use when RHEL version distribution or version-based filtering is required. + +| Parameter | Type | Required | Example | Notes | +|-----------|------|----------|---------|-------| +| `host_ids` | string | No | `"uuid-1"` or `"uuid-1,uuid-2"` | Comma-separated UUIDs. **One or two at a time** — MCP warns of very large responses. Default `""`. | + +``` +inventory__get_host_system_profile(host_ids="68ce32aa-57da-49b7-8ded-dc4ad54e520a") +``` + +**Response envelope**: `{ total, count, page, per_page, results[] }` (same as `list_hosts`). + +**Each `results[]` item** (live shape): `id` + `system_profile` only — not the full inventory record from `list_hosts`. + +**`system_profile` fields** (live; OS version equivalents): +- `operating_system.name` — e.g. `"RHEL"` +- `operating_system.major` / `operating_system.minor` — e.g. `10` / `1` (no `operating_system.version` string in live responses) +- `os_release` — e.g. `"10.1"` +- `installed_packages`, `enabled_services`, `installed_services` +- Hardware/infrastructure: `cpu_model`, `number_of_cpus`, `system_memory_bytes`, `network_interfaces`, etc. + +Use `system_profile.operating_system.version` in docs as the canonical name; at runtime read `major`/`minor`, `os_release`, or `operating_system.name` when `version` is absent. + +## vulnerability__get_cve_systems + +**Purpose**: List systems affected by a CVE. + +| Parameter | Type | Required | Example | Notes | +|-----------|------|----------|---------|-------| +| `cve` | string | Yes | `"CVE-2024-1234"` | Required. Not `cve_id`. | +| `limit` | integer | No | `100` | Records per page (default 10). | +| `offset` | integer | No | `0` | Pagination offset. | +| `sort` | string | No | `"-updated"` | Prefix `-` for descending. | +| `filter_` | string | No | `""` | Full-text filter on system display name. | +| `system_uuid` | string | No | `"68ce32aa-..."` | Check if a specific system is affected. | + +**Correct**: +``` +vulnerability__get_cve_systems(cve="CVE-2024-1234", limit=100, offset=0) +``` + +**Wrong**: +``` +vulnerability__get_cve_systems(cve_id="CVE-2024-1234") # Use cve, not cve_id +``` + +**Response fields**: affected systems with id, display_name, status, remediation_available; paginate with limit/offset for large result sets. **Status values**: Vulnerable (patch needed), Patched (no action), Not Affected (exclude) -## Filtering and Sorting +## Client-side filtering and sorting + +When API filters are insufficient, filter after listing or after fetching profiles: -**By RHEL**: `[s for s in systems if s['rhel_version'].startswith("8")]` -**By tag**: `[s for s in systems if "production" in s.get('tags', [])]` -**By stale**: `[s for s in systems if not s.get('stale', False)]` -**Sort by last_seen**: `sorted(systems, key=lambda s: s['last_seen'], reverse=True)` -**Sort by display_name**: `sorted(systems, key=lambda s: s['display_name'])` +**By RHEL major** (requires `get_host_system_profile` data): `[h for h in profiles if h.get('system_profile', {}).get('operating_system', {}).get('major') == 8]` +**By tag** (when present on host): `[h for h in hosts if any("production" in t for t in h.get('tags', []))]` +**By stale** (from list_hosts): compare `last_check_in` to `stale_timestamp`, or use `staleness` filter on `list_hosts` +**Sort by last check-in**: `sorted(hosts, key=lambda h: h.get('last_check_in', ''), reverse=True)` +**Sort by updated**: `sorted(hosts, key=lambda h: h.get('updated', ''), reverse=True)` diff --git a/rh-sre/skills/fleet-inventory/references/03-output-templates.md b/rh-sre/skills/fleet-inventory/references/03-output-templates.md index b0337ed8..16c644e3 100644 --- a/rh-sre/skills/fleet-inventory/references/03-output-templates.md +++ b/rh-sre/skills/fleet-inventory/references/03-output-templates.md @@ -25,7 +25,9 @@ Retrieved from Red Hat Lightspeed on YYYY-MM-DDTHH:MM:SSZ | Environment | Count | Systems | ## Top 20 Systems (by last check-in) -[Table: display_name, rhel_version, tags, last_seen] +[Table: display_name, last_check_in, updated, groups or tags when present] + +For RHEL version breakdown, call `inventory__get_host_system_profile` and use `system_profile.operating_system.version` or equivalent (`os_release`, `major`/`minor`). **Would you like to**: Filter by environment/RHEL, view CVEs, create remediation plans ``` diff --git a/rh-sre/skills/fleet-inventory/references/04-examples.md b/rh-sre/skills/fleet-inventory/references/04-examples.md index 2d08d77a..8db77951 100644 --- a/rh-sre/skills/fleet-inventory/references/04-examples.md +++ b/rh-sre/skills/fleet-inventory/references/04-examples.md @@ -5,21 +5,23 @@ **User Request**: "Show the managed fleet" 1. Invoke mcp-lightspeed-validator (Step 0) → PASSED -2. Call `get_host_details()` with no filters -3. Consult fleet-management.md for grouping -4. Group by RHEL version, environment tags -5. Generate Template 1 output -6. Offer next steps (CVE analysis, remediation) +2. Call `inventory__list_hosts(per_page=10, page=1, display_name="")` +3. Paginate: increment `page` until a page returns fewer than `per_page` hosts +4. Consult fleet-management.md for grouping +5. Group by environment (`groups` or `tags` when present); for RHEL version breakdown, call `inventory__get_host_system_profile(host_ids="")` per host (one or two UUIDs at a time) +6. Generate Template 1 output +7. Offer next steps (CVE analysis, remediation) ## Example 2: CVE Impact Query **User Request**: "What systems are affected by CVE-2024-1234?" 1. Invoke mcp-lightspeed-validator (Step 0) → PASSED -2. Call `get_cve_systems(cve_id="CVE-2024-1234")` -3. Separate vulnerable vs. patched systems -4. Generate Template 2 output -5. Suggest /remediation for next steps +2. Call `vulnerability__get_cve_systems(cve="CVE-2024-1234", limit=100, offset=0)` +3. Paginate with `offset += limit` until fewer records than `limit` are returned +4. Separate vulnerable vs. patched systems +5. Generate Template 2 output +6. Suggest /remediation for next steps ## Example 3: Environment Filter @@ -27,6 +29,17 @@ 1. Invoke mcp-lightspeed-validator (Step 0) → PARTIAL 2. Ask user: "Proceed? (yes/no)" → yes -3. Call `get_host_details()` → filter by tag "staging" -4. Group by tier (hostname patterns) -5. Generate Template 3 output +3. Call `inventory__list_hosts(per_page=10, page=1, tags="insights-client/owner=staging")` (adjust tag string to match your environment), or list all and filter client-side by tag +4. Paginate through results +5. Group by tier (hostname patterns) +6. Generate Template 3 output + +## Example 4: Hostname Lookup + +**User Request**: "Find web-server-01 in the fleet" + +1. Invoke mcp-lightspeed-validator (Step 0) → PASSED +2. Call `inventory__find_host_by_name(hostname="web-server-01")` +3. If inventory metadata needed, call `inventory__get_host_details(host_ids="")` +4. If OS version needed, call `inventory__get_host_system_profile(host_ids="")` +5. Present host summary