Nodea — logo

Klucze SSH — API v1 i MCP | Dokumentacja Nodea

Moduł Klucze SSH zarządza publicznymi kluczami SSH użytkownika — tymi, które są wdrażane na serwery podczas provisioningu. Obejmuje listowanie, dodanie klucza, zmianę jego nazwy oraz usunięcie. Dokument opisuje warstwę REST API v1 (/api/v1/ssh-keys) oraz narzędzia MCP z tego modułu.

Uwierzytelnianie i zakresy (scopes)

API v1 uwierzytelnia się tokenem osobistym Passport przez nagłówek Authorization: Bearer <token>. Poziomy dostępu:

  • infra:read — listowanie kluczy.
  • infra:write — dodanie klucza oraz zmiana jego nazwy.
  • infra:delete — usunięcie klucza.

Cały moduł jest dodatkowo bramkowany flagą Pennant features:servers — wyłączenie modułu serwerów ukrywa klucze SSH zarówno w web UI, jak i w API/MCP. Limit zapytań: throttle:api-v1 = 240/min na użytkownika tokenu.

Własność i bezpieczeństwo

Dostęp na poziomie wiersza wymusza UserSshKeyPolicy (owner-only dla update/delete). Listowanie jest zawężone do właściciela z definicji. Cudzy identyfikator przy edycji/usunięciu zwraca 403. Nie istnieje model współdzielenia kluczy SSH.

Ważne: kolumna content przechowuje wyłącznie klucz publiczny (zaszyfrowany at rest), dlatego zwracanie go jest bezpieczne — klucze prywatne nigdy nie trafiają do tej tabeli. Nigdy nie wysyłaj klucza prywatnego. Materiał klucza jest niemutowalny: edycja pozwala zmienić tylko nazwę wyświetlaną (wymiana klucza = usuń + dodaj).

API v1 — endpointy

MetodaŚcieżkaScopeOpis
GET/api/v1/ssh-keysinfra:readLista kluczy użytkownika, paginowana (najnowsze pierwsze).
POST/api/v1/ssh-keysinfra:writeDodanie klucza publicznego OpenSSH. Zwraca 201.
PUT/PATCH/api/v1/ssh-keys/{sshKey}infra:writeZmiana nazwy wyświetlanej klucza (owner-only).
DELETE/api/v1/ssh-keys/{sshKey}infra:deleteUsunięcie klucza (owner-only). Zwraca 204.

GET /ssh-keys — parametry i odpowiedź

  • per_page (int 1–100, domyślnie 20), page (int ≥1).

Odpowiedź: kolekcja UserSshKeyResource — pola: id, name, for_root (bool), public_key (zawartość klucza), fingerprint (SHA256 w stylu ssh-keygen -lfSHA256:... bez paddingu; null, gdy treść nie jest parsowalna jako <typ> <base64> [komentarz]), created_at, updated_at.

POST — parametry ciała

  • name (string, wymagany, min 3, max 255) — nazwa wyświetlana.
  • content (string, wymagany, min 3, max 10000, reguła ValidPublicSshKey) — materiał klucza publicznego w formacie OpenSSH. Reguła przepuszcza klucz przez ssh-keygen -l, więc niepoprawny materiał zwraca 422.
  • for_root (bool, opcjonalny) — czy klucz ma być instalowany dla użytkownika root podczas provisioningu.

PATCH — parametry ciała

  • name (string, wymagany, min 3, max 255) — jedyne mutowalne pole.

Kody błędów

  • 401 — brak/niepoprawny token.
  • 403 — brak wymaganego scope lub cudzy klucz (polityka owner-only).
  • 404 — nieznany identyfikator.
  • 422 — walidacja (niepoprawny klucz publiczny, zbyt krótka/długa nazwa).

Przykłady — API

Lista kluczy

curl -s https://app.nodea.io/api/v1/ssh-keys \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Accept: application/json"

Dodanie klucza publicznego (dla root)

curl -s -X POST https://app.nodea.io/api/v1/ssh-keys \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "laptop-ed25519",
    "content": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@host",
    "for_root": true
  }'

Zmiana nazwy klucza

curl -s -X PATCH https://app.nodea.io/api/v1/ssh-keys/17 \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "laptop-sluzbowy" }'

MCP — narzędzia

Narzędzia MCP dzielą model uwierzytelniania i zakresów z API v1 (Bearer + scope sprawdzany w ensureScope) oraz flagę features:servers (narzędzie na nieaktywnej fladze znika z tools/list). Klucze adresowane są po całkowitym id; brakujący i cudzy identyfikator zwracają ten sam błąd (brak enumeracji między najemcami). Wynik korzysta z tego samego kształtu co API (UserSshKeyResource).

NarzędzieScopeTrybOpis
ssh-keys-listinfra:readread-onlyLista kluczy; page, per_page (max 50). Zwraca id/name/for_root/public_key/fingerprint/daty.
ssh-key-createinfra:writezapisDodanie klucza publicznego OpenSSH; name (min 3), content, for_root. Walidacja przez ssh-keygen. Nigdy nie przekazuj klucza prywatnego.
ssh-key-deleteinfra:deletedestrukcyjneUsunięcie klucza po id; wymaga confirm: true. Klucze już wdrożone na serwery nie są z nich usuwane.

Przykład — MCP (JSON-RPC)

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "ssh-key-create",
    "arguments": {
      "name": "laptop-ed25519",
      "content": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@host",
      "for_root": true
    }
  }
}
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "ssh-key-delete",
    "arguments": { "id": 17, "confirm": true }
  }
}