From 434243367ef29024d64741c3440e8805fc4cd7b4 Mon Sep 17 00:00:00 2001 From: Ev Lacey Date: Tue, 27 Oct 2026 16:03:03 -0700 Subject: [PATCH 01/13] Add read-only Redfish tools for BCM nodes Add modules.bcm.redfish (off by default) so the agent can read a node's BMC over Redfish when the node is down or unreachable in-band. The BCM SSH adapter registers redfish_* MCP tools behind its existing bearer auth. The model passes only a BCM hostname; the adapter resolves the BMC address and credentials through CMSH and never returns them. RedfishPolicy allowlists GET on inventory, health, sensor, log, firmware and task resources, accepts only $expand, $top and $skip, and rejects Actions, AccountService, SessionService, CertificateService, EventService, SecureBoot, Bios/Settings, VirtualMedia, '..', '//' and '%' before any credential lookup. Responses have password, token and secret fields redacted, and errors omit the BMC address. By default each GET runs curl on the BCM head node over the adapter's SSH session, with the credential on stdin; viaHeadNode=false uses a direct HTTPS client without redirects. The extension adds bcm_redfish_system_summary, _thermal, _power, _sel, _firmware and _get as read tools in every mode, outside the mutation policy. Signed-off-by: Ev Lacey --- docs/bcm.md | 55 +++ docs/installation.md | 2 + docs/security_model.md | 2 + .../files/agent-documentation.tar.gz | Bin 29857 -> 31187 bytes helm/mosaic-stack/files/bcm-mcp-ssh-server.py | 393 +++++++++++++++++- .../openclaw-seed/extensions/bcm/index.ts | 116 ++++++ .../extensions/bcm/openclaw.plugin.json | 12 +- .../files/openclaw-seed/nemoclaw.json | 3 +- .../files/openclaw-seed/skills/bcm/SKILL.md | 13 + .../mosaic-stack/templates/bcm-mcp-tools.yaml | 10 + helm/mosaic-stack/templates/validation.yaml | 8 + .../tests/bcm-tool-boundary.test.mjs | 95 +++++ helm/mosaic-stack/tests/chart-render.test.mjs | 38 ++ helm/mosaic-stack/tests/test_bcm_server.py | 136 ++++++ helm/mosaic-stack/values.yaml | 8 + 15 files changed, 888 insertions(+), 3 deletions(-) diff --git a/docs/bcm.md b/docs/bcm.md index e42e3b7b..15148d34 100644 --- a/docs/bcm.md +++ b/docs/bcm.md @@ -280,3 +280,58 @@ kubectl -n mosaic get secret mosaic-ui-auth \ Open `http://127.0.0.1:3210` on the workstation. Both forwarding processes must remain running. + +## 8. Optional: Read-Only Redfish + +Redfish lets the agent read a node's BMC when the node is down or unreachable in-band: power state, +hardware health, temperatures, fans, power supplies, BMC event logs, and firmware inventory. The +agent passes only a Base Command Manager hostname. The Base Command Manager adapter looks up the +BMC address and credentials through CMSH, the same lookup the Hardware Agent uses, and never returns +them to the model. + +Prerequisites: + +- The Base Command Manager adapter runs in `ssh-adapter` mode (section 5). +- The adapter's SSH identity can read `bmcsettings` and BMC interfaces through CMSH on the head node. +- The head node can reach the BMC network over HTTPS and has `curl`. Check one BMC from the head node: + + ```bash + curl -sk https:///redfish/v1 | head -c 300; echo + ``` + +Enable it: + +```bash +helm upgrade mosaic "$MOSAIC_CHART" \ + --devel \ + -n mosaic \ + --reuse-values \ + --set modules.bcm.redfish.enabled=true \ + --wait \ + --timeout 12m +``` + +By default each request runs `curl` on the head node over the adapter's existing SSH session +(`modules.bcm.redfish.viaHeadNode=true`), because the head node is routed to the BMC network. The +BMC credential reaches `curl` on standard input, so it does not appear in process listings. Set +`viaHeadNode=false` only when the adapter pod itself can reach the BMCs. BMCs usually present +self-signed certificates, so `modules.bcm.redfish.verifyTls` defaults to `false`. +`modules.bcm.redfish.timeoutSeconds` (default `60`) bounds each request; some DGX BMCs take about +30 seconds to return the expanded firmware inventory. + +The adapter enforces the following allowlist before it looks up any credential. Only `GET` is +used, and the only query parameters accepted are `$expand`, `$top`, and `$skip`: + +| Resource | Paths under `/redfish/v1` | +| --- | --- | +| Service root and collections | `/`, `Systems`, `Chassis`, `Managers` | +| Systems | `Systems/{id}` and its `Processors`, `Memory`, `Storage`, `EthernetInterfaces`, and `LogServices/{id}/Entries` | +| Chassis | `Chassis/{id}` and its `Thermal`, `ThermalSubsystem`, `Power`, `PowerSubsystem`, and `Sensors` | +| Managers | `Managers/{id}` and its `EthernetInterfaces` and `LogServices/{id}/Entries` | +| Firmware and tasks | `UpdateService/FirmwareInventory`, `TaskService/Tasks` | + +Everything else is refused, including any path containing `Actions`, and `AccountService`, +`SessionService`, `CertificateService`, `EventService`, `SecureBoot`, `Bios/Settings`, and +`VirtualMedia`. Paths with `..`, `//`, `%`, or other query parameters are also refused. Fields named +like passwords, tokens, or secrets are redacted from responses. Resets and other BMC actions are not +available in any session mode. diff --git a/docs/installation.md b/docs/installation.md index da556ddf..43135b17 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -473,6 +473,8 @@ helm upgrade mosaic "$MOSAIC_CHART" \ The SSH identity must be allowed to create or update the dedicated read-only CMSH user during startup. +To let the agent read node BMCs over read-only Redfish, see [Read-only Redfish](bcm.md#8-optional-read-only-redfish). + ### Research To deploy the Research Agent and OpenSearch, set the embedding API key, active diff --git a/docs/security_model.md b/docs/security_model.md index 3dffa9cc..47c67549 100644 --- a/docs/security_model.md +++ b/docs/security_model.md @@ -39,6 +39,8 @@ The read-only and administrative Base Command Manager paths use separate identit Base Command Manager's configured profile remains authoritative. Enabling Base Command Manager administration requires an operator-provided credential with the intended cluster permissions. +When `modules.bcm.redfish.enabled=true`, the `bcm_redfish_*` tools read node BMCs in every mode, including View and automated sessions. They are never mutation tools. The model supplies only a Base Command Manager hostname and a path or named query. The Base Command Manager adapter resolves the BMC address and credentials through CMSH and does not return them. Its `RedfishPolicy` allowlist is enforced server-side before any credential lookup. It permits only `GET` on inventory, health, sensor, log, firmware, and task resources, and rejects any path containing `Actions`, as well as account, session, certificate, event, Secure Boot, BIOS settings, and virtual media resources. Responses have password, token, and secret fields redacted, and errors omit the BMC address. Like other read-only tools, Redfish is not a confidentiality boundary: anything the allowlist permits is visible to the session. + ## Diagnostic Commands And SSH Local `exec` runs inside the per-session OpenShell sandbox in View, Edit, Auto, and automated sessions. OpenShell enforces this boundary; the session guard does not parse or allowlist sandbox commands. diff --git a/helm/mosaic-stack/files/agent-documentation.tar.gz b/helm/mosaic-stack/files/agent-documentation.tar.gz index 4edf4b8909b4de0bd50347dee65192a88f4d6b97..09b778803dd2ae4a9282adf33b4fcafc271cbb9e 100644 GIT binary patch literal 31187 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 C*jNYv literal 29857 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 YsZym%l`2)LRQbR154wC(^#Hg5061=b{Qv*} diff --git a/helm/mosaic-stack/files/bcm-mcp-ssh-server.py b/helm/mosaic-stack/files/bcm-mcp-ssh-server.py index a785838b..53b62086 100644 --- a/helm/mosaic-stack/files/bcm-mcp-ssh-server.py +++ b/helm/mosaic-stack/files/bcm-mcp-ssh-server.py @@ -2,14 +2,19 @@ # SPDX-License-Identifier: Apache-2.0 import asyncio +import base64 import hmac import ipaddress +import json import logging import re import shlex +import ssl import subprocess import textwrap import threading +import urllib.error +import urllib.request from bcm_mcp_tools.cli.support_mcp.main import configure_logging from bcm_mcp_tools.cli.support_mcp.options import get_env_bool, get_env_int, get_env_str @@ -68,6 +73,117 @@ def last_cmsh_value(output: str) -> str | None: return lines[-1] if lines else None +class RedfishError(Exception): + def __init__(self, status: int, message: str): + super().__init__(message) + self.status = status + + +class RedfishPolicy: + """Read-only Redfish allowlist enforced before any BMC credential is resolved.""" + + _ID = r"[A-Za-z0-9_-][A-Za-z0-9._-]*" + _SUB = rf"(?:/{_ID})*" + _LOGS = rf"/LogServices(?:/{_ID}(?:/Entries(?:/{_ID})?)?)?" + ALLOWED = tuple(re.compile(f"/redfish/v1{pattern}") for pattern in ( + "", + "/(?:Systems|Chassis|Managers)", + rf"/Systems/{_ID}", + rf"/Systems/{_ID}/(?:Processors|Memory|Storage|EthernetInterfaces){_SUB}", + rf"/Systems/{_ID}{_LOGS}", + rf"/Chassis/{_ID}", + rf"/Chassis/{_ID}/(?:Thermal|ThermalSubsystem|Power|PowerSubsystem|Sensors){_SUB}", + rf"/Managers/{_ID}", + rf"/Managers/{_ID}{_LOGS}", + rf"/Managers/{_ID}/EthernetInterfaces{_SUB}", + rf"/UpdateService/FirmwareInventory{_SUB}", + rf"/TaskService/Tasks{_SUB}", + )) + DENIED_SEGMENTS = frozenset({ + "accountservice", "sessionservice", "certificateservice", "eventservice", + "actions", "secureboot", "virtualmedia", + }) + QUERY = { + "$expand": re.compile(r"[.*~](?:\(\$levels=[1-5]\))?"), + "$top": re.compile(r"[0-9]{1,4}"), + "$skip": re.compile(r"[0-9]{1,7}"), + } + + @classmethod + def normalize(cls, path: str) -> str | None: + if not isinstance(path, str) or len(path) > 512 or any(c in path for c in "%#\\\"' \t\r\n"): + return None + resource, separator, query = path.partition("?") + if separator and not query: + return None + if "//" in resource or ".." in resource or "/bios/settings" in resource.lower(): + return None + if len(resource) > len("/redfish/v1") and resource.endswith("/"): + resource = resource[:-1] + if any(segment.lower() in cls.DENIED_SEGMENTS for segment in resource.split("/")): + return None + if not any(pattern.fullmatch(resource) for pattern in cls.ALLOWED): + return None + params = [] + for item in query.split("&") if query else []: + name, separator, value = item.partition("=") + if not separator or name not in cls.QUERY or not cls.QUERY[name].fullmatch(value): + return None + params.append(item) + return resource + ("?" + "&".join(params) if params else "") + + @classmethod + def is_allowed(cls, method: str, path: str) -> bool: + return method == "GET" and cls.normalize(path) is not None + + +REDFISH_SECRET_SUFFIXES = ("password", "token", "secret") +REDFISH_METADATA = ("@odata.context", "@odata.etag", "@odata.type") +REDFISH_MAX_CHARS = 32000 +REDFISH_MAX_BYTES = 8 * 1024 * 1024 +REDFISH_SKIPPED_LOGS = frozenset({"debugtokenservice", "diagnosticlog", "dump", "fdr", "journal"}) +CURL_ERRORS = {6: "BMC address could not be resolved", 7: "BMC is unreachable", 28: "BMC request timed out", + 35: "BMC TLS handshake failed", 60: "BMC TLS certificate verification failed"} + + +def scrub_redfish(value): + if isinstance(value, dict): + return { + key: "[redacted]" if key.lower().endswith(REDFISH_SECRET_SUFFIXES) else scrub_redfish(item) + for key, item in value.items() + if key not in REDFISH_METADATA + } + if isinstance(value, list): + return [scrub_redfish(item) for item in value] + return value + + +def curl_user_config(username: str, password: str) -> bytes: + if any(c in username + password for c in "\r\n\0"): + raise RedfishError(502, "BMC credentials in BCM are malformed") + escaped = f"{username}:{password}".replace("\\", "\\\\").replace('"', '\\"') + return f'user = "{escaped}"\n'.encode() + + +def redfish_member_paths(data: dict) -> list[str]: + return [m["@odata.id"] for m in data.get("Members", []) if isinstance(m, dict) and isinstance(m.get("@odata.id"), str)] + + +def health(item: dict) -> str | None: + status = item.get("Status") or {} + return status.get("Health") if isinstance(status, dict) else None + + +def present(item: dict) -> bool: + status = item.get("Status") or {} + return not isinstance(status, dict) or status.get("State") != "Absent" + + +class _NoRedirect(urllib.request.HTTPRedirectHandler): + def redirect_request(self, *_args, **_kwargs): + return None + + class StaticTokenVerifier: def __init__(self, token: str): self.token = token @@ -90,10 +206,15 @@ def __init__(self, *args, **kwargs): self.cmsh_path = get_env_str("MOSAIC_BCM_CMSH_PATH", "/cm/local/apps/cmd/bin/cmsh") or "/cm/local/apps/cmd/bin/cmsh" self.hardware_compat_enabled = get_env_bool("MOSAIC_BCM_HARDWARE_COMPAT_ENABLED", False) self.bcm_head_host = get_env_str("MOSAIC_BCM_HEAD_HOST", "") or "" + self.redfish_enabled = get_env_bool("MOSAIC_BCM_REDFISH_ENABLED", False) + self.redfish_verify_tls = get_env_bool("MOSAIC_BCM_REDFISH_VERIFY_TLS", False) + self.redfish_timeout = get_env_int("MOSAIC_BCM_REDFISH_TIMEOUT", 60) + self.redfish_via_head_node = get_env_bool("MOSAIC_BCM_REDFISH_VIA_HEAD_NODE", True) + self._redfish_members: dict[tuple[str, str], list[str]] = {} self._cmsh_ready = False self._cmsh_setup_lock = threading.Lock() - def _ssh(self, script: str, timeout: int) -> subprocess.CompletedProcess[bytes]: + def _ssh(self, script: str, timeout: int, stdin: bytes | None = None) -> subprocess.CompletedProcess[bytes]: if not self.bcm_head_host: raise RuntimeError("BCM head host is not configured") return subprocess.run( @@ -101,6 +222,7 @@ def _ssh(self, script: str, timeout: int) -> subprocess.CompletedProcess[bytes]: capture_output=True, timeout=timeout, check=False, + input=stdin, ) def _ensure_cmsh_user(self) -> None: @@ -185,6 +307,244 @@ def read(field: str) -> str | None: "host_password": host_password, } + def _redfish_bmc(self, hostname: str) -> dict[str, str]: + bmc = self.hardware_bmc(hostname) + if bmc is None: + raise RedfishError(404, f"no BMC address and credentials are configured in BCM for {hostname}") + return bmc + + def _redfish_fetch(self, bmc: dict[str, str], path: str) -> tuple[int, bytes]: + url = f"https://{bmc['bmc_ip']}{path}" + if self.redfish_via_head_node: + command = ["curl", "-sS", "--proto", "=https", "--max-time", str(self.redfish_timeout), + "-H", "Accept: application/json", "-K", "/dev/stdin", "-w", "\n%{http_code}"] + if not self.redfish_verify_tls: + command.append("-k") + try: + result = self._ssh(shlex.join(command + [url]), self.redfish_timeout + 30, + curl_user_config(bmc["bmc_username"], bmc["bmc_password"])) + except subprocess.TimeoutExpired as error: + raise RedfishError(504, "BMC request timed out") from error + if result.returncode != 0: + raise RedfishError(502, CURL_ERRORS.get(result.returncode, "BMC request through the BCM head node failed")) + body, _, code = result.stdout.rpartition(b"\n") + return int(code) if code.isdigit() else 502, body + context = ssl.create_default_context() + if not self.redfish_verify_tls: + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + credentials = base64.b64encode(f"{bmc['bmc_username']}:{bmc['bmc_password']}".encode()).decode() + request = urllib.request.Request(url, headers={"Accept": "application/json", "Authorization": f"Basic {credentials}"}) + opener = urllib.request.build_opener(urllib.request.HTTPSHandler(context=context), _NoRedirect()) + try: + with opener.open(request, timeout=self.redfish_timeout) as response: + return response.status, response.read(REDFISH_MAX_BYTES + 1) + except urllib.error.HTTPError as error: + return error.code, b"" + except (urllib.error.URLError, OSError) as error: + raise RedfishError(502, "BMC is unreachable from the BCM MCP service") from error + + def _redfish_read(self, bmc: dict[str, str], path: str) -> dict: + allowed = RedfishPolicy.normalize(path) + if allowed is None: + raise RedfishError(403, f"{path} is not permitted by the read-only Redfish policy") + status, body = self._redfish_fetch(bmc, allowed) + if status != 200: + raise RedfishError(status if 400 <= status < 600 else 502, f"BMC returned HTTP {status} for {allowed}") + if len(body) > REDFISH_MAX_BYTES: + raise RedfishError(502, f"BMC response for {allowed} is too large") + try: + data = json.loads(body) + except ValueError as error: + raise RedfishError(502, f"BMC returned non-JSON content for {allowed}") from error + return scrub_redfish(data) if isinstance(data, dict) else {"value": scrub_redfish(data)} + + def _redfish_members_of(self, hostname: str, bmc: dict[str, str], collection: str) -> list[str]: + key = (hostname, collection) + if key not in self._redfish_members: + members = redfish_member_paths(self._redfish_read(bmc, f"/redfish/v1/{collection}")) + self._redfish_members[key] = [path for path in members if RedfishPolicy.normalize(path) == path] + return self._redfish_members[key] + + def _redfish_chassis(self, hostname: str, bmc: dict[str, str], chassis: str) -> str: + if chassis: + path = f"/redfish/v1/Chassis/{chassis}" + if RedfishPolicy.normalize(path) != path: + raise ValueError("invalid chassis id") + return path + for system in self._redfish_members_of(hostname, bmc, "Systems")[:1]: + linked = redfish_member_paths({"Members": (self._redfish_read(bmc, system).get("Links") or {}).get("Chassis", [])}) + if linked: + return linked[0] + members = self._redfish_members_of(hostname, bmc, "Chassis") + if not members: + raise RedfishError(404, "the BMC reports no chassis") + return members[0] + + def redfish_get(self, hostname: str, path: str) -> dict: + if RedfishPolicy.normalize(path) is None: + raise RedfishError(403, f"{path} is not permitted by the read-only Redfish policy") + return self._redfish_read(self._redfish_bmc(hostname), path) + + def redfish_system_summary(self, hostname: str) -> dict: + bmc = self._redfish_bmc(hostname) + systems = [] + for path in self._redfish_members_of(hostname, bmc, "Systems")[:4]: + data = self._redfish_read(bmc, path) + status = data.get("Status") or {} + systems.append({ + "id": data.get("Id"), "powerState": data.get("PowerState"), + "health": status.get("Health"), "healthRollup": status.get("HealthRollup"), "state": status.get("State"), + "manufacturer": data.get("Manufacturer"), "model": data.get("Model"), "serialNumber": data.get("SerialNumber"), + "biosVersion": data.get("BiosVersion"), "lastResetTime": data.get("LastResetTime"), + "bootProgress": (data.get("BootProgress") or {}).get("LastState"), + }) + return {"hostname": hostname, "systems": systems} + + def redfish_thermal(self, hostname: str, chassis: str = "") -> dict: + bmc = self._redfish_bmc(hostname) + base = self._redfish_chassis(hostname, bmc, chassis) + try: + data = self._redfish_read(bmc, f"{base}/Thermal") + temps = [{"name": t.get("Name"), "readingCelsius": t.get("ReadingCelsius"), + "upperCritical": t.get("UpperThresholdCritical"), "upperFatal": t.get("UpperThresholdFatal"), + "health": health(t)} for t in data.get("Temperatures", []) if present(t) and t.get("ReadingCelsius") is not None] + fans = [{"name": f.get("Name"), "reading": f.get("Reading"), "units": f.get("ReadingUnits"), + "lowerCritical": f.get("LowerThresholdCritical"), "health": health(f)} + for f in data.get("Fans", []) if present(f) and f.get("Reading") is not None] + source = "Thermal" + except RedfishError as error: + if error.status not in (404, 405): + raise + metrics = self._redfish_read(bmc, f"{base}/ThermalSubsystem/ThermalMetrics") + temps = [{"name": t.get("DeviceName") or t.get("DataSourceUri"), "readingCelsius": t.get("Reading"), + "upperCritical": None, "upperFatal": None, "health": None} + for t in metrics.get("TemperatureReadingsCelsius", []) if t.get("Reading") is not None] + fan_data = self._redfish_read(bmc, f"{base}/ThermalSubsystem/Fans?$expand=.($levels=1)") + fans = [{"name": f.get("Name") or f.get("Id"), "reading": (f.get("SpeedPercent") or {}).get("Reading"), + "units": "%", "lowerCritical": None, "health": health(f)} + for f in fan_data.get("Members", []) if isinstance(f, dict) and present(f)] + source = "ThermalSubsystem" + + def margin(row): + limit = row["upperCritical"] if row["upperCritical"] is not None else row["upperFatal"] + return (0, limit - row["readingCelsius"]) if limit is not None else (1, -row["readingCelsius"]) + + readings = [f["reading"] for f in fans if isinstance(f["reading"], (int, float))] + return { + "hostname": hostname, "chassis": base.rsplit("/", 1)[1], "source": source, + "temperatureCount": len(temps), + "unhealthyTemperatures": [t for t in temps if t["health"] not in (None, "OK")], + "closestToLimit": sorted(temps, key=margin)[:15], + "fanCount": len(fans), + "unhealthyFans": [f for f in fans if f["health"] not in (None, "OK")], + "fanReadingRange": [min(readings), max(readings)] if readings else None, + "slowestFans": sorted((f for f in fans if isinstance(f["reading"], (int, float))), key=lambda f: f["reading"])[:5], + } + + def redfish_power(self, hostname: str, chassis: str = "") -> dict: + bmc = self._redfish_bmc(hostname) + base = self._redfish_chassis(hostname, bmc, chassis) + result: dict = {"hostname": hostname, "chassis": base.rsplit("/", 1)[1], "powerControl": [], "powerSupplies": []} + try: + data = self._redfish_read(bmc, f"{base}/Power") + for control in data.get("PowerControl", []): + metrics = control.get("PowerMetrics") or {} + result["powerControl"].append({ + "name": control.get("Name"), "consumedWatts": control.get("PowerConsumedWatts"), + "averageWatts": metrics.get("AverageConsumedWatts"), "maxWatts": metrics.get("MaxConsumedWatts"), + "capacityWatts": control.get("PowerCapacityWatts"), "health": health(control), + }) + for supply in data.get("PowerSupplies", []): + result["powerSupplies"].append({ + "name": supply.get("Name"), "health": health(supply), "present": present(supply), + "inputWatts": supply.get("PowerInputWatts"), "outputWatts": supply.get("PowerOutputWatts"), + "capacityWatts": supply.get("PowerCapacityWatts"), + }) + result["unhealthyVoltages"] = [{"name": v.get("Name"), "readingVolts": v.get("ReadingVolts"), "health": health(v)} + for v in data.get("Voltages", []) if present(v) and health(v) not in (None, "OK")] + except RedfishError as error: + if error.status not in (404, 405): + raise + if not result["powerSupplies"]: + try: + supplies = self._redfish_read(bmc, f"{base}/PowerSubsystem/PowerSupplies?$expand=.($levels=1)") + except RedfishError as error: + if error.status not in (404, 405): + raise + else: + result["powerSupplies"] = [{ + "name": s.get("Name") or s.get("Id"), "health": health(s), "present": present(s), + "capacityWatts": s.get("PowerCapacityWatts"), "model": s.get("Model"), + } for s in supplies.get("Members", []) if isinstance(s, dict)] + return result + + def redfish_sel(self, hostname: str, limit: int = 50) -> dict: + limit = max(1, min(int(limit), 200)) + bmc = self._redfish_bmc(hostname) + services = [] + for collection in ("Managers", "Systems"): + for member in self._redfish_members_of(hostname, bmc, collection): + try: + listed = redfish_member_paths(self._redfish_read(bmc, f"{member}/LogServices")) + except RedfishError: + continue + services += [path for path in listed + if path.rsplit("/", 1)[1].lower() not in REDFISH_SKIPPED_LOGS and path not in services] + entries, sources = [], [] + for service in services[:10]: + try: + first = self._redfish_read(bmc, f"{service}/Entries?$top={limit}") + count = first.get("Members@odata.count") or 0 + pages = [first] + if isinstance(count, int) and count > limit: + pages.append(self._redfish_read(bmc, f"{service}/Entries?$skip={count - limit}&$top={limit}")) + except RedfishError: + continue + source = service.removeprefix("/redfish/v1/").replace("/LogServices/", "/") + sources.append(source) + for page in pages: + for entry in page.get("Members", []): + if isinstance(entry, dict): + entries.append({ + "created": entry.get("Created"), "severity": entry.get("Severity"), + "message": str(entry.get("Message") or "")[:240], "source": source, "id": entry.get("Id"), + }) + unique = {(e["source"], e["id"]): e for e in entries}.values() + newest = sorted(unique, key=lambda e: str(e["created"] or ""), reverse=True)[:limit] + return {"hostname": hostname, "sources": sources, "entries": newest} + + def redfish_firmware(self, hostname: str) -> dict: + bmc = self._redfish_bmc(hostname) + try: + members = self._redfish_read(bmc, "/redfish/v1/UpdateService/FirmwareInventory?$expand=.($levels=1)").get("Members", []) + if members and set(members[0]) <= {"@odata.id"}: + raise RedfishError(501, "expand not honored") + except RedfishError: + paths = redfish_member_paths(self._redfish_read(bmc, "/redfish/v1/UpdateService/FirmwareInventory")) + members = [self._redfish_read(bmc, path) for path in paths[:100]] + return {"hostname": hostname, "firmware": [ + {"id": m.get("Id"), "name": m.get("Name"), "version": m.get("Version"), + "updateable": m.get("Updateable"), "health": health(m)} + for m in members if isinstance(m, dict) + ]} + + def redfish_tool(self, call, *args) -> str: + try: + payload = call(*args) + except RedfishError as error: + payload = {"error": str(error), "status": error.status} + except ValueError as error: + payload = {"error": str(error), "status": 400} + except RuntimeError: + logging.getLogger("mosaic.bcm").exception("Redfish BCM lookup failed") + payload = {"error": "BCM lookup for the BMC failed", "status": 502} + text = json.dumps(payload, separators=(",", ":"), default=str) + if len(text) > REDFISH_MAX_CHARS: + text = (text[:REDFISH_MAX_CHARS] + "\n...(truncated: use a named Redfish tool, a member path, or $top" + " for a smaller response)") + return text + def register_hardware_routes(self, token: str) -> None: def authorized(request: Request) -> bool: return hmac.compare_digest(request.headers.get("authorization", ""), f"Bearer {token}") @@ -251,6 +611,37 @@ async def slurm_job_evidence(job_id: str) -> str: """Return BCM WLM metadata and bounded stdout/stderr for a numeric Slurm job ID.""" return await asyncio.to_thread(self.slurm_job_evidence, job_id) + if self.redfish_enabled: + @self.mcp.tool(name="redfish_get") + async def redfish_get_tool(hostname: str, path: str) -> str: + """Read one allowlisted Redfish resource from a node's BMC with GET.""" + return await asyncio.to_thread(self.redfish_tool, self.redfish_get, hostname, path) + + @self.mcp.tool(name="redfish_system_summary") + async def redfish_system_summary_tool(hostname: str) -> str: + """Return BMC-reported power state, health, model, serial and BIOS version.""" + return await asyncio.to_thread(self.redfish_tool, self.redfish_system_summary, hostname) + + @self.mcp.tool(name="redfish_thermal") + async def redfish_thermal_tool(hostname: str, chassis: str = "") -> str: + """Summarize BMC temperature and fan sensors with thresholds and health.""" + return await asyncio.to_thread(self.redfish_tool, self.redfish_thermal, hostname, chassis) + + @self.mcp.tool(name="redfish_power") + async def redfish_power_tool(hostname: str, chassis: str = "") -> str: + """Return BMC-reported power draw and power supply status.""" + return await asyncio.to_thread(self.redfish_tool, self.redfish_power, hostname, chassis) + + @self.mcp.tool(name="redfish_sel") + async def redfish_sel_tool(hostname: str, limit: int = 50) -> str: + """Return the newest BMC manager and system log entries.""" + return await asyncio.to_thread(self.redfish_tool, self.redfish_sel, hostname, limit) + + @self.mcp.tool(name="redfish_firmware") + async def redfish_firmware_tool(hostname: str) -> str: + """Return the BMC firmware inventory.""" + return await asyncio.to_thread(self.redfish_tool, self.redfish_firmware, hostname) + def main() -> int: host = get_env_str("MOSAIC_BCM_ADAPTER_HOST", "0.0.0.0") or "0.0.0.0" diff --git a/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts b/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts index 25610ec7..a43a4f65 100644 --- a/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts +++ b/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts @@ -29,6 +29,7 @@ type BcmConfig = { hitl: boolean; approvalTimeoutMs: number; slurmEnabled: boolean; + redfishEnabled: boolean; timeoutMs: number; subagentEventsUrl: string; }; @@ -148,6 +149,7 @@ function readConfig(pluginConfig: unknown): BcmConfig { hitl: boolConfig(pluginConfig, "hitl", true), approvalTimeoutMs: numberConfig(pluginConfig, "approvalTimeoutMs", 120_000), slurmEnabled: boolConfig(pluginConfig, "slurmEnabled", false), + redfishEnabled: boolConfig(pluginConfig, "redfishEnabled", false), timeoutMs: numberConfig(pluginConfig, "timeoutMs", DEFAULT_TIMEOUT_MS), subagentEventsUrl: resolveSubagentEventsUrl(pluginConfig), }; @@ -489,6 +491,35 @@ async function callBcmTool( } } +async function redfishTool( + config: BcmConfig, + mcpToolName: string, + args: Record, + options: SubagentOptions, +) { + const result = await callBcmTool(config, mcpToolName, args, options); + const text = textFromResult(result.details); + let payload: unknown; + try { + payload = JSON.parse(text); + } catch { + return result; + } + if (payload && typeof payload === "object" && "error" in payload) { + const { error, status } = payload as { error?: unknown; status?: unknown }; + throw new Error(status === 403 + ? `Redfish request refused: ${String(error)}. Redfish access is read-only; actions and account, session, certificate, and event services are unavailable.` + : `Redfish request failed: ${String(error)}`); + } + return jsonToolResult(payload); +} + +function hostnameParam(value: unknown) { + const hostname = stringParam(value); + if (!/^[A-Za-z0-9][A-Za-z0-9-]{0,62}$/.test(hostname)) throw new Error("hostname must be a BCM node hostname"); + return hostname; +} + function stringParam(value: unknown) { return typeof value === "string" && value.trim() ? value.trim() : ""; } @@ -814,6 +845,91 @@ export default definePluginEntry({ }, }); + if (config.redfishEnabled) { + const hostname = { type: "string", description: "BCM node hostname, for example dgx-03. The BMC address and credentials are resolved from BCM." }; + const chassis = { type: "string", description: "Optional Redfish chassis id. Defaults to the chassis linked to the node's system." }; + const redfishTools: Array<{ + name: string; + label: string; + description: string; + mcpToolName: string; + properties: Record; + args: (params: Record) => Record; + }> = [ + { + name: "bcm_redfish_system_summary", + label: "BCM Redfish System Summary", + description: "Read a node's power state, health, model, serial number, and BIOS version from its BMC over Redfish. Read-only; works when the node is unreachable in-band.", + mcpToolName: "redfish_system_summary", + properties: {}, + args: () => ({}), + }, + { + name: "bcm_redfish_thermal", + label: "BCM Redfish Thermal", + description: "Summarize a node's BMC temperature and fan sensors with thresholds and health over Redfish. Read-only.", + mcpToolName: "redfish_thermal", + properties: { chassis }, + args: (params) => ({ chassis: stringParam(params.chassis) }), + }, + { + name: "bcm_redfish_power", + label: "BCM Redfish Power", + description: "Read a node's power draw and power supply status from its BMC over Redfish. Read-only.", + mcpToolName: "redfish_power", + properties: { chassis }, + args: (params) => ({ chassis: stringParam(params.chassis) }), + }, + { + name: "bcm_redfish_sel", + label: "BCM Redfish Event Log", + description: "Return the newest BMC system event log and manager log entries for a node over Redfish, newest first. Read-only.", + mcpToolName: "redfish_sel", + properties: { limit: { type: "number", description: "Maximum entries to return, 1-200. Default 50." } }, + args: (params) => ({ limit: numberParam(params.limit, 50, 1, 200) }), + }, + { + name: "bcm_redfish_firmware", + label: "BCM Redfish Firmware", + description: "List a node's firmware inventory from its BMC over Redfish. Read-only.", + mcpToolName: "redfish_firmware", + properties: {}, + args: () => ({}), + }, + { + name: "bcm_redfish_get", + label: "BCM Redfish GET", + description: "Read one Redfish resource from a node's BMC with GET. The server allows only inventory, health, sensor, log, firmware, and task paths under /redfish/v1 and refuses actions and account, session, certificate, and event services. Optional query parameters: $expand, $top, $skip.", + mcpToolName: "redfish_get", + properties: { path: { type: "string", description: "Redfish path, for example /redfish/v1/Chassis/DGX/Sensors." } }, + args: (params) => { + const path = stringParam(params.path); + if (!path.startsWith("/redfish/v1") || path.length > 512) throw new Error("path must be a /redfish/v1 resource path"); + return { path }; + }, + }, + ]; + for (const tool of redfishTools) registerTool({ + name: tool.name, + label: tool.label, + description: tool.description, + parameters: { + type: "object", + additionalProperties: false, + required: ["hostname", ...(tool.name === "bcm_redfish_get" ? ["path"] : [])], + properties: { hostname, ...tool.properties }, + }, + async execute(toolCallId: string, rawParams: Record) { + return redfishTool( + config, + tool.mcpToolName, + { hostname: hostnameParam(rawParams.hostname), ...tool.args(rawParams) }, + subagentOptions(config, toolCallId, tool.name, tool.label), + ); + }, + }); + } + registerTool({ name: "bcm_list_notes", label: "BCM List Notes", diff --git a/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/openclaw.plugin.json b/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/openclaw.plugin.json index f4714ad4..1535cb56 100644 --- a/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/openclaw.plugin.json +++ b/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/openclaw.plugin.json @@ -17,7 +17,13 @@ "bcm_list_notes", "bcm_search_notes", "bcm_add_note", - "bcm_remove_note" + "bcm_remove_note", + "bcm_redfish_system_summary", + "bcm_redfish_thermal", + "bcm_redfish_power", + "bcm_redfish_sel", + "bcm_redfish_firmware", + "bcm_redfish_get" ], "trustedToolPolicies": ["bcm-access"] }, @@ -74,6 +80,10 @@ "type": "boolean", "description": "Expose BCM WLM-backed Slurm job evidence." }, + "redfishEnabled": { + "type": "boolean", + "description": "Expose read-only Redfish tools that read node BMCs through the BCM MCP service." + }, "timeoutMs": { "type": "number", "minimum": 1000, diff --git a/helm/mosaic-stack/files/openclaw-seed/nemoclaw.json b/helm/mosaic-stack/files/openclaw-seed/nemoclaw.json index 0e94b506..dfe9bf85 100644 --- a/helm/mosaic-stack/files/openclaw-seed/nemoclaw.json +++ b/helm/mosaic-stack/files/openclaw-seed/nemoclaw.json @@ -302,7 +302,8 @@ "editEnabled": {{ and .Values.modules.edit.enabled .Values.modules.edit.bcm.enabled (eq (include "mosaic-stack.bcmEnabled" .) "true") }}, "hitl": {{ .Values.modules.edit.hitl }}, "approvalTimeoutMs": {{ .Values.modules.edit.approvalTimeoutMs }}, - "slurmEnabled": {{ eq (include "mosaic-stack.slurmBcmEnabled" .) "true" }} + "slurmEnabled": {{ eq (include "mosaic-stack.slurmBcmEnabled" .) "true" }}, + "redfishEnabled": {{ and .Values.modules.bcm.redfish.enabled (eq (include "mosaic-stack.bcmEnabled" .) "true") }} } }, "remote-ssh": { diff --git a/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md b/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md index e3846f47..904cda54 100644 --- a/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md +++ b/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md @@ -44,3 +44,16 @@ Pass CMSH commands as the same semicolon-separated command string used by `cmsh - `kubernetes; foreach * (show)` For broad cluster summaries, combine `bcm_get_info` with `bcm_execute_cmsh` command strings such as `kubernetes; list`, `category; list`, and `device; list`. For a short inventory, summarize the first rows returned by `device; list`; do not use shell pipes or `limit` inside CMSH. + +## Redfish (out-of-band) + +When the `bcm_redfish_*` tools are registered, they read a node's BMC over Redfish through the Base Command Manager service. Prefer them over CMSH when the node is unreachable in-band or down, for power state, hardware health, temperature, fan, power supply, or system event log questions, and for firmware inventory. Pass only the Base Command Manager hostname; the service resolves the BMC address and credentials from Base Command Manager. Never ask the user for BMC addresses, usernames, or passwords, and never put them in a reply. + +Redfish access is read-only in every session mode. Resets, power actions, BMC configuration, accounts, sessions, certificates, event subscriptions, and virtual media are unavailable; if the user asks for one, say that Redfish actions are not available through this agent rather than retrying through another tool. A refusal from `bcm_redfish_get` means the path is outside the read-only allowlist. + +Use the named tools first: `bcm_redfish_system_summary` (power state, health, model, BIOS version), `bcm_redfish_thermal` (temperatures closest to their thresholds and fan readings), `bcm_redfish_power` (power draw and power supplies), `bcm_redfish_sel` (newest BMC event log entries across log services), and `bcm_redfish_firmware`. Systems such as DGX expose several chassis; pass `chassis` to the thermal or power tool, for example a GPU baseboard chassis, when the default chassis does not cover the question. Use `bcm_redfish_get` with an allowlisted `/redfish/v1/...` path only for detail the named tools omit, starting from a collection such as `/redfish/v1/Chassis` to discover member ids. + +Examples: + +- "What's the power state and health of dgx-03 according to its BMC?" → `bcm_redfish_system_summary` with `hostname: "dgx-03"`. +- "Show the last 20 SEL entries on dgx-03" → `bcm_redfish_sel` with `hostname: "dgx-03", limit: 20`; report timestamp, severity, source, and message for each entry. diff --git a/helm/mosaic-stack/templates/bcm-mcp-tools.yaml b/helm/mosaic-stack/templates/bcm-mcp-tools.yaml index 60f088c6..6b745fd0 100644 --- a/helm/mosaic-stack/templates/bcm-mcp-tools.yaml +++ b/helm/mosaic-stack/templates/bcm-mcp-tools.yaml @@ -127,6 +127,16 @@ spec: value: {{ .Values.bcmMcp.config.cmshExecTimeout | default "120" | quote }} - name: MOSAIC_BCM_CMSH_PATH value: {{ .Values.bcmMcp.config.cmshPath | default "/cm/local/apps/cmd/bin/cmsh" | quote }} + {{- if .Values.modules.bcm.redfish.enabled }} + - name: MOSAIC_BCM_REDFISH_ENABLED + value: "true" + - name: MOSAIC_BCM_REDFISH_VERIFY_TLS + value: {{ .Values.modules.bcm.redfish.verifyTls | quote }} + - name: MOSAIC_BCM_REDFISH_TIMEOUT + value: {{ .Values.modules.bcm.redfish.timeoutSeconds | quote }} + - name: MOSAIC_BCM_REDFISH_VIA_HEAD_NODE + value: {{ .Values.modules.bcm.redfish.viaHeadNode | quote }} + {{- end }} {{- end }} ports: - containerPort: {{ .Values.bcmMcp.service.port }} diff --git a/helm/mosaic-stack/templates/validation.yaml b/helm/mosaic-stack/templates/validation.yaml index f4632633..ada7d401 100644 --- a/helm/mosaic-stack/templates/validation.yaml +++ b/helm/mosaic-stack/templates/validation.yaml @@ -24,6 +24,14 @@ {{- fail (printf "Slack edit user %q must also appear in openclaw.slack.allowedUserIds" .) -}} {{- end -}} {{- end -}} +{{- if .Values.modules.bcm.redfish.enabled -}} +{{- if not (and .Values.modules.bcm.enabled .Values.bcmMcp.enabled (eq .Values.bcmMcp.mode "ssh-adapter")) -}} +{{- fail "modules.bcm.redfish.enabled requires modules.bcm.enabled=true, bcmMcp.enabled=true and bcmMcp.mode=ssh-adapter" -}} +{{- end -}} +{{- if or (lt (int .Values.modules.bcm.redfish.timeoutSeconds) 1) (gt (int .Values.modules.bcm.redfish.timeoutSeconds) 300) -}} +{{- fail "modules.bcm.redfish.timeoutSeconds must be between 1 and 300" -}} +{{- end -}} +{{- end -}} {{- if and .Values.modules.slurm.enabled (eq .Values.modules.slurm.backend "bcm") (ne (include "mosaic-stack.bcmEnabled" .) "true") -}} {{- fail "modules.slurm.backend=bcm requires an enabled BCM MCP service" -}} {{- end -}} diff --git a/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs b/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs index 3ca0e416..c9093fe8 100644 --- a/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs +++ b/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs @@ -56,3 +56,98 @@ test("retains the authenticated admin backend without readonly fallback", () => assert.match(adapter, /StaticTokenVerifier/); assert.doesNotMatch(adapter, /_run_cmsh_admin[\s\S]*?su\s+-/); }); + +const redfishToolNames = [ + "bcm_redfish_system_summary", + "bcm_redfish_thermal", + "bcm_redfish_power", + "bcm_redfish_sel", + "bcm_redfish_firmware", + "bcm_redfish_get", +]; + +async function loadBcmPlugin() { + const { registerHooks } = await import("node:module"); + const hooks = registerHooks({ + resolve(specifier, context, nextResolve) { + if (specifier === "openclaw/plugin-sdk/plugin-entry") return { + url: "data:text/javascript,export const definePluginEntry = entry => entry;", shortCircuit: true, + }; + return nextResolve(specifier, context); + }, + }); + try { + return (await import("../files/openclaw-seed/extensions/bcm/index.ts")).default; + } finally { + hooks.deregister(); + } +} + +function registerBcm(plugin, pluginConfig) { + const tools = new Map(); + let policy; + plugin.register({ + pluginConfig: { cmshEnabled: true, ...pluginConfig }, + session: { state: { registerSessionExtension() {} } }, + registerTrustedToolPolicy: value => { policy = value; }, + registerTool: tool => tools.set(tool.name, tool), + }); + return { tools, policy }; +} + +test("registers read-only Redfish tools only when enabled", async () => { + const plugin = await loadBcmPlugin(); + const disabled = registerBcm(plugin, {}); + assert.deepEqual(redfishToolNames.filter(name => disabled.tools.has(name)), []); + const enabled = registerBcm(plugin, { redfishEnabled: true }); + assert.deepEqual(redfishToolNames.filter(name => enabled.tools.has(name)), redfishToolNames); + const manifest = JSON.parse(readFileSync( + new URL("../files/openclaw-seed/extensions/bcm/openclaw.plugin.json", import.meta.url), + )); + for (const name of redfishToolNames) assert.ok(manifest.contracts.tools.includes(name), name); + assert.equal(manifest.configSchema.properties.redfishEnabled.type, "boolean"); +}); + +test("never treats Redfish tools as mutations", async () => { + const plugin = await loadBcmPlugin(); + const { policy } = registerBcm(plugin, { redfishEnabled: true, editEnabled: true }); + const automation = "agent:default:mosaic-automation-alert-node-down"; + assert.equal((await policy.evaluate({ toolName: "bcm_add_note", toolCallId: "call-0", params: {} }, { sessionKey: automation })).block, true); + for (const toolName of redfishToolNames) { + for (const sessionKey of ["agent:default:main", automation]) { + assert.equal(await policy.evaluate({ toolName, toolCallId: "call-1", params: {} }, { sessionKey }), undefined); + } + } +}); + +test("surfaces Redfish policy refusals and validates hostnames before calling the backend", async () => { + const plugin = await loadBcmPlugin(); + const { tools } = registerBcm(plugin, { redfishEnabled: true, mcpUrl: "http://bcm.test/mcp", authToken: "token" }); + const calls = []; + const originalFetch = globalThis.fetch; + globalThis.fetch = async (url, init) => { + if (String(url).includes("/api/subagents/events")) return new Response("{}"); + const request = JSON.parse(init.body); + calls.push(request.params); + const payload = request.params.arguments.path === "/redfish/v1/AccountService" + ? { error: "/redfish/v1/AccountService is not permitted by the read-only Redfish policy", status: 403 } + : { hostname: request.params.arguments.hostname, systems: [{ id: "DGX", powerState: "On", health: "OK" }] }; + return new Response(JSON.stringify({ jsonrpc: "2.0", id: request.id, result: { content: [{ type: "text", text: JSON.stringify(payload) }] } })); + }; + try { + await assert.rejects( + tools.get("bcm_redfish_get").execute("call-1", { hostname: "dgx-03", path: "/redfish/v1/AccountService" }), + /Redfish request refused: .*read-only/, + ); + const summary = await tools.get("bcm_redfish_system_summary").execute("call-2", { hostname: "dgx-03" }); + assert.equal(summary.details.systems[0].powerState, "On"); + assert.deepEqual(calls.map(call => call.name), ["redfish_get", "redfish_system_summary"]); + for (const hostname of ["dgx-03;reboot", "../dgx", "", "10.0.0.1"]) { + await assert.rejects(tools.get("bcm_redfish_thermal").execute("call-3", { hostname }), /hostname must be a BCM node hostname/); + } + await assert.rejects(tools.get("bcm_redfish_get").execute("call-4", { hostname: "dgx-03", path: "https://10.0.0.1/redfish/v1" }), /path must be/); + assert.equal(calls.length, 2); + } finally { + globalThis.fetch = originalFetch; + } +}); diff --git a/helm/mosaic-stack/tests/chart-render.test.mjs b/helm/mosaic-stack/tests/chart-render.test.mjs index d342e030..e65a41d6 100644 --- a/helm/mosaic-stack/tests/chart-render.test.mjs +++ b/helm/mosaic-stack/tests/chart-render.test.mjs @@ -783,6 +783,44 @@ test("renders an authenticated BCM admin path only for BCM edit mode", () => { assert.doesNotMatch(output, /"authToken": "[A-Za-z0-9]{48}"/); }); +const bcmAdapterArgs = [ + "--set", "bcmMcp.enabled=true", + "--set", "bcmMcp.mode=ssh-adapter", + "--set", "bcmMcp.headHost=bcm-head", + "--set", "bcmMcp.hostSshKeySecretName=bcm-host-ssh", +]; + +test("renders read-only Redfish only when enabled", () => { + const disabled = render(...bcmAdapterArgs); + assert.doesNotMatch(disabled, /name: MOSAIC_BCM_REDFISH_/); + assert.match(disabled, /"redfishEnabled": false/); + + const enabled = render(...bcmAdapterArgs, "--set", "modules.bcm.redfish.enabled=true"); + assert.match(enabled, /name: MOSAIC_BCM_REDFISH_ENABLED\s+value: "true"/); + assert.match(enabled, /name: MOSAIC_BCM_REDFISH_VERIFY_TLS\s+value: "false"/); + assert.match(enabled, /name: MOSAIC_BCM_REDFISH_TIMEOUT\s+value: "60"/); + assert.match(enabled, /name: MOSAIC_BCM_REDFISH_VIA_HEAD_NODE\s+value: "true"/); + assert.match(enabled, /"redfishEnabled": true/); + assert.doesNotMatch(enabled, /name: MOSAIC_BCM_REDFISH_(?:USER|PASS|IP)/); + + const direct = render(...bcmAdapterArgs, "--set", "modules.bcm.redfish.enabled=true", + "--set", "modules.bcm.redfish.viaHeadNode=false", "--set", "modules.bcm.redfish.verifyTls=true"); + assert.match(direct, /name: MOSAIC_BCM_REDFISH_VERIFY_TLS\s+value: "true"/); + assert.match(direct, /name: MOSAIC_BCM_REDFISH_VIA_HEAD_NODE\s+value: "false"/); +}); + +test("rejects Redfish without the BCM SSH adapter", () => { + for (const [args, expected] of [ + [["--set", "modules.bcm.redfish.enabled=true"], /modules\.bcm\.redfish\.enabled requires/], + [["--set", "modules.bcm.redfish.enabled=true", "--set", "bcmMcp.enabled=true"], /requires|ssh-adapter/], + [[...bcmAdapterArgs, "--set", "modules.bcm.redfish.enabled=true", "--set", "modules.bcm.redfish.timeoutSeconds=0"], /timeoutSeconds must be between 1 and 300/], + ]) { + const result = spawnSync("helm", ["template", "mosaic", chart, "--namespace", "mosaic-test", ...args], { encoding: "utf8" }); + assert.notEqual(result.status, 0); + assert.match(result.stderr, expected); + } +}); + test("keeps the managed BCM adapter read-only when edit mode is disabled", () => { const output = render( "--set", diff --git a/helm/mosaic-stack/tests/test_bcm_server.py b/helm/mosaic-stack/tests/test_bcm_server.py index af3b0ea2..37d2fcde 100644 --- a/helm/mosaic-stack/tests/test_bcm_server.py +++ b/helm/mosaic-stack/tests/test_bcm_server.py @@ -4,6 +4,7 @@ import asyncio import importlib.util import inspect +import json import subprocess import sys import threading @@ -97,6 +98,11 @@ def server(self): server.cmsh_admin_enabled = False server.hardware_compat_enabled = True server.bcm_head_host = "head.example" + server.redfish_enabled = False + server.redfish_verify_tls = False + server.redfish_timeout = 20 + server.redfish_via_head_node = True + server._redfish_members = {} server._cmsh_ready = False server._cmsh_setup_lock = threading.Lock() return server @@ -181,6 +187,136 @@ def __init__(self, authorization=""): self.assertEqual((denied.status_code, denied.content), (401, {"detail": "unauthorized"})) self.assertEqual((allowed.status_code, allowed.content), (200, {"devices": [], "count": 0})) + def test_redfish_policy_allows_read_only_inventory(self): + policy = self.module.RedfishPolicy + for path in [ + "/redfish/v1", + "/redfish/v1/", + "/redfish/v1/Systems", + "/redfish/v1/Systems/DGX", + "/redfish/v1/Systems/System.Embedded.1/Processors/CPU.1", + "/redfish/v1/Systems/DGX/LogServices/BIOS/Entries?$top=5", + "/redfish/v1/Chassis/DGX/ThermalSubsystem/ThermalMetrics", + "/redfish/v1/Chassis/DGX/PowerSubsystem/PowerSupplies?$expand=.($levels=1)", + "/redfish/v1/Managers/BMC/LogServices/SEL/Entries?$skip=3467&$top=75", + "/redfish/v1/Managers/BMC/EthernetInterfaces/eth0", + "/redfish/v1/UpdateService/FirmwareInventory/CX7_0", + "/redfish/v1/TaskService/Tasks/10", + ]: + self.assertTrue(policy.is_allowed("GET", path), path) + + def test_redfish_policy_rejects_writes_and_sensitive_resources(self): + policy = self.module.RedfishPolicy + self.assertFalse(policy.is_allowed("POST", "/redfish/v1/Systems/DGX")) + self.assertFalse(policy.is_allowed("PATCH", "/redfish/v1/Systems/DGX")) + for path in [ + "/redfish/v1/AccountService", + "/redfish/v1/AccountService/Accounts/2", + "/redfish/v1/SessionService/Sessions", + "/redfish/v1/CertificateService", + "/redfish/v1/EventService/Subscriptions", + "/redfish/v1/Systems/DGX/Actions/ComputerSystem.Reset", + "/redfish/v1/Managers/BMC/Actions/Manager.Reset", + "/redfish/v1/Systems/DGX/LogServices/SEL/Actions/LogService.ClearLog", + "/redfish/v1/Systems/DGX/SecureBoot", + "/redfish/v1/Systems/DGX/Bios/Settings", + "/redfish/v1/Managers/BMC/VirtualMedia/CD1", + "/redfish/v1/Systems/../AccountService", + "/redfish/v1/Systems/DGX/..", + "/redfish/v1//Systems", + "/redfish/v1/Systems/DGX%2F..", + "/redfish/v1/Systems?$filter=Id", + "/redfish/v1/Systems?$expand=*&$select=Id", + "/redfish/v1/Systems?$top=1;rm", + "/redfish/v1/Systems/DGX?", + "/redfish/v1/Systems/DGX#x", + "/redfish/v1/Systems/DGX/Oem", + "/redfish/v1/Managers/BMC/NodeManager", + "/redfish/v1/UpdateService", + "/redfish/v1/Systems/DGX/LogServices/SEL/Entries/1/attachment", + "/redfish/v2", + "https://10.0.0.1/redfish/v1", + "", + ]: + self.assertFalse(policy.is_allowed("GET", path), path) + + def test_redfish_denied_paths_never_resolve_bmc_credentials(self): + server = self.server() + server.hardware_bmc = Mock() + with self.assertRaises(self.module.RedfishError) as raised: + server.redfish_get("atlas-01", "/redfish/v1/AccountService") + self.assertEqual(raised.exception.status, 403) + server.hardware_bmc.assert_not_called() + payload = json.loads(server.redfish_tool(server.redfish_get, "atlas-01", "/redfish/v1/Systems/DGX/Actions/ComputerSystem.Reset")) + self.assertEqual(payload["status"], 403) + + def test_redfish_head_node_transport_keeps_credentials_off_the_command_line(self): + server = self.server() + server.hardware_bmc = Mock(return_value={ + "hostname": "atlas-01", "bmc_ip": "10.30.0.11", "bmc_username": "admin", "bmc_password": 'p"a\\ss', + }) + body = b'{"@odata.type":"#ComputerSystem","Id":"DGX","PowerState":"On","Oem":{"UserPassword":"x","AuthToken":"y"}}' + server._ssh = Mock(return_value=subprocess.CompletedProcess([], 0, body + b"\n200", b"")) + result = server.redfish_get("atlas-01", "/redfish/v1/Systems/DGX") + script, timeout, stdin = server._ssh.call_args.args + self.assertNotIn("p\"a", script) + self.assertIn("-K /dev/stdin", script) + self.assertIn("https://10.30.0.11/redfish/v1/Systems/DGX", script) + self.assertEqual(stdin, b'user = "admin:p\\"a\\\\ss"\n') + self.assertGreater(timeout, server.redfish_timeout) + self.assertEqual(result, {"Id": "DGX", "PowerState": "On", "Oem": {"UserPassword": "[redacted]", "AuthToken": "[redacted]"}}) + + def test_redfish_errors_omit_the_bmc_address(self): + server = self.server() + server.hardware_bmc = Mock(return_value={ + "hostname": "atlas-01", "bmc_ip": "10.30.0.11", "bmc_username": "admin", "bmc_password": "secret", + }) + server._ssh = Mock(return_value=subprocess.CompletedProcess([], 7, b"", b"curl: (7) Failed to connect to 10.30.0.11 port 443")) + text = server.redfish_tool(server.redfish_system_summary, "atlas-01") + self.assertEqual(json.loads(text), {"error": "BMC is unreachable", "status": 502}) + server._ssh = Mock(return_value=subprocess.CompletedProcess([], 0, b"\n401", b"")) + text = server.redfish_tool(server.redfish_get, "atlas-01", "/redfish/v1/Systems") + self.assertEqual(json.loads(text)["status"], 401) + self.assertNotIn("10.30.0.11", text) + self.assertNotIn("secret", text) + + def test_redfish_tools_register_only_when_enabled(self): + names = {"redfish_get", "redfish_system_summary", "redfish_thermal", "redfish_power", "redfish_sel", "redfish_firmware"} + for enabled in (False, True): + server = self.server() + server.redfish_enabled = enabled + server.register_mosaic_tools() + registered = set(server.mcp._tool_manager._tools) & names + self.assertEqual(registered, names if enabled else set()) + + def test_redfish_sel_merges_newest_entries_across_log_services(self): + server = self.server() + server.hardware_bmc = Mock(return_value={"bmc_ip": "10.30.0.11", "bmc_username": "u", "bmc_password": "p"}) + entry = lambda n, day: {"Id": str(n), "Created": f"2026-09-{day:02d}T00:00:00+00:00", "Severity": "OK", "Message": f"event {n}"} + responses = { + "/redfish/v1/Managers": {"Members": [{"@odata.id": "/redfish/v1/Managers/BMC"}]}, + "/redfish/v1/Systems": {"Members": [{"@odata.id": "/redfish/v1/Systems/DGX"}]}, + "/redfish/v1/Managers/BMC/LogServices": {"Members": [ + {"@odata.id": "/redfish/v1/Managers/BMC/LogServices/SEL"}, + {"@odata.id": "/redfish/v1/Managers/BMC/LogServices/Journal"}, + ]}, + "/redfish/v1/Systems/DGX/LogServices": {"Members": [{"@odata.id": "/redfish/v1/Systems/DGX/LogServices/BIOS"}]}, + "/redfish/v1/Managers/BMC/LogServices/SEL/Entries?$top=2": {"Members@odata.count": 5, "Members": [entry(1, 1), entry(2, 2)]}, + "/redfish/v1/Managers/BMC/LogServices/SEL/Entries?$skip=3&$top=2": {"Members": [entry(4, 4), entry(5, 5)]}, + "/redfish/v1/Systems/DGX/LogServices/BIOS/Entries?$top=2": {"Members@odata.count": 1, "Members": [entry(9, 3)]}, + } + requested = [] + + def fetch(_bmc, path): + requested.append(path) + return 200, json.dumps(responses[path]).encode() + + server._redfish_fetch = fetch + result = server.redfish_sel("atlas-01", 2) + self.assertEqual(result["sources"], ["Managers/BMC/SEL", "Systems/DGX/BIOS"]) + self.assertEqual([(e["source"], e["id"]) for e in result["entries"]], [("Managers/BMC/SEL", "5"), ("Managers/BMC/SEL", "4")]) + self.assertNotIn("/redfish/v1/Managers/BMC/LogServices/Journal/Entries?$top=2", requested) + if __name__ == "__main__": unittest.main() diff --git a/helm/mosaic-stack/values.yaml b/helm/mosaic-stack/values.yaml index cbce2c6c..423c2d48 100644 --- a/helm/mosaic-stack/values.yaml +++ b/helm/mosaic-stack/values.yaml @@ -50,6 +50,14 @@ modules: enabled: true bcm: enabled: true + # Read-only Redfish through the BCM MCP SSH adapter; BMCs are resolved by hostname from BCM. + redfish: + enabled: false + # BMCs usually present self-signed certificates. + verifyTls: false + timeoutSeconds: 60 + # Run each GET with curl on the BCM head node, which is routed to the BMC network. + viaHeadNode: true slurm: enabled: true backend: auto From ea1a89e86de28e423ac807914a2a3c059053cfa2 Mon Sep 17 00:00:00 2001 From: Ev Lacey Date: Tue, 27 Oct 2026 16:46:34 -0700 Subject: [PATCH 02/13] Confine Redfish expansion and report incomplete event logs Address review findings on the read-only Redfish tools. $expand could return denied resources: the policy checked only the requested path, so /redfish/v1?$expand=*($levels=5) inlined AccountService. Accept only $expand=. at one level, refuse query parameters on the service root, and check every embedded resource in a response against the allowlist, reducing any outside it to a bare link. bcm_redfish_sel hid read failures: errors reading LogServices or Entries were skipped, so a 403, 503 or 504 looked like an empty log. Report failed sources in errors with complete=false, and fail the call when no log could be read. Log services that reject query parameters are read unqueried. bcm_redfish_sel could omit the newest events: it ignored Members@odata.nextLink. Follow continuation pages, bounded, through the same policy check. Keep oversized results valid JSON by omitting the oldest entries and reporting how many were omitted. Signed-off-by: Ev Lacey --- docs/bcm.md | 10 +- docs/security_model.md | 2 +- .../files/agent-documentation.tar.gz | Bin 31187 -> 31352 bytes helm/mosaic-stack/files/bcm-mcp-ssh-server.py | 106 +++++++++++++--- .../openclaw-seed/extensions/bcm/index.ts | 2 +- .../files/openclaw-seed/skills/bcm/SKILL.md | 2 +- helm/mosaic-stack/tests/test_bcm_server.py | 117 ++++++++++++++++++ 7 files changed, 214 insertions(+), 25 deletions(-) diff --git a/docs/bcm.md b/docs/bcm.md index 15148d34..927f7fa8 100644 --- a/docs/bcm.md +++ b/docs/bcm.md @@ -320,7 +320,8 @@ self-signed certificates, so `modules.bcm.redfish.verifyTls` defaults to `false` 30 seconds to return the expanded firmware inventory. The adapter enforces the following allowlist before it looks up any credential. Only `GET` is -used, and the only query parameters accepted are `$expand`, `$top`, and `$skip`: +used, and the only query parameters accepted are `$top`, `$skip`, and `$expand=.` limited to one +level, which is refused on the service root: | Resource | Paths under `/redfish/v1` | | --- | --- | @@ -332,6 +333,9 @@ used, and the only query parameters accepted are `$expand`, `$top`, and `$skip`: Everything else is refused, including any path containing `Actions`, and `AccountService`, `SessionService`, `CertificateService`, `EventService`, `SecureBoot`, `Bios/Settings`, and -`VirtualMedia`. Paths with `..`, `//`, `%`, or other query parameters are also refused. Fields named -like passwords, tokens, or secrets are redacted from responses. Resets and other BMC actions are not +`VirtualMedia`. Paths with `..`, `//`, `%`, or other query parameters are also refused. The adapter +also checks every resource embedded in a response, such as `$expand` results and continuation pages, +against the same allowlist. It reduces any embedded resource outside it to a bare link, so a BMC that +expands more than requested cannot return denied content. Fields named like passwords, tokens, or +secrets are redacted from responses. Resets and other BMC actions are not available in any session mode. diff --git a/docs/security_model.md b/docs/security_model.md index 47c67549..06223842 100644 --- a/docs/security_model.md +++ b/docs/security_model.md @@ -39,7 +39,7 @@ The read-only and administrative Base Command Manager paths use separate identit Base Command Manager's configured profile remains authoritative. Enabling Base Command Manager administration requires an operator-provided credential with the intended cluster permissions. -When `modules.bcm.redfish.enabled=true`, the `bcm_redfish_*` tools read node BMCs in every mode, including View and automated sessions. They are never mutation tools. The model supplies only a Base Command Manager hostname and a path or named query. The Base Command Manager adapter resolves the BMC address and credentials through CMSH and does not return them. Its `RedfishPolicy` allowlist is enforced server-side before any credential lookup. It permits only `GET` on inventory, health, sensor, log, firmware, and task resources, and rejects any path containing `Actions`, as well as account, session, certificate, event, Secure Boot, BIOS settings, and virtual media resources. Responses have password, token, and secret fields redacted, and errors omit the BMC address. Like other read-only tools, Redfish is not a confidentiality boundary: anything the allowlist permits is visible to the session. +When `modules.bcm.redfish.enabled=true`, the `bcm_redfish_*` tools read node BMCs in every mode, including View and automated sessions. They are never mutation tools. The model supplies only a Base Command Manager hostname and a path or named query. The Base Command Manager adapter resolves the BMC address and credentials through CMSH and does not return them. Its `RedfishPolicy` allowlist is enforced server-side before any credential lookup, and again on every resource embedded in a response, so `$expand` cannot reach a denied resource. It permits only `GET` on inventory, health, sensor, log, firmware, and task resources, and rejects any path containing `Actions`, as well as account, session, certificate, event, Secure Boot, BIOS settings, and virtual media resources. Responses have password, token, and secret fields redacted, and errors omit the BMC address. Like other read-only tools, Redfish is not a confidentiality boundary: anything the allowlist permits is visible to the session. ## Diagnostic Commands And SSH diff --git a/helm/mosaic-stack/files/agent-documentation.tar.gz b/helm/mosaic-stack/files/agent-documentation.tar.gz index 09b778803dd2ae4a9282adf33b4fcafc271cbb9e..3f3378dd84484d371c68fddc9444ceb9f6d7f56f 100644 GIT binary patch delta 26901 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 diff --git a/helm/mosaic-stack/files/bcm-mcp-ssh-server.py b/helm/mosaic-stack/files/bcm-mcp-ssh-server.py index 53b62086..d6b7845d 100644 --- a/helm/mosaic-stack/files/bcm-mcp-ssh-server.py +++ b/helm/mosaic-stack/files/bcm-mcp-ssh-server.py @@ -104,7 +104,7 @@ class RedfishPolicy: "actions", "secureboot", "virtualmedia", }) QUERY = { - "$expand": re.compile(r"[.*~](?:\(\$levels=[1-5]\))?"), + "$expand": re.compile(r"\.(?:\(\$levels=1\))?"), "$top": re.compile(r"[0-9]{1,4}"), "$skip": re.compile(r"[0-9]{1,7}"), } @@ -130,6 +130,8 @@ def normalize(cls, path: str) -> str | None: if not separator or name not in cls.QUERY or not cls.QUERY[name].fullmatch(value): return None params.append(item) + if resource == "/redfish/v1" and params: + return None return resource + ("?" + "&".join(params) if params else "") @classmethod @@ -141,6 +143,9 @@ def is_allowed(cls, method: str, path: str) -> bool: REDFISH_METADATA = ("@odata.context", "@odata.etag", "@odata.type") REDFISH_MAX_CHARS = 32000 REDFISH_MAX_BYTES = 8 * 1024 * 1024 +REDFISH_MAX_PAGES = 50 +REDFISH_MAX_LOG_SERVICES = 10 +REDFISH_MAX_UNQUERIED_ENTRIES = 1000 REDFISH_SKIPPED_LOGS = frozenset({"debugtokenservice", "diagnosticlog", "dump", "fdr", "journal"}) CURL_ERRORS = {6: "BMC address could not be resolved", 7: "BMC is unreachable", 28: "BMC request timed out", 35: "BMC TLS handshake failed", 60: "BMC TLS certificate verification failed"} @@ -158,6 +163,18 @@ def scrub_redfish(value): return value +def confine_redfish(value): + """Reduce embedded resources outside the allowlist, such as $expand results, to bare links.""" + if isinstance(value, list): + return [confine_redfish(item) for item in value] + if not isinstance(value, dict): + return value + link = value.get("@odata.id") + if isinstance(link, str) and set(value) - {"@odata.id"} and RedfishPolicy.normalize(link.split("#", 1)[0]) is None: + return {"@odata.id": link} + return {key: confine_redfish(item) for key, item in value.items()} + + def curl_user_config(username: str, password: str) -> bytes: if any(c in username + password for c in "\r\n\0"): raise RedfishError(502, "BMC credentials in BCM are malformed") @@ -357,7 +374,8 @@ def _redfish_read(self, bmc: dict[str, str], path: str) -> dict: data = json.loads(body) except ValueError as error: raise RedfishError(502, f"BMC returned non-JSON content for {allowed}") from error - return scrub_redfish(data) if isinstance(data, dict) else {"value": scrub_redfish(data)} + data = scrub_redfish(confine_redfish(data)) + return data if isinstance(data, dict) else {"value": data} def _redfish_members_of(self, hostname: str, bmc: dict[str, str], collection: str) -> list[str]: key = (hostname, collection) @@ -479,40 +497,84 @@ def redfish_power(self, hostname: str, chassis: str = "") -> dict: } for s in supplies.get("Members", []) if isinstance(s, dict)] return result + def _redfish_entries(self, bmc: dict[str, str], path: str, limit: int) -> tuple[list[dict], object, bool]: + """Read up to limit members from path, following bounded nextLink pages; report whether more exist.""" + members: list[dict] = [] + count = None + page = path + for _ in range(REDFISH_MAX_PAGES): + data = self._redfish_read(bmc, page) + if count is None: + count = data.get("Members@odata.count") + members += [m for m in data.get("Members", []) if isinstance(m, dict)] + link = data.get("Members@odata.nextLink") + if not isinstance(link, str) or not link or len(members) >= limit: + return members[:limit], count, len(members) > limit or bool(isinstance(link, str) and link) + page = link + return members[:limit], count, True + def redfish_sel(self, hostname: str, limit: int = 50) -> dict: limit = max(1, min(int(limit), 200)) bmc = self._redfish_bmc(hostname) - services = [] + services: list[str] = [] + errors: list[dict] = [] + + def source_of(path: str) -> str: + return path.removeprefix("/redfish/v1/").replace("/LogServices/", "/") + for collection in ("Managers", "Systems"): for member in self._redfish_members_of(hostname, bmc, collection): try: listed = redfish_member_paths(self._redfish_read(bmc, f"{member}/LogServices")) - except RedfishError: + except RedfishError as error: + if error.status != 404: + errors.append({"source": source_of(member), "status": error.status, "error": str(error)}) continue services += [path for path in listed if path.rsplit("/", 1)[1].lower() not in REDFISH_SKIPPED_LOGS and path not in services] + if len(services) > REDFISH_MAX_LOG_SERVICES: + errors.append({"source": None, "status": None, + "error": f"{len(services) - REDFISH_MAX_LOG_SERVICES} more log services were not read"}) entries, sources = [], [] - for service in services[:10]: + for service in services[:REDFISH_MAX_LOG_SERVICES]: + source = source_of(service) try: - first = self._redfish_read(bmc, f"{service}/Entries?$top={limit}") - count = first.get("Members@odata.count") or 0 - pages = [first] + try: + members, count, more = self._redfish_entries(bmc, f"{service}/Entries?$top={limit}", limit) + except RedfishError as error: + if error.status != 400: + raise + # Some log services reject every query parameter; read them unqueried instead. + members, more = self._redfish_entries(bmc, f"{service}/Entries", REDFISH_MAX_UNQUERIED_ENTRIES)[::2] + count = None if isinstance(count, int) and count > limit: - pages.append(self._redfish_read(bmc, f"{service}/Entries?$skip={count - limit}&$top={limit}")) - except RedfishError: + newest, _, _ = self._redfish_entries(bmc, f"{service}/Entries?$skip={count - limit}&$top={limit}", limit) + members += newest + if len(newest) < limit: + errors.append({"source": source, "status": None, + "error": "fewer of the newest entries were returned than requested"}) + elif more: + errors.append({"source": source, "status": None, + "error": "more entries exist than could be read, so the newest may be missing"}) + except RedfishError as error: + errors.append({"source": source, "status": error.status, "error": str(error)}) continue - source = service.removeprefix("/redfish/v1/").replace("/LogServices/", "/") sources.append(source) - for page in pages: - for entry in page.get("Members", []): - if isinstance(entry, dict): - entries.append({ - "created": entry.get("Created"), "severity": entry.get("Severity"), - "message": str(entry.get("Message") or "")[:240], "source": source, "id": entry.get("Id"), - }) + for entry in members: + entries.append({ + "created": entry.get("Created"), "severity": entry.get("Severity"), + "message": str(entry.get("Message") or "")[:240], "source": source, "id": entry.get("Id"), + }) + failed = [e for e in errors if e["status"] is not None] + if failed and not sources: + raise RedfishError(failed[0]["status"], "no BMC event log could be read: " + + "; ".join(f"{e['source']}: {e['error']}" for e in failed[:5])) unique = {(e["source"], e["id"]): e for e in entries}.values() newest = sorted(unique, key=lambda e: str(e["created"] or ""), reverse=True)[:limit] - return {"hostname": hostname, "sources": sources, "entries": newest} + result = {"hostname": hostname, "sources": sources, "entries": newest, "complete": not errors} + if errors: + result["errors"] = errors + return result def redfish_firmware(self, hostname: str) -> dict: bmc = self._redfish_bmc(hostname) @@ -540,6 +602,12 @@ def redfish_tool(self, call, *args) -> str: logging.getLogger("mosaic.bcm").exception("Redfish BCM lookup failed") payload = {"error": "BCM lookup for the BMC failed", "status": 502} text = json.dumps(payload, separators=(",", ":"), default=str) + entries = payload.get("entries") if isinstance(payload, dict) else None + while len(text) > REDFISH_MAX_CHARS and isinstance(entries, list) and entries: + dropped = max(1, len(entries) // 10) + del entries[-dropped:] + payload["omittedOlderEntries"] = payload.get("omittedOlderEntries", 0) + dropped + text = json.dumps(payload, separators=(",", ":"), default=str) if len(text) > REDFISH_MAX_CHARS: text = (text[:REDFISH_MAX_CHARS] + "\n...(truncated: use a named Redfish tool, a member path, or $top" " for a smaller response)") diff --git a/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts b/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts index a43a4f65..0a22ab20 100644 --- a/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts +++ b/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts @@ -899,7 +899,7 @@ export default definePluginEntry({ { name: "bcm_redfish_get", label: "BCM Redfish GET", - description: "Read one Redfish resource from a node's BMC with GET. The server allows only inventory, health, sensor, log, firmware, and task paths under /redfish/v1 and refuses actions and account, session, certificate, and event services. Optional query parameters: $expand, $top, $skip.", + description: "Read one Redfish resource from a node's BMC with GET. The server allows only inventory, health, sensor, log, firmware, and task paths under /redfish/v1 and refuses actions and account, session, certificate, and event services. Optional query parameters: $top, $skip, and $expand=. (one level, not on the service root).", mcpToolName: "redfish_get", properties: { path: { type: "string", description: "Redfish path, for example /redfish/v1/Chassis/DGX/Sensors." } }, args: (params) => { diff --git a/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md b/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md index 904cda54..aa6e7fc1 100644 --- a/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md +++ b/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md @@ -51,7 +51,7 @@ When the `bcm_redfish_*` tools are registered, they read a node's BMC over Redfi Redfish access is read-only in every session mode. Resets, power actions, BMC configuration, accounts, sessions, certificates, event subscriptions, and virtual media are unavailable; if the user asks for one, say that Redfish actions are not available through this agent rather than retrying through another tool. A refusal from `bcm_redfish_get` means the path is outside the read-only allowlist. -Use the named tools first: `bcm_redfish_system_summary` (power state, health, model, BIOS version), `bcm_redfish_thermal` (temperatures closest to their thresholds and fan readings), `bcm_redfish_power` (power draw and power supplies), `bcm_redfish_sel` (newest BMC event log entries across log services), and `bcm_redfish_firmware`. Systems such as DGX expose several chassis; pass `chassis` to the thermal or power tool, for example a GPU baseboard chassis, when the default chassis does not cover the question. Use `bcm_redfish_get` with an allowlisted `/redfish/v1/...` path only for detail the named tools omit, starting from a collection such as `/redfish/v1/Chassis` to discover member ids. +Use the named tools first: `bcm_redfish_system_summary` (power state, health, model, BIOS version), `bcm_redfish_thermal` (temperatures closest to their thresholds and fan readings), `bcm_redfish_power` (power draw and power supplies), `bcm_redfish_sel` (newest BMC event log entries across log services), and `bcm_redfish_firmware`. When `bcm_redfish_sel` returns `complete: false`, report the failed sources from `errors`; missing entries from a failed source are unknown, not an empty log. Systems such as DGX expose several chassis; pass `chassis` to the thermal or power tool, for example a GPU baseboard chassis, when the default chassis does not cover the question. Use `bcm_redfish_get` with an allowlisted `/redfish/v1/...` path only for detail the named tools omit, starting from a collection such as `/redfish/v1/Chassis` to discover member ids. Examples: diff --git a/helm/mosaic-stack/tests/test_bcm_server.py b/helm/mosaic-stack/tests/test_bcm_server.py index 37d2fcde..468fc115 100644 --- a/helm/mosaic-stack/tests/test_bcm_server.py +++ b/helm/mosaic-stack/tests/test_bcm_server.py @@ -317,6 +317,123 @@ def fetch(_bmc, path): self.assertEqual([(e["source"], e["id"]) for e in result["entries"]], [("Managers/BMC/SEL", "5"), ("Managers/BMC/SEL", "4")]) self.assertNotIn("/redfish/v1/Managers/BMC/LogServices/Journal/Entries?$top=2", requested) + def test_redfish_expand_cannot_reach_denied_resources(self): + policy = self.module.RedfishPolicy + for path in [ + "/redfish/v1?$expand=*($levels=5)", + "/redfish/v1?$expand=.", + "/redfish/v1?$top=1", + "/redfish/v1/Systems?$expand=*", + "/redfish/v1/Systems?$expand=~", + "/redfish/v1/Systems?$expand=.($levels=2)", + ]: + self.assertFalse(policy.is_allowed("GET", path), path) + self.assertTrue(policy.is_allowed("GET", "/redfish/v1/Managers?$expand=.($levels=1)")) + + server = self.server() + server.hardware_bmc = Mock(return_value={"bmc_ip": "10.30.0.11", "bmc_username": "u", "bmc_password": "p"}) + expanded = {"@odata.id": "/redfish/v1/Managers", "Members": [ + {"@odata.id": "/redfish/v1/Managers/BMC", "FirmwareVersion": "25.06", "Links": {"ManagerForServers": [{"@odata.id": "/redfish/v1/Systems/DGX"}]}}, + {"@odata.id": "/redfish/v1/Managers/BMC/NodeManager", "NvidiaPSUPolicies": {"Mode": "x"}}, + {"@odata.id": "/redfish/v1/AccountService", "Accounts": {"Members": [{"@odata.id": "/redfish/v1/AccountService/Accounts/2", "UserName": "admin"}]}}, + ]} + server._redfish_fetch = Mock(return_value=(200, json.dumps(expanded).encode())) + result = server.redfish_get("atlas-01", "/redfish/v1/Managers?$expand=.($levels=1)") + self.assertEqual(result["Members"], [ + {"@odata.id": "/redfish/v1/Managers/BMC", "FirmwareVersion": "25.06", "Links": {"ManagerForServers": [{"@odata.id": "/redfish/v1/Systems/DGX"}]}}, + {"@odata.id": "/redfish/v1/Managers/BMC/NodeManager"}, + {"@odata.id": "/redfish/v1/AccountService"}, + ]) + self.assertNotIn("admin", json.dumps(result)) + + def test_redfish_sel_reports_failed_log_reads(self): + server = self.server() + server.hardware_bmc = Mock(return_value={"bmc_ip": "10.30.0.11", "bmc_username": "u", "bmc_password": "p"}) + entry = {"Id": "1", "Created": "2026-09-01T00:00:00+00:00", "Severity": "Critical", "Message": "PSU fault"} + statuses = {} + base = { + "/redfish/v1/Managers": {"Members": [{"@odata.id": "/redfish/v1/Managers/BMC"}]}, + "/redfish/v1/Systems": {"Members": [{"@odata.id": "/redfish/v1/Systems/DGX"}]}, + "/redfish/v1/Managers/BMC/LogServices": {"Members": [{"@odata.id": "/redfish/v1/Managers/BMC/LogServices/SEL"}]}, + "/redfish/v1/Systems/DGX/LogServices": {"Members": [{"@odata.id": "/redfish/v1/Systems/DGX/LogServices/EventLog"}]}, + "/redfish/v1/Managers/BMC/LogServices/SEL/Entries?$top=50": {"Members@odata.count": 1, "Members": [entry]}, + "/redfish/v1/Systems/DGX/LogServices/EventLog/Entries?$top=50": {"Members@odata.count": 1, "Members": [entry]}, + } + + def fetch(_bmc, path): + if path in statuses: + return statuses[path], b"" + return 200, json.dumps(base[path]).encode() + + server._redfish_fetch = fetch + statuses["/redfish/v1/Systems/DGX/LogServices/EventLog/Entries?$top=50"] = 503 + partial = server.redfish_sel("atlas-01") + self.assertFalse(partial["complete"]) + self.assertEqual(partial["sources"], ["Managers/BMC/SEL"]) + self.assertEqual([(e["source"], e["status"]) for e in partial["errors"]], [("Systems/DGX/EventLog", 503)]) + self.assertEqual(len(partial["entries"]), 1) + + for status in (403, 503, 504): + server._redfish_members = {} + statuses.clear() + statuses["/redfish/v1/Managers/BMC/LogServices/SEL/Entries?$top=50"] = status + statuses["/redfish/v1/Systems/DGX/LogServices"] = status + payload = json.loads(server.redfish_tool(server.redfish_sel, "atlas-01")) + self.assertEqual(payload["status"], status) + self.assertIn("no BMC event log could be read", payload["error"]) + self.assertNotIn("entries", payload) + + def test_redfish_sel_follows_next_links_for_newest_entries(self): + server = self.server() + server.hardware_bmc = Mock(return_value={"bmc_ip": "10.30.0.11", "bmc_username": "u", "bmc_password": "p"}) + events = [{"Id": str(n), "Created": f"2026-09-{n:02d}T00:00:00+00:00", "Severity": "OK", "Message": f"event {n}"} + for n in range(1, 11)] + service = "/redfish/v1/Managers/BMC/LogServices/SEL" + + def fetch(_bmc, path): + if path == "/redfish/v1/Managers": + return 200, json.dumps({"Members": [{"@odata.id": "/redfish/v1/Managers/BMC"}]}).encode() + if path == "/redfish/v1/Systems": + return 200, json.dumps({"Members": []}).encode() + if path == "/redfish/v1/Managers/BMC/LogServices": + return 200, json.dumps({"Members": [{"@odata.id": service}]}).encode() + params = dict(item.split("=") for item in path.partition("?")[2].split("&") if item) + skip, top = int(params.get("$skip", 0)), int(params.get("$top", len(events))) + page = events[skip:skip + min(top, 2)] + body = {"Members@odata.count": len(events), "Members": page} + if skip + len(page) < min(skip + top, len(events)): + body["Members@odata.nextLink"] = f"{service}/Entries?$skip={skip + 2}&$top={top - 2}" + return 200, json.dumps(body).encode() + + server._redfish_fetch = fetch + result = server.redfish_sel("atlas-01", 4) + self.assertEqual([e["id"] for e in result["entries"]], ["10", "9", "8", "7"]) + self.assertTrue(result["complete"]) + + def unqueried(_bmc, path): + if path.endswith("/Entries"): + return 200, json.dumps({"Members": events[:5], "Members@odata.nextLink": f"{service}/Entries?$skip=5"}).encode() + if path.endswith("/Entries?$skip=5"): + return 200, json.dumps({"Members": events[5:]}).encode() + if "/Entries?" in path: + return 400, b"" + return fetch(_bmc, path) + + server._redfish_fetch = unqueried + server._redfish_members = {} + result = server.redfish_sel("atlas-01", 4) + self.assertEqual([e["id"] for e in result["entries"]], ["10", "9", "8", "7"]) + + def test_redfish_sel_output_stays_valid_json_within_budget(self): + server = self.server() + entries = [{"created": f"2026-09-01T00:{n // 60:02d}:{n % 60:02d}", "severity": "OK", "message": "x" * 240, + "source": "Managers/BMC/SEL", "id": str(n)} for n in range(200, 0, -1)] + text = server.redfish_tool(lambda: {"hostname": "atlas-01", "sources": [], "entries": entries, "complete": True}) + payload = json.loads(text) + self.assertLessEqual(len(text), self.module.REDFISH_MAX_CHARS) + self.assertEqual(payload["entries"][0]["id"], "200") + self.assertEqual(len(payload["entries"]) + payload["omittedOlderEntries"], 200) + if __name__ == "__main__": unittest.main() From cdec19c40cd223eea11b2c13cf29dfe9abfcbdd0 Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Fri, 30 Oct 2026 12:07:04 -0700 Subject: [PATCH 03/13] Clarify advertised Redfish actions versus agent capabilities Require capability claims to follow registered tools and session access. Explain that Redfish Actions metadata does not grant an executable tool, and avoid offering unavailable writes or asking for confirmation to perform them. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md | 2 +- helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md b/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md index aa6e7fc1..57dab14e 100644 --- a/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md +++ b/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md @@ -49,7 +49,7 @@ For broad cluster summaries, combine `bcm_get_info` with `bcm_execute_cmsh` comm When the `bcm_redfish_*` tools are registered, they read a node's BMC over Redfish through the Base Command Manager service. Prefer them over CMSH when the node is unreachable in-band or down, for power state, hardware health, temperature, fan, power supply, or system event log questions, and for firmware inventory. Pass only the Base Command Manager hostname; the service resolves the BMC address and credentials from Base Command Manager. Never ask the user for BMC addresses, usernames, or passwords, and never put them in a reply. -Redfish access is read-only in every session mode. Resets, power actions, BMC configuration, accounts, sessions, certificates, event subscriptions, and virtual media are unavailable; if the user asks for one, say that Redfish actions are not available through this agent rather than retrying through another tool. A refusal from `bcm_redfish_get` means the path is outside the read-only allowlist. +Redfish access is read-only in every session mode. Resets, power actions, BMC configuration, accounts, sessions, certificates, event subscriptions, and virtual media are unavailable; if the user asks for one, say that Redfish actions are not available through this agent rather than retrying through another tool. A refusal from `bcm_redfish_get` means the path is outside the read-only allowlist. An `Actions` object in a returned resource is descriptive metadata, not an executable tool. When reporting it, distinguish the actions the BMC advertises from the read-only operations available through the registered Redfish tools. Do not offer to execute advertised actions or ask for confirmation to perform them. Use the named tools first: `bcm_redfish_system_summary` (power state, health, model, BIOS version), `bcm_redfish_thermal` (temperatures closest to their thresholds and fan readings), `bcm_redfish_power` (power draw and power supplies), `bcm_redfish_sel` (newest BMC event log entries across log services), and `bcm_redfish_firmware`. When `bcm_redfish_sel` returns `complete: false`, report the failed sources from `errors`; missing entries from a failed source are unknown, not an empty log. Systems such as DGX expose several chassis; pass `chassis` to the thermal or power tool, for example a GPU baseboard chassis, when the default chassis does not cover the question. Use `bcm_redfish_get` with an allowlisted `/redfish/v1/...` path only for detail the named tools omit, starting from a collection such as `/redfish/v1/Chassis` to discover member ids. diff --git a/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md b/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md index 90ebe20c..5f4200d9 100644 --- a/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md +++ b/helm/mosaic-stack/files/openclaw-seed/workspace/AGENTS.md @@ -61,7 +61,7 @@ For GPU networking measurement or diagnosis, read the gpu-networking skill and i A Kubernetes cluster contains only its registered nodes. The physical fleet can also include other Kubernetes clusters, scheduler-managed nodes, bare-metal services, and management hosts. An empty GPU inventory in one Kubernetes context says nothing about GPUs elsewhere in the fleet. -Establish capabilities from this session's registered tools and configured targets. Pods, labels, or services belonging to another deployment do not establish that this agent has that integration, credentials, or access. For broader inventory, use configured BCM inventory tools, additional registered Kubernetes clusters, Slurm inventory, or monitoring targets as appropriate. Correlate hostnames and addresses across sources and state each source's coverage. If no broader inventory is available, report that boundary without concluding the hosts do not exist. Inventory discovery does not authorize access to newly found hosts. +Establish capabilities from this session's registered tools and configured targets. Before offering an operation, verify that a registered tool supports it in the current session. Actions advertised by a remote API describe the target's capabilities, not this agent's executable capabilities. Describe unsupported operations as unavailable; requesting confirmation does not make an unsupported operation executable. Pods, labels, or services belonging to another deployment do not establish that this agent has that integration, credentials, or access. For broader inventory, use configured BCM inventory tools, additional registered Kubernetes clusters, Slurm inventory, or monitoring targets as appropriate. Correlate hostnames and addresses across sources and state each source's coverage. If no broader inventory is available, report that boundary without concluding the hosts do not exist. Inventory discovery does not authorize access to newly found hosts. For service-placement questions, distinguish the agent runtime, proxies, and backend service. Inspect the current deployment's non-secret configuration and follow service references and upstream endpoints before identifying where the backend runs. An agent pod's node or GPU allocation does not establish the inference server's placement or GPU count. Confirm those from the backend's deployment or host evidence. Chart source may not be mounted; rendered workloads and ConfigMaps remain useful read-only evidence. Never retrieve Secrets or dump credential-bearing configuration for this purpose. From c3476edf6e1f06e90e510f10728fe82bdec01e29 Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Wed, 28 Oct 2026 13:59:28 -0700 Subject: [PATCH 04/13] Classify Redfish tools as read-only in the global session policy The deployed application rejected all six Redfish tools as unclassified even though BCM registered them as read-only. Add the explicit Redfish API tools to the shared read-only classification and verify that every registered Redfish tool remains available without Edit mode; existing mutation policy is unchanged. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- .../files/openclaw-seed/extensions/automation-context.ts | 6 ++++++ helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/helm/mosaic-stack/files/openclaw-seed/extensions/automation-context.ts b/helm/mosaic-stack/files/openclaw-seed/extensions/automation-context.ts index c77afb6e..cc970398 100644 --- a/helm/mosaic-stack/files/openclaw-seed/extensions/automation-context.ts +++ b/helm/mosaic-stack/files/openclaw-seed/extensions/automation-context.ts @@ -27,6 +27,12 @@ const READ_ONLY_TOOLS = new Set([ "bcm_health", "bcm_list_notes", "bcm_node_health_summary", + "bcm_redfish_firmware", + "bcm_redfish_get", + "bcm_redfish_power", + "bcm_redfish_sel", + "bcm_redfish_system_summary", + "bcm_redfish_thermal", "bcm_search_notes", "bcm_search_tools", "dashboard_create", diff --git a/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs b/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs index c9093fe8..9c57b444 100644 --- a/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs +++ b/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs @@ -4,6 +4,7 @@ import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; +import { toolAccess, toolRequiresEdit } from "../files/openclaw-seed/extensions/automation-context.ts"; const plugin = readFileSync( new URL("../files/openclaw-seed/extensions/bcm/index.ts", import.meta.url), @@ -66,6 +67,13 @@ const redfishToolNames = [ "bcm_redfish_get", ]; +test("classifies every registered Redfish tool as read-only in the global session policy", () => { + for (const name of redfishToolNames) { + assert.equal(toolAccess(name), "read", name); + assert.equal(toolRequiresEdit(name), false, name); + } +}); + async function loadBcmPlugin() { const { registerHooks } = await import("node:module"); const hooks = registerHooks({ From f1c1a9b3dd5216ce374c11a88c4513b6ea4ea9b2 Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Fri, 30 Oct 2026 12:53:13 -0700 Subject: [PATCH 05/13] Sanitize credentials in Redfish task payloads Redact sensitive HTTP headers and recursively sanitize JSON-encoded task bodies before returning Redfish data to the model or UI telemetry. Preserve task state, request metadata, and non-secret fields; redact malformed encoded bodies and header containers that cannot be inspected safely. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- helm/mosaic-stack/files/bcm-mcp-ssh-server.py | 38 ++++++++++++++++--- helm/mosaic-stack/tests/test_bcm_server.py | 27 +++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/helm/mosaic-stack/files/bcm-mcp-ssh-server.py b/helm/mosaic-stack/files/bcm-mcp-ssh-server.py index fb08ae20..c94b08f9 100644 --- a/helm/mosaic-stack/files/bcm-mcp-ssh-server.py +++ b/helm/mosaic-stack/files/bcm-mcp-ssh-server.py @@ -150,13 +150,41 @@ def is_allowed(cls, method: str, path: str) -> bool: 35: "BMC TLS handshake failed", 60: "BMC TLS certificate verification failed"} +def redfish_secret_key(key: str) -> bool: + key = key.lower().replace("-", "").replace("_", "") + return key.endswith((*REDFISH_SECRET_SUFFIXES, "apikey")) or key in { + "authorization", "proxyauthorization", "cookie", "setcookie", + } + + +def scrub_redfish_header(header) -> str: + if not isinstance(header, str): + return "[redacted]" + name, separator, _ = header.partition(":") + if not separator: + return "[redacted]" + return f"{name}: [redacted]" if redfish_secret_key(name.strip()) else header + + def scrub_redfish(value): if isinstance(value, dict): - return { - key: "[redacted]" if key.lower().endswith(REDFISH_SECRET_SUFFIXES) else scrub_redfish(item) - for key, item in value.items() - if key not in REDFISH_METADATA - } + result = {} + for key, item in value.items(): + if key in REDFISH_METADATA: + continue + if redfish_secret_key(key): + item = "[redacted]" + elif key.lower() == "httpheaders": + item = [scrub_redfish_header(header) for header in item] if isinstance(item, list) else "[redacted]" + elif key.lower() == "jsonbody" and isinstance(item, str) and item: + try: + item = json.dumps(scrub_redfish(json.loads(item))) + except ValueError: + item = "[redacted]" + else: + item = scrub_redfish(item) + result[key] = item + return result if isinstance(value, list): return [scrub_redfish(item) for item in value] return value diff --git a/helm/mosaic-stack/tests/test_bcm_server.py b/helm/mosaic-stack/tests/test_bcm_server.py index c73fc5b1..070cd91b 100644 --- a/helm/mosaic-stack/tests/test_bcm_server.py +++ b/helm/mosaic-stack/tests/test_bcm_server.py @@ -340,6 +340,33 @@ def test_redfish_errors_omit_the_bmc_address(self): self.assertNotIn("10.30.0.11", text) self.assertNotIn("secret", text) + def test_redfish_task_payload_redacts_secrets_without_losing_diagnostics(self): + for secret_key, header in (("Password", "Authorization"), ("ClientSecret", "X-Api-Key"), ("AccessToken", "Cookie")): + with self.subTest(secret_key=secret_key, header=header): + server = self.server() + server.hardware_bmc = Mock(return_value={}) + payload = { + "@odata.id": "/redfish/v1/TaskService/Tasks/42", + "TaskState": "Completed", + "Payload": { + "HttpOperation": "POST", + "HttpHeaders": [f"{header}: private-value", "Content-Type: application/json"], + "JsonBody": json.dumps({"nested": {secret_key: "private-value", "Mode": "diagnostic"}}), + }, + } + server._redfish_fetch = Mock(return_value=(200, json.dumps(payload).encode())) + result = server.redfish_get("atlas-01", payload["@odata.id"]) + self.assertNotIn("private-value", json.dumps(result)) + self.assertEqual(result["TaskState"], "Completed") + self.assertEqual(result["Payload"]["HttpOperation"], "POST") + self.assertIn("Content-Type: application/json", result["Payload"]["HttpHeaders"]) + body = json.loads(result["Payload"]["JsonBody"]) + self.assertEqual(body["nested"]["Mode"], "diagnostic") + self.assertEqual(body["nested"][secret_key], "[redacted]") + self.assertEqual(self.module.scrub_redfish({"JsonBody": "not JSON"})["JsonBody"], "[redacted]") + self.assertEqual(self.module.scrub_redfish({"HttpHeaders": "Authorization: private-value"}), + {"HttpHeaders": "[redacted]"}) + def test_redfish_tools_register_only_when_enabled(self): names = {"redfish_get", "redfish_system_summary", "redfish_thermal", "redfish_power", "redfish_sel", "redfish_firmware"} for enabled in (False, True): From e6cbf8e0334b304e3875c2fa970b145a10d394df Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Fri, 30 Oct 2026 12:57:08 -0700 Subject: [PATCH 06/13] Bound Redfish downloads before buffering SSH output Limit curl downloads and cap SSH stdout while data arrives, terminating and reaping the child on oversized output or timeout. Use nonblocking input and output so the deadline also covers blocked credential input. Preserve existing CMSH calls and direct-transport limits; verify bounded reads, timeouts, and process cleanup without contacting hardware. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- helm/mosaic-stack/files/bcm-mcp-ssh-server.py | 65 ++++++++++++++++--- helm/mosaic-stack/tests/test_bcm_server.py | 37 +++++++++++ 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/helm/mosaic-stack/files/bcm-mcp-ssh-server.py b/helm/mosaic-stack/files/bcm-mcp-ssh-server.py index c94b08f9..49d8d513 100644 --- a/helm/mosaic-stack/files/bcm-mcp-ssh-server.py +++ b/helm/mosaic-stack/files/bcm-mcp-ssh-server.py @@ -7,12 +7,15 @@ import ipaddress import json import logging +import os import re +import selectors import shlex import ssl import subprocess import textwrap import threading +import time import urllib.error import urllib.request @@ -147,7 +150,8 @@ def is_allowed(cls, method: str, path: str) -> bool: REDFISH_MAX_UNQUERIED_ENTRIES = 1000 REDFISH_SKIPPED_LOGS = frozenset({"debugtokenservice", "diagnosticlog", "dump", "fdr", "journal"}) CURL_ERRORS = {6: "BMC address could not be resolved", 7: "BMC is unreachable", 28: "BMC request timed out", - 35: "BMC TLS handshake failed", 60: "BMC TLS certificate verification failed"} + 35: "BMC TLS handshake failed", 60: "BMC TLS certificate verification failed", + 63: "BMC response exceeds the size limit"} def redfish_secret_key(key: str) -> bool: @@ -258,16 +262,55 @@ def __init__(self, *args, **kwargs): self._cmsh_ready = False self._cmsh_setup_lock = threading.Lock() - def _ssh(self, script: str, timeout: int, stdin: bytes | None = None) -> subprocess.CompletedProcess[bytes]: + def _ssh(self, script: str, timeout: int, stdin: bytes | None = None, + max_output_bytes: int | None = None) -> subprocess.CompletedProcess[bytes]: if not self.bcm_head_host: raise RuntimeError("BCM head host is not configured") - return subprocess.run( - ["ssh", self.bcm_head_host, "sh -lc " + shlex.quote(script)], - capture_output=True, - timeout=timeout, - check=False, - input=stdin, - ) + command = ["ssh", self.bcm_head_host, "sh -lc " + shlex.quote(script)] + if max_output_bytes is None: + return subprocess.run(command, capture_output=True, timeout=timeout, check=False, input=stdin) + deadline = time.monotonic() + timeout + with subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) as process: + try: + output = bytearray() + pending = memoryview(stdin or b"") + with selectors.DefaultSelector() as selector: + selector.register(process.stdout, selectors.EVENT_READ) + if pending: + os.set_blocking(process.stdin.fileno(), False) + selector.register(process.stdin, selectors.EVENT_WRITE) + else: + process.stdin.close() + while selector.get_map(): + remaining = deadline - time.monotonic() + events = selector.select(max(0, remaining)) + if remaining <= 0 or not events: + raise subprocess.TimeoutExpired(command, timeout) + for key, _ in events: + if key.fileobj is process.stdin: + try: + pending = pending[os.write(key.fd, pending):] + except BlockingIOError: + continue + except BrokenPipeError: + pending = memoryview(b"") + if not pending: + selector.unregister(process.stdin) + process.stdin.close() + else: + chunk = os.read(key.fd, min(65536, max_output_bytes + 1 - len(output))) + if not chunk: + selector.unregister(process.stdout) + output.extend(chunk) + if len(output) > max_output_bytes: + raise RedfishError(502, "BMC response exceeds the size limit") + code = process.wait(timeout=max(0, deadline - time.monotonic())) + return subprocess.CompletedProcess(command, code, bytes(output), b"") + finally: + if process.poll() is None: + process.kill() + process.wait() def _ensure_cmsh_user(self) -> None: if self._cmsh_ready: @@ -374,12 +417,14 @@ def _redfish_fetch(self, bmc: dict[str, str], path: str) -> tuple[int, bytes]: url = f"https://{bmc['bmc_ip']}{path}" if self.redfish_via_head_node: command = ["curl", "-sS", "--proto", "=https", "--max-time", str(self.redfish_timeout), + "--max-filesize", str(REDFISH_MAX_BYTES), "-H", "Accept: application/json", "-K", "/dev/stdin", "-w", "\n%{http_code}"] if not self.redfish_verify_tls: command.append("-k") try: result = self._ssh(shlex.join(command + [url]), self.redfish_timeout + 30, - curl_user_config(bmc["bmc_username"], bmc["bmc_password"])) + curl_user_config(bmc["bmc_username"], bmc["bmc_password"]), + max_output_bytes=REDFISH_MAX_BYTES + 4) except subprocess.TimeoutExpired as error: raise RedfishError(504, "BMC request timed out") from error if result.returncode != 0: diff --git a/helm/mosaic-stack/tests/test_bcm_server.py b/helm/mosaic-stack/tests/test_bcm_server.py index 070cd91b..b92976df 100644 --- a/helm/mosaic-stack/tests/test_bcm_server.py +++ b/helm/mosaic-stack/tests/test_bcm_server.py @@ -115,6 +115,43 @@ def test_ssh_always_targets_the_configured_head(self): self.assertEqual(run.call_args.args[0][:2], ["ssh", "head.example"]) self.assertNotIn("pip", run.call_args.args[0][-1]) + def test_bounded_ssh_returns_small_output_and_stops_oversized_output(self): + actual_popen = subprocess.Popen + for content, limit in ((b"small response", 128), (b"x" * 8192, 128)): + with self.subTest(size=len(content), limit=limit): + processes = [] + + def launch(_command, **kwargs): + program = f"import os; os.write(1, {content!r})" + process = actual_popen([sys.executable, "-c", program], **kwargs) + processes.append(process) + return process + + with patch.object(self.module.subprocess, "Popen", side_effect=launch): + if len(content) <= limit: + result = self.server()._ssh("diagnostic", 5, max_output_bytes=limit) + self.assertEqual(result.stdout, content) + self.assertEqual(result.returncode, 0) + else: + with self.assertRaises(self.module.RedfishError) as raised: + self.server()._ssh("diagnostic", 5, max_output_bytes=limit) + self.assertEqual(raised.exception.status, 502) + self.assertIsNotNone(processes[0].poll()) + + def test_bounded_ssh_preserves_timeout_and_reaps_the_child(self): + actual_popen = subprocess.Popen + processes = [] + + def launch(_command, **kwargs): + process = actual_popen([sys.executable, "-c", "import time; time.sleep(30)"], **kwargs) + processes.append(process) + return process + + with patch.object(self.module.subprocess, "Popen", side_effect=launch): + with self.assertRaises(subprocess.TimeoutExpired): + self.server()._ssh("diagnostic", 0.1, stdin=b"x" * 131072, max_output_bytes=128) + self.assertIsNotNone(processes[0].poll()) + def test_cmsh_identity_is_checked_once(self): server = self.server() server._ssh = Mock(return_value=subprocess.CompletedProcess([], 0, b"", b"")) From b43e5be605f2875f55e7a2c7951942be8e691b4a Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Fri, 30 Oct 2026 15:55:58 -0700 Subject: [PATCH 07/13] Clarify the scope of BCM diagnostic tool searches Explain that diagnostic catalog searches do not enumerate registered agent capabilities, both in the tool description and each search response. Preserve diagnostic results and tool registration, and verify the scope guidance for empty and populated results. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- .../openclaw-seed/extensions/bcm/index.ts | 11 ++++++-- .../files/openclaw-seed/skills/bcm/SKILL.md | 2 ++ .../tests/bcm-tool-boundary.test.mjs | 26 +++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts b/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts index 0a22ab20..d10281b9 100644 --- a/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts +++ b/helm/mosaic-stack/files/openclaw-seed/extensions/bcm/index.ts @@ -725,7 +725,7 @@ export default definePluginEntry({ registerTool({ name: "bcm_search_tools", label: "BCM Search Tools", - description: "Search bcm-mcp-tools diagnostic tool IDs and descriptions before choosing a BCM command to run.", + description: "Search the diagnostic command catalog used by bcm_execute_tool. This does not search registered agent tools, including the separate bcm_redfish_* tools. Use the current tool definitions to determine agent capabilities; zero catalog matches do not mean a capability is unavailable.", parameters: { type: "object", additionalProperties: false, @@ -737,7 +737,7 @@ export default definePluginEntry({ }, async execute(toolCallId: string, rawParams: Record) { const query = stringParam(rawParams.query); - return callBcmTool( + const result = await callBcmTool( config, "search_tool", { query, @@ -746,6 +746,13 @@ export default definePluginEntry({ }, subagentOptions(config, toolCallId, "bcm_search_tools", "BCM tool search"), ); + return { + ...result, + content: [ + { type: "text", text: "Search scope: diagnostic commands for bcm_execute_tool only. Registered agent tools are outside this catalog. Check the current tool definitions before concluding that a capability is unavailable." }, + ...result.content, + ], + }; }, }); diff --git a/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md b/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md index 57dab14e..4db6a4d8 100644 --- a/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md +++ b/helm/mosaic-stack/files/openclaw-seed/skills/bcm/SKILL.md @@ -47,6 +47,8 @@ For broad cluster summaries, combine `bcm_get_info` with `bcm_execute_cmsh` comm ## Redfish (out-of-band) +Determine available capabilities from the tools registered in the current session. `bcm_search_tools` searches only the diagnostic command catalog for `bcm_execute_tool`; it does not enumerate agent tools. Empty diagnostic search results provide no evidence that another registered capability is absent. + When the `bcm_redfish_*` tools are registered, they read a node's BMC over Redfish through the Base Command Manager service. Prefer them over CMSH when the node is unreachable in-band or down, for power state, hardware health, temperature, fan, power supply, or system event log questions, and for firmware inventory. Pass only the Base Command Manager hostname; the service resolves the BMC address and credentials from Base Command Manager. Never ask the user for BMC addresses, usernames, or passwords, and never put them in a reply. Redfish access is read-only in every session mode. Resets, power actions, BMC configuration, accounts, sessions, certificates, event subscriptions, and virtual media are unavailable; if the user asks for one, say that Redfish actions are not available through this agent rather than retrying through another tool. A refusal from `bcm_redfish_get` means the path is outside the read-only allowlist. An `Actions` object in a returned resource is descriptive metadata, not an executable tool. When reporting it, distinguish the actions the BMC advertises from the read-only operations available through the registered Redfish tools. Do not offer to execute advertised actions or ask for confirmation to perform them. diff --git a/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs b/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs index 9c57b444..7d183882 100644 --- a/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs +++ b/helm/mosaic-stack/tests/bcm-tool-boundary.test.mjs @@ -128,6 +128,32 @@ test("never treats Redfish tools as mutations", async () => { } }); +test("diagnostic searches retain catalog results and explain their capability discovery scope", async () => { + const plugin = await loadBcmPlugin(); + const { tools } = registerBcm(plugin, { redfishEnabled: true, mcpUrl: "http://catalog-scope.test/mcp" }); + const originalFetch = globalThis.fetch; + let payload; + globalThis.fetch = async (url, init) => { + if (String(url).includes("/api/subagents/events")) return new Response("{}"); + const request = JSON.parse(init.body); + assert.equal(request.params.name, "search_tool"); + return Response.json({ jsonrpc: "2.0", id: request.id, result: payload }); + }; + try { + for (const [query, text] of [["inventory", "Matches: 0"], ["sensors", "Matches: 1\nexample_diagnostic"]]) { + payload = { content: [{ type: "text", text }] }; + const result = await tools.get("bcm_search_tools").execute("scope-check", { query }); + assert.deepEqual(result.details, payload); + assert.deepEqual(result.content.slice(1), payload.content); + assert.match(result.content[0].text, /diagnostic commands for bcm_execute_tool only/); + assert.match(result.content[0].text, /Registered agent tools are outside this catalog/); + } + for (const name of redfishToolNames) assert.ok(tools.has(name)); + } finally { + globalThis.fetch = originalFetch; + } +}); + test("surfaces Redfish policy refusals and validates hostnames before calling the backend", async () => { const plugin = await loadBcmPlugin(); const { tools } = registerBcm(plugin, { redfishEnabled: true, mcpUrl: "http://bcm.test/mcp", authToken: "token" }); From 4d5ef6df22e50f28c56a5cdf93c4ab0d0e21a2a8 Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:08:32 -0700 Subject: [PATCH 08/13] Expose read-only Redfish in the installation builder Add an opt-in BCM Redfish checkbox and emit its nested Helm flag only when BCM is enabled. Explain the read-only and TLS defaults, preserve dependency-driven BCM selection, and verify generated commands render successfully. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- docs/_static/install-builder.mjs | 6 ++++++ docs/installation_builder.md | 2 ++ .../files/agent-documentation.tar.gz | Bin 35210 -> 35264 bytes tests/docs/install-builder.test.mjs | 9 +++++++++ 4 files changed, 17 insertions(+) diff --git a/docs/_static/install-builder.mjs b/docs/_static/install-builder.mjs index 4c0753e7..5e142c62 100644 --- a/docs/_static/install-builder.mjs +++ b/docs/_static/install-builder.mjs @@ -47,6 +47,7 @@ export function buildCommand(state) { set('llm.external.existingSecret', value('llmSecret'), true); } for (const name of ['ui', 'execution', 'observability', ...Object.keys(modules).filter(name => !observabilityServices.includes(name))]) set(`modules.${name}.enabled`, ['ui', 'execution'].includes(name) || enabled.has(name)); + set('modules.bcm.redfish.enabled', enabled.has('bcm') && !!state.redfish); for (const service of ['prometheus', 'alertmanager']) { set(`observability.${service}Url`, enabled.has(service) ? value(`${service}Url`) : '', true); } @@ -156,6 +157,10 @@ if (root) { const input = document.createElement('input'); input.name = key; input.value = state[key] ?? initial; input.placeholder = placeholder || ''; input.addEventListener('input', () => {state[key] = input.value; update(false);}); wrapper.append(input); settingsBody.append(wrapper); } + if (enabled.has('bcm')) { + const wrapper = document.createElement('label'); const input = document.createElement('input'); input.type = 'checkbox'; input.name = 'redfish'; input.checked = !!state.redfish; + input.addEventListener('change', () => {state.redfish = input.checked; update(false);}); wrapper.append(input, document.createTextNode('Read-only Redfish through BCM')); settingsBody.append(wrapper); + } const wrapper = document.createElement('label'); const input = document.createElement('input'); input.type = 'checkbox'; input.checked = !!state.sandboxInstalled; input.addEventListener('change', () => {state.sandboxInstalled = input.checked; update(false);}); wrapper.append(input, document.createTextNode('Cluster already has a compatible agent-sandbox installation')); settingsBody.append(wrapper); } @@ -167,6 +172,7 @@ if (root) { } if (enabled.has('grafana')) notes.push(`Create ${state.grafanaSecret || fields.grafanaSecret[1]} with keys username and password.`); if (enabled.has('bcm')) notes.push(`Create ${state.bcmSecret || fields.bcmSecret[1]} with key id_ecdsa; its SSH identity must bootstrap the read-only CMSH user.`); + if (enabled.has('bcm') && state.redfish) notes.push('Redfish reads node BMCs through the BCM head using credentials stored in BCM. Resets and configuration changes are unavailable. BMC TLS certificate verification is off by default; see the Redfish installation guide to configure it.'); if (enabled.has('research')) notes.push('Create iraop-secrets with NVIDIA_API_KEY, NVIDIA_CHAT_API_KEY and IRAOP_API_KEY; prepare the corpus directory.'); if (enabled.has('webSearch')) notes.push('Web search uses DuckDuckGo without an API key; the OpenClaw pod needs HTTPS egress to duckduckgo.com. Clear it for air-gapped installations.'); if (state.inference !== 'external') notes.push('Verify GPU, memory and model cache requirements in the on-prem inference section.'); diff --git a/docs/installation_builder.md b/docs/installation_builder.md index f19b150f..f27be8ea 100644 --- a/docs/installation_builder.md +++ b/docs/installation_builder.md @@ -4,6 +4,8 @@ Select your inference path and modules to generate an installation command. Comp CPU, RAM, GPUs and disk update automatically with your selections. Values come from this documentation version’s rendered Helm manifests. Different chart versions or site overrides can change the requirements. +Select Base Command Manager to expose the optional **Read-only Redfish through BCM** setting. See the [Redfish installation guide](bcm.md#8-optional-read-only-redfish) for BMC credential resolution and TLS verification settings. + ```{raw} html ``` diff --git a/helm/mosaic-stack/files/agent-documentation.tar.gz b/helm/mosaic-stack/files/agent-documentation.tar.gz index 783ac2cf41d0da2fa9219638dff8c922950362ee..d52fe4a48fb554e9ec14ec66ca5edcfd9ba691da 100644 GIT binary patch delta 15148 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 a@bmEV@bmEV@be7o`1v1Zxy&;F-~j-wg_~Uf delta 15121 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 diff --git a/tests/docs/install-builder.test.mjs b/tests/docs/install-builder.test.mjs index 35730bbe..3ba30798 100644 --- a/tests/docs/install-builder.test.mjs +++ b/tests/docs/install-builder.test.mjs @@ -23,6 +23,7 @@ const example = {inference:'external', baseUrl:'https://inference.example.com/v1 corpus:'/data/corpus', evidenceRoot:'/data/jobs', evidenceNode:'login-node'}; for (const state of [ {modules:[]}, {modules:['terminal']}, {modules:['slurm']}, {modules:['slurm'], slurmBackend:'vanilla'}, + {modules:['bcm'],redfish:true}, {modules:['kubernetes','prometheus','alertmanager','loki','grafana','bcm','slurm','diagnostics','research','terminal','edit','clusters']}, {inference:'super',modules:['terminal']}, {inference:'ultra',modules:['grafana']}, ]) test(`generated selection renders in Helm: ${JSON.stringify(state)}`, () => { @@ -41,6 +42,14 @@ test('dependencies are derived without changing requested modules', () => { assert.deepEqual([...enabledModules(state)].sort(),['bcm','diagnostics','kubernetes','terminal']); assert.deepEqual(state.modules,['diagnostics','terminal']); }); +test('Redfish is opt-in and requires BCM, including when BCM is selected by a dependency', () => { + for (const [selected, redfish, expected] of [ + [['bcm'],true,true], [['diagnostics'],true,true], [['bcm'],false,false], [[],true,false], + ]) { + const args = argumentsFor({...example, modules:selected, redfish}); + assert.ok(args.includes(`modules.bcm.redfish.enabled=${expected}`)); + } +}); test('shell metacharacters remain literal arguments and Helm list separators are escaped', () => { for(const model of ["quoted' name,revision", 'model $(printf unsafe); $HOME']) { const args=argumentsFor({...example,modules:[],model}); From 0bb85dd6f67eee7deae54e41b78f717520db85e1 Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:08:55 -0700 Subject: [PATCH 09/13] Document installation guide and builder synchronization Require new installation headings and options to be reflected in the builder, and place a reminder beside the guide title. Document the builder validation commands and refresh the bundled agent documentation. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- CONTRIBUTING.md | 2 ++ docs/installation.md | 2 ++ .../files/agent-documentation.tar.gz | Bin 35264 -> 35333 bytes 3 files changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 73009d05..a777fac5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,6 +27,8 @@ Open an issue before substantial implementation work so maintainers can confirm 4. Open a pull request using the repository template. 5. Address review feedback and ensure required status checks pass. +When adding a heading or installation option to `docs/installation.md`, update `docs/installation_builder.md` and `docs/_static/install-builder.mjs` in the same change. Keep the builder's options, generated Helm flags, prerequisites, and guide links aligned with the installation guide. For sections that do not map to a selectable option, include the relevant guidance or link in the builder page. Validate with `node --test tests/docs/*.test.mjs` and `uv run --project docs --locked sphinx-build -W --keep-going -b html -c docs . docs/_build/html`, then inspect the rendered builder. + ## Developer Certificate Of Origin External contributions require agreement to the [Developer Certificate of Origin 1.1](DCO.md). Every commit must include a `Signed-off-by` line. Add it automatically with the `-s` option: diff --git a/docs/installation.md b/docs/installation.md index ef6348bf..68c8abb3 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,5 +1,7 @@ # AI Factory Operations Agent Helm Deployment + + AI Factory Operations Agent is installed with Helm. This guide documents the shared upgrade, LLM, module, UI, and headless workflows. ## Install AI Factory Operations Agent diff --git a/helm/mosaic-stack/files/agent-documentation.tar.gz b/helm/mosaic-stack/files/agent-documentation.tar.gz index d52fe4a48fb554e9ec14ec66ca5edcfd9ba691da..dbdc7c2a4d59af08dee1929bd1fb20ab333dcf87 100644 GIT binary patch delta 30694 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 Date: Fri, 30 Oct 2026 16:09:52 -0700 Subject: [PATCH 10/13] Keep builder maintenance guidance in contributing documentation Remove the maintainer comment from the installation guide as requested, retaining the synchronization guidance in CONTRIBUTING.md. Refresh the bundled documentation. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- docs/installation.md | 2 -- .../files/agent-documentation.tar.gz | Bin 35333 -> 35264 bytes 2 files changed, 2 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 68c8abb3..ef6348bf 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,7 +1,5 @@ # AI Factory Operations Agent Helm Deployment - - AI Factory Operations Agent is installed with Helm. This guide documents the shared upgrade, LLM, module, UI, and headless workflows. ## Install AI Factory Operations Agent diff --git a/helm/mosaic-stack/files/agent-documentation.tar.gz b/helm/mosaic-stack/files/agent-documentation.tar.gz index dbdc7c2a4d59af08dee1929bd1fb20ab333dcf87..d52fe4a48fb554e9ec14ec66ca5edcfd9ba691da 100644 GIT binary patch delta 30651 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 Date: Fri, 30 Oct 2026 16:12:11 -0700 Subject: [PATCH 11/13] Nest Redfish inside the BCM module block Move the Redfish checkbox from connection settings into the BCM module block and indent it below BCM. Preserve opt-in behavior and generated Helm settings; update builder guidance and bundled documentation. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- docs/_static/docs.css | 4 +++- docs/_static/install-builder.mjs | 13 ++++++++----- docs/installation_builder.md | 2 +- .../files/agent-documentation.tar.gz | Bin 35264 -> 35351 bytes 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/docs/_static/docs.css b/docs/_static/docs.css index 07c43af0..48c5feb4 100644 --- a/docs/_static/docs.css +++ b/docs/_static/docs.css @@ -21,7 +21,9 @@ pre, .admonition, .search-button { border-radius: 0; } #install-command-builder .builder-settings { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .8rem; } #install-command-builder .builder-settings > label { flex-direction: column; align-items: stretch; text-align: left; } #install-command-builder input:not([type=checkbox]), #install-command-builder select { width: 100%; padding: .45rem; border: 1px solid var(--pst-color-border); border-radius: 0; background: var(--pst-color-background); color: var(--pst-color-text-base); } -.builder-modules { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem; } +.builder-modules { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem; align-items: start; } +.builder-module { background: var(--pst-color-surface); } +.builder-suboptions { padding-left: 1.5rem; } .builder-modules label { padding: .5rem; background: var(--pst-color-surface); cursor: pointer; } .builder-modules input { accent-color: var(--pst-color-primary); } .builder-prerequisites { font-size: .9rem; } diff --git a/docs/_static/install-builder.mjs b/docs/_static/install-builder.mjs index 5e142c62..8540a745 100644 --- a/docs/_static/install-builder.mjs +++ b/docs/_static/install-builder.mjs @@ -112,10 +112,16 @@ if (root) { const moduleGroup = document.createElement('fieldset'); moduleGroup.innerHTML = 'Modules

UI and execution are always enabled. Required dependencies are selected automatically.

'; const buttons = document.createElement('div'); buttons.className = 'builder-modules'; const inputs = new Map(); + const redfishOptions = document.createElement('div'); redfishOptions.className = 'builder-suboptions'; + const redfishLabel = document.createElement('label'); const redfishInput = document.createElement('input'); redfishInput.type = 'checkbox'; redfishInput.name = 'redfish'; + redfishInput.addEventListener('change', () => {state.redfish = redfishInput.checked; update(false);}); redfishLabel.append(redfishInput, document.createTextNode('Read-only Redfish')); redfishOptions.append(redfishLabel); for (const [name, label] of Object.entries(modules)) { const wrapper = document.createElement('label'); const input = document.createElement('input'); input.type = 'checkbox'; input.name = name; input.addEventListener('change', () => {const requested = new Set(state.modules); input.checked ? requested.add(name) : requested.delete(name); state.modules = [...requested]; update(true);}); - wrapper.append(input, document.createTextNode(label)); buttons.append(wrapper); inputs.set(name, input); + wrapper.append(input, document.createTextNode(label)); inputs.set(name, input); + if (name === 'bcm') { + const block = document.createElement('div'); block.className = 'builder-module'; block.append(wrapper, redfishOptions); buttons.append(block); + } else buttons.append(wrapper); } moduleGroup.append(buttons); form.append(moduleGroup); const settings = document.createElement('fieldset'); settings.innerHTML = 'Connection settings'; @@ -135,6 +141,7 @@ if (root) { }).then(data => {catalog = data; update(false);}).catch(error => {sizing.textContent = `Deployment footprint unavailable: ${error.message}`;}); function update(renderSettings) { const enabled = enabledModules(state); + redfishOptions.hidden = !enabled.has('bcm'); redfishInput.checked = !!state.redfish; for (const [name, input] of inputs) {input.checked = enabled.has(name); input.disabled = enabled.has(name) && !state.modules.includes(name);} if (renderSettings) { settingsBody.replaceChildren(); @@ -157,10 +164,6 @@ if (root) { const input = document.createElement('input'); input.name = key; input.value = state[key] ?? initial; input.placeholder = placeholder || ''; input.addEventListener('input', () => {state[key] = input.value; update(false);}); wrapper.append(input); settingsBody.append(wrapper); } - if (enabled.has('bcm')) { - const wrapper = document.createElement('label'); const input = document.createElement('input'); input.type = 'checkbox'; input.name = 'redfish'; input.checked = !!state.redfish; - input.addEventListener('change', () => {state.redfish = input.checked; update(false);}); wrapper.append(input, document.createTextNode('Read-only Redfish through BCM')); settingsBody.append(wrapper); - } const wrapper = document.createElement('label'); const input = document.createElement('input'); input.type = 'checkbox'; input.checked = !!state.sandboxInstalled; input.addEventListener('change', () => {state.sandboxInstalled = input.checked; update(false);}); wrapper.append(input, document.createTextNode('Cluster already has a compatible agent-sandbox installation')); settingsBody.append(wrapper); } diff --git a/docs/installation_builder.md b/docs/installation_builder.md index f27be8ea..e5a8ec4c 100644 --- a/docs/installation_builder.md +++ b/docs/installation_builder.md @@ -4,7 +4,7 @@ Select your inference path and modules to generate an installation command. Comp CPU, RAM, GPUs and disk update automatically with your selections. Values come from this documentation version’s rendered Helm manifests. Different chart versions or site overrides can change the requirements. -Select Base Command Manager to expose the optional **Read-only Redfish through BCM** setting. See the [Redfish installation guide](bcm.md#8-optional-read-only-redfish) for BMC credential resolution and TLS verification settings. +Select Base Command Manager to expose the optional **Read-only Redfish** checkbox inside its module block. See the [Redfish installation guide](bcm.md#8-optional-read-only-redfish) for BMC credential resolution and TLS verification settings. ```{raw} html
diff --git a/helm/mosaic-stack/files/agent-documentation.tar.gz b/helm/mosaic-stack/files/agent-documentation.tar.gz index d52fe4a48fb554e9ec14ec66ca5edcfd9ba691da..99dfac76a2040ebb9d541a0ed174ca7e48f18e96 100644 GIT binary patch delta 16739 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 z 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 I1OVUx0FsoHnE(I) From 1f144734e11034dc14b503947ac2d4d317653db2 Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:14:09 -0700 Subject: [PATCH 12/13] Pack module choices around expanded BCM options Let the expanded BCM block occupy two grid rows so adjacent modules fill the available space. Preserve a single-column flow on narrow screens. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- docs/_static/docs.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/_static/docs.css b/docs/_static/docs.css index 48c5feb4..994c35c7 100644 --- a/docs/_static/docs.css +++ b/docs/_static/docs.css @@ -23,6 +23,7 @@ pre, .admonition, .search-button { border-radius: 0; } #install-command-builder input:not([type=checkbox]), #install-command-builder select { width: 100%; padding: .45rem; border: 1px solid var(--pst-color-border); border-radius: 0; background: var(--pst-color-background); color: var(--pst-color-text-base); } .builder-modules { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem; align-items: start; } .builder-module { background: var(--pst-color-surface); } +.builder-module:has(.builder-suboptions:not([hidden])) { grid-row: span 2; } .builder-suboptions { padding-left: 1.5rem; } .builder-modules label { padding: .5rem; background: var(--pst-color-surface); cursor: pointer; } .builder-modules input { accent-color: var(--pst-color-primary); } @@ -30,7 +31,7 @@ pre, .admonition, .search-button { border-radius: 0; } #install-command-builder button { padding: .4rem .8rem; border: 1px solid var(--pst-color-border); border-radius: 0; background: var(--pst-color-surface); color: var(--pst-color-text-base); } #install-command-builder [role=status] { margin-left: .6rem; } #install-command-builder pre { margin-top: .6rem; padding: 1rem; white-space: pre; overflow: auto; } -@media (max-width: 600px) { #install-command-builder .builder-settings, .builder-modules { grid-template-columns: 1fr; } } +@media (max-width: 600px) { #install-command-builder .builder-settings, .builder-modules { grid-template-columns: 1fr; } .builder-module:has(.builder-suboptions:not([hidden])) { grid-row: auto; } } #install-command-builder .builder-settings > label:has(input[type=checkbox]) { flex-direction: row; align-items: center; grid-column: 1 / -1; } .builder-sizing { margin: 2rem 0; } From 72bed516d86a6d2c158996d93b8bf7ff643bc1ac Mon Sep 17 00:00:00 2001 From: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:18:30 -0700 Subject: [PATCH 13/13] Document Redfish alongside the installation extensions Move the complete Redfish setup from the BCM-specific guide to the main installation guide after BCM. Point the BCM guide and installation builder at the canonical extension section and refresh bundled agent documentation. Signed-off-by: Rohan Adwankar <39285979+RohanAdwankar@users.noreply.github.com> --- docs/bcm.md | 59 +----------------- docs/installation.md | 59 +++++++++++++++++- docs/installation_builder.md | 2 +- .../files/agent-documentation.tar.gz | Bin 35351 -> 35326 bytes 4 files changed, 60 insertions(+), 60 deletions(-) diff --git a/docs/bcm.md b/docs/bcm.md index 33a24f4d..de341761 100644 --- a/docs/bcm.md +++ b/docs/bcm.md @@ -285,61 +285,4 @@ kubectl -n mosaic get secret mosaic-ui-auth \ Open `http://127.0.0.1:3210` on the workstation. Both forwarding processes must remain running. -## 8. Optional: Read-Only Redfish - -Redfish lets the agent read a node's BMC when the node is down or unreachable in-band: power state, -hardware health, temperatures, fans, power supplies, BMC event logs, and firmware inventory. The -agent passes only a Base Command Manager hostname. The Base Command Manager adapter looks up the -BMC address and credentials through CMSH, the same lookup the Hardware Agent uses, and never returns -them to the model. - -Prerequisites: - -- The Base Command Manager adapter runs in `ssh-adapter` mode (section 5). -- The adapter's SSH identity can read `bmcsettings` and BMC interfaces through CMSH on the head node. -- The head node can reach the BMC network over HTTPS and has `curl`. Check one BMC from the head node: - - ```bash - curl -sk https:///redfish/v1 | head -c 300; echo - ``` - -Enable it: - -```bash -helm upgrade mosaic "$MOSAIC_CHART" \ - --devel \ - -n mosaic \ - --reuse-values \ - --set modules.bcm.redfish.enabled=true \ - --wait \ - --timeout 12m -``` - -By default each request runs `curl` on the head node over the adapter's existing SSH session -(`modules.bcm.redfish.viaHeadNode=true`), because the head node is routed to the BMC network. The -BMC credential reaches `curl` on standard input, so it does not appear in process listings. Set -`viaHeadNode=false` only when the adapter pod itself can reach the BMCs. BMCs usually present -self-signed certificates, so `modules.bcm.redfish.verifyTls` defaults to `false`. -`modules.bcm.redfish.timeoutSeconds` (default `60`) bounds each request; some DGX BMCs take about -30 seconds to return the expanded firmware inventory. - -The adapter enforces the following allowlist before it looks up any credential. Only `GET` is -used, and the only query parameters accepted are `$top`, `$skip`, and `$expand=.` limited to one -level, which is refused on the service root: - -| Resource | Paths under `/redfish/v1` | -| --- | --- | -| Service root and collections | `/`, `Systems`, `Chassis`, `Managers` | -| Systems | `Systems/{id}` and its `Processors`, `Memory`, `Storage`, `EthernetInterfaces`, and `LogServices/{id}/Entries` | -| Chassis | `Chassis/{id}` and its `Thermal`, `ThermalSubsystem`, `Power`, `PowerSubsystem`, and `Sensors` | -| Managers | `Managers/{id}` and its `EthernetInterfaces` and `LogServices/{id}/Entries` | -| Firmware and tasks | `UpdateService/FirmwareInventory`, `TaskService/Tasks` | - -Everything else is refused, including any path containing `Actions`, and `AccountService`, -`SessionService`, `CertificateService`, `EventService`, `SecureBoot`, `Bios/Settings`, and -`VirtualMedia`. Paths with `..`, `//`, `%`, or other query parameters are also refused. The adapter -also checks every resource embedded in a response, such as `$expand` results and continuation pages, -against the same allowlist. It reduces any embedded resource outside it to a bare link, so a BMC that -expands more than requested cannot return denied content. Fields named like passwords, tokens, or -secrets are redacted from responses. Resets and other BMC actions are not -available in any session mode. +For optional BMC inventory and monitoring, follow the [Read-only Redfish installation](installation.md#read-only-redfish). diff --git a/docs/installation.md b/docs/installation.md index ef6348bf..459f0600 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -531,7 +531,64 @@ helm upgrade mosaic "$MOSAIC_CHART" \ The SSH identity must be allowed to create or update the dedicated read-only CMSH user during startup. -To let the agent read node BMCs over read-only Redfish, see [Read-only Redfish](bcm.md#8-optional-read-only-redfish). +### Read-only Redfish + +Redfish lets the agent read a node's BMC when the node is down or unreachable in-band: power state, +hardware health, temperatures, fans, power supplies, BMC event logs, and firmware inventory. The +agent passes only a Base Command Manager hostname. The Base Command Manager adapter looks up the +BMC address and credentials through CMSH, the same lookup the Hardware Agent uses, and never returns +them to the model. + +Prerequisites: + +- The [Base Command Manager extension](#base-command-manager) is configured in `ssh-adapter` mode. +- The adapter's SSH identity can read `bmcsettings` and BMC interfaces through CMSH on the head node. +- The head node can reach the BMC network over HTTPS and has `curl`. Check one BMC from the head node: + + ```bash + curl -sk https:///redfish/v1 | head -c 300; echo + ``` + +Enable it: + +```bash +helm upgrade mosaic "$MOSAIC_CHART" \ + --devel \ + -n mosaic \ + --reuse-values \ + --set modules.bcm.redfish.enabled=true \ + --wait \ + --timeout 12m +``` + +By default each request runs `curl` on the head node over the adapter's existing SSH session +(`modules.bcm.redfish.viaHeadNode=true`), because the head node is routed to the BMC network. The +BMC credential reaches `curl` on standard input, so it does not appear in process listings. Set +`viaHeadNode=false` only when the adapter pod itself can reach the BMCs. BMCs usually present +self-signed certificates, so `modules.bcm.redfish.verifyTls` defaults to `false`. +`modules.bcm.redfish.timeoutSeconds` (default `60`) bounds each request; some DGX BMCs take about +30 seconds to return the expanded firmware inventory. + +The adapter enforces the following allowlist before it looks up any credential. Only `GET` is +used, and the only query parameters accepted are `$top`, `$skip`, and `$expand=.` limited to one +level, which is refused on the service root: + +| Resource | Paths under `/redfish/v1` | +| --- | --- | +| Service root and collections | `/`, `Systems`, `Chassis`, `Managers` | +| Systems | `Systems/{id}` and its `Processors`, `Memory`, `Storage`, `EthernetInterfaces`, and `LogServices/{id}/Entries` | +| Chassis | `Chassis/{id}` and its `Thermal`, `ThermalSubsystem`, `Power`, `PowerSubsystem`, and `Sensors` | +| Managers | `Managers/{id}` and its `EthernetInterfaces` and `LogServices/{id}/Entries` | +| Firmware and tasks | `UpdateService/FirmwareInventory`, `TaskService/Tasks` | + +Everything else is refused, including any path containing `Actions`, and `AccountService`, +`SessionService`, `CertificateService`, `EventService`, `SecureBoot`, `Bios/Settings`, and +`VirtualMedia`. Paths with `..`, `//`, `%`, or other query parameters are also refused. The adapter +also checks every resource embedded in a response, such as `$expand` results and continuation pages, +against the same allowlist. It reduces any embedded resource outside it to a bare link, so a BMC that +expands more than requested cannot return denied content. Fields named like passwords, tokens, or +secrets are redacted from responses. Resets and other BMC actions are not +available in any session mode. ### Research diff --git a/docs/installation_builder.md b/docs/installation_builder.md index e5a8ec4c..602765df 100644 --- a/docs/installation_builder.md +++ b/docs/installation_builder.md @@ -4,7 +4,7 @@ Select your inference path and modules to generate an installation command. Comp CPU, RAM, GPUs and disk update automatically with your selections. Values come from this documentation version’s rendered Helm manifests. Different chart versions or site overrides can change the requirements. -Select Base Command Manager to expose the optional **Read-only Redfish** checkbox inside its module block. See the [Redfish installation guide](bcm.md#8-optional-read-only-redfish) for BMC credential resolution and TLS verification settings. +Select Base Command Manager to expose the optional **Read-only Redfish** checkbox inside its module block. See the [Redfish installation guide](installation.md#read-only-redfish) for BMC credential resolution and TLS verification settings. ```{raw} html diff --git a/helm/mosaic-stack/files/agent-documentation.tar.gz b/helm/mosaic-stack/files/agent-documentation.tar.gz index 99dfac76a2040ebb9d541a0ed174ca7e48f18e96..4abee1d0111510a18909e210cb885c9d9ded728a 100644 GIT binary patch delta 34373 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 VpSz#CpI^_<{{R#Fy($3U0RRC!VgUdE delta 34313 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 N{{ecejCTOw0RRVhnMMEr