Skip to content

bug(slm): Edit Node silently discards all SSH/PKI/enrollment fields — NodeUpdate accepts 5 of 14; ssh_key dropped on register and connection-test too #13145

Description

@mrveiss

Found while deriving SLM frontend types from the generated OpenAPI contract (#13138). The name-collision scan flagged NodeUpdate, NodeCreate and ConnectionTestRequest as declaring fields that do not exist in the contract; all three were confirmed against backend source.

Pydantic's default is extra="ignore", and none of these three models sets model_config to change it, so the surplus fields are dropped without an error. The request returns 200, and the UI reports success.

1. Edit Node silently discards every SSH/enrollment field (highest impact)

PATCH /api/nodes/{node_id} binds NodeUpdate (autobot-slm-backend/api/nodes.py:571-574), which declares exactly five fields (autobot-slm-backend/models/schemas.py:172-179):

hostname, ansible_name, ip_address, status, roles

The handler then does node_data.model_dump(exclude_unset=True) (autobot-slm-backend/api/nodes.py:588), so only those five can ever reach the DB.

The Edit-Node modal sends nine more (autobot-slm-frontend/src/components/AddNodeModal.vue:1123-1141):

ssh_user, ssh_port, auth_method, ssh_password, ssh_key,
auto_enroll, deploy_pki, import_existing, run_enrollment

All nine are discarded. What the user sees:

  • autobot-slm-frontend/src/components/AddNodeModal.vue:476-488 — "Deploy PKI certificates after saving" checkbox: no-op.
  • autobot-slm-frontend/src/components/AddNodeModal.vue:490-502 — "Re-run enrollment tasks" checkbox: no-op.
  • autobot-slm-frontend/src/components/AddNodeModal.vue:861 — validation forces the user to supply an SSH password whenever either checkbox is ticked (sshOpsRequested), i.e. a credential is demanded to enable an action that never happens.
  • autobot-slm-frontend/src/components/AddNodeModal.vue:203-227 and :272 — changing SSH user / port / auth method / password on an existing node: no-op, reported as addNodeModal.nodeUpdatedSuccessfully (autobot-slm-frontend/src/components/AddNodeModal.vue:1142).

2. Register Node silently discards ssh_key and deploy_pki

NodeCreate (autobot-slm-backend/models/schemas.py:156-169) has no ssh_key and no deploy_pki. ssh_key does not exist anywhere in autobot-slm-backend/api/nodes.py or autobot-slm-backend/models/schemas.py; the only key the backend uses is the fleet-wide one at autobot-slm-backend/api/nodes.py:2761 (_DEFAULT_SSH_KEY = config.path.ssh_key_path).

So a key pasted into the Add-Node form (autobot-slm-frontend/src/components/AddNodeModal.vue:1130, getSshKey()) is never used — enrollment silently falls back to the canonical inter-node key, which is a different trust decision from the one the operator made in the UI.

3. Connection test silently discards ssh_key

ConnectionTestRequest (autobot-slm-backend/models/schemas.py:471-478) accepts password but has no ssh_key, while the frontend type declares one (autobot-slm-frontend/src/types/slm.ts:270-277). A key-auth connection test therefore never tests the supplied key.

Which side is wrong

Deliberately not decided here, because it is a product question and #13138 is a frontend type-derivation task that must not change server contracts:

  • Server is wrong -> add the fields to NodeUpdate / NodeCreate / ConnectionTestRequest and implement the SSH/PKI/enrollment side effects. Note ssh_password and ssh_key on an update path need the same handling as the register path (never persisted in plain text, never echoed back — NodeResponse at autobot-slm-backend/models/schemas.py:182 correctly omits both today).
  • Frontend is wrong -> remove the controls, and drop the validation rule that demands a password for them.

Either way the current state is worse than both: the UI collects an SSH password to perform an operation that cannot happen.

A third, cheap mitigation that is independent of the decision: set model_config = {"extra": "forbid"} on request models so an unknown field 422s instead of vanishing. Same root cause as #13051.

Until the decision is made, NodeCreate, NodeUpdate and ConnectionTestRequest cannot be derived from components['schemas'][...] in #13138 — deriving them turns the surplus fields into compile errors whose only silent fix is deleting UI controls. They are explicitly deferred there and blocked on this issue.

Verification path (no code execution required)

  1. autobot-slm-backend/models/schemas.py:172-179 — NodeUpdate field list.
  2. autobot-slm-backend/api/nodes.py:588 — model_dump(exclude_unset=True).
  3. autobot-slm-frontend/src/components/AddNodeModal.vue:1123-1141 — the payload actually sent.

Related: #13051 (same silent-drop class, secrets API), #13138 (the derivation work that surfaced this), #13139 (endpoints with no response_model).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions