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żka | Scope | Opis |
|---|---|---|---|
| GET | /api/v1/ssh-keys | infra:read | Lista kluczy użytkownika, paginowana (najnowsze pierwsze). |
| POST | /api/v1/ssh-keys | infra:write | Dodanie klucza publicznego OpenSSH. Zwraca 201. |
| PUT/PATCH | /api/v1/ssh-keys/{sshKey} | infra:write | Zmiana nazwy wyświetlanej klucza (owner-only). |
| DELETE | /api/v1/ssh-keys/{sshKey} | infra:delete | Usunię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 -lf — SHA256:... 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łaValidPublicSshKey) — materiał klucza publicznego w formacie OpenSSH. Reguła przepuszcza klucz przezssh-keygen -l, więc niepoprawny materiał zwraca422.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ędzie | Scope | Tryb | Opis |
|---|---|---|---|
| ssh-keys-list | infra:read | read-only | Lista kluczy; page, per_page (max 50). Zwraca id/name/for_root/public_key/fingerprint/daty. |
| ssh-key-create | infra:write | zapis | Dodanie klucza publicznego OpenSSH; name (min 3), content, for_root. Walidacja przez ssh-keygen. Nigdy nie przekazuj klucza prywatnego. |
| ssh-key-delete | infra:delete | destrukcyjne | Usunię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 }
}
}