Bezpieczeństwo i uwierzytelnianie
Szybki start
Bezpieczeństwo i uwierzytelnianie
PgArachne opiera się całkowicie na systemie uprawnień PostgreSQL. Nie tworzy własnych list kontroli dostępu (ACL).
PgArachne wspiera cztery metody uwierzytelniania. Metody 1–3 wykorzystują
SET LOCAL ROLE do przełączania tożsamości; metoda 4 (bezpośrednie dane logowania) łączy się
bezpośrednio jako dany użytkownik, więc przełączanie roli nie jest potrzebne.
Dotyczy to endpointów JSON-RPC i MCP. Endpoint SSE jest jedynym
wyjątkiem — uwierzytelnia wywołującego, ale nie przełącza roli ani nie sprawdza uprawnień na poziomie
kanału, ponieważ kanały LISTEN/NOTIFY PostgreSQL nie są obiektami bazy danych z
własnymi egzekwowalnymi GRANTami. Zobacz stronę SSE, aby dowiedzieć się, co to oznacza w
praktyce.
1. Logowanie interaktywne (JWT)
Użytkownicy uwierzytelniają się za pomocą swojej rzeczywistej nazwy użytkownika i hasła PostgreSQL przez
uwierzytelnianie HTTP Basic w POST /{prefix}/{database}/token. Jeśli logowanie powiedzie się, otrzymują krótkotrwały JWT. Kolejne żądania
przekazują ten token w nagłówku Authorization: Bearer <token>, a PgArachne przełącza
aktywną rolę na tego użytkownika na czas trwania każdego żądania.
curl -X POST http://localhost:8080/db/my_database/token -u demo_user:user_password
→ {"token":"eyJhbGciOi...","token_type":"Bearer","expires_in":28800}Dane logowania podróżują w nagłówku Authorization, nigdy w treści JSON, a logowanie ma własny adres URL, więc reverse proxy
może ograniczać jego częstotliwość bez odczytywania treści żądań. Odpowiedź nigdy nie może być cache’owana.
Wymaga JWT_SECRET. Gdy nie jest skonfigurowany, endpoint zwraca HTTP 404
(-32601), a klienci korzystają zamiast tego z bezpośrednich danych logowania (metoda 4)
lub tokenów API (metoda 2).
2. Konta serwisowe (tokeny API)
Dla systemów automatycznych lub skryptów zalecane są długoterminowe tokeny API.
- Tokeny są przechowywane w tabeli
pgarachne.api_tokens. - Każdy token jest przypisany do konkretnej roli w bazie danych.
- Token wysyła się w nagłówku
Authorization: Bearer <token>.
Generowanie tokenów API wymaga roli pgarachne_admin. Użyj pgarachne.add_api_token(...)
z rolą, która jest członkiem pgarachne_admin.
3. Zewnętrzny dostawca identyfikacji (własny JWT)
Jeśli użytkownicy są uwierzytelniani poza PgArachne (na przykład przez zewnętrzną usługę uwierzytelniania), możesz generować tam JWT i wysyłać je bezpośrednio do PgArachne.
- Format nagłówka:
Authorization: Bearer <jwt>. - Podpisywanie: tylko HMAC (
HS256/HS384/HS512) z użyciem tego samegoJWT_SECRETskonfigurowanego w PgArachne. - Wymagane claimy:
db_role(ciąg znaków, niepusty) orazdb_name(ciąg znaków, musi odpowiadać segmentowi ścieżki:database). - Wymagany claim:
exp(znacznik czasu Unix) do określenia wygaśnięcia tokenu.
Wymaga JWT_SECRET; bez niego wartości Bearer są sprawdzane wyłącznie jako tokeny API.
Minimalny przykład payloadu:
{
"db_role": "demo_user",
"db_name": "my_database",
"exp": 1767225600
}Uwaga: asymetryczne algorytmy JWT (np. RS256 / ES256) nie są
wspierane.
4. Bezpośrednie dane logowania do bazy danych (Basic Auth)
Najprostsza opcja: wysyłaj nazwę użytkownika i hasło PostgreSQL z każdym żądaniem, używając
standardowego HTTP Basic Authentication. PgArachne otwiera dedykowany pool połączeń uwierzytelniony bezpośrednio
jako ten użytkownik — SET LOCAL ROLE nie jest wykonywane.
Authorization: Basic <base64(username:password)>Przykład z curl:
curl -X POST http://localhost:8080/db/my_database/jsonrpc \
-u demo_user:user_password \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"api.hello_world","params":{},"id":1}'- Szybkie prototypowanie i lokalny rozwój — zarządzanie tokenami nie jest wymagane.
- Usługi wewnętrzne, które już bezpiecznie zarządzają danymi logowania.
- Scenariusze, w których wcześniejsze wystawianie JWT dodaje niepotrzebną złożoność.
Kluczowe różnice względem metod opartych na tokenach:
GRANT demo_user TO pgarachnenie jest wymagane — PgArachne nie przełącza ról.- Row-Level Security PostgreSQL oraz uprawnienia
GRANTsą wymuszane jak zwykle, ponieważ połączenie działa jako rzeczywisty użytkownik. - Poole połączeń są utrzymywane osobno dla każdego użytkownika, z maksymalnym czasem życia 5 minut. Po zmianie hasła stare połączenia wygasają w tym okresie.
- Aby klucze idempotencji działały z bezpośrednimi danymi logowania, przyznaj użytkownikowi uprawnienie
EXECUTE ON FUNCTION pgarachne.save_idempotency_key(text, text).
Uprawnienia proxy: wymagane tylko dla metod 1–3
Dla uwierzytelniania JWT i tokenem API, PgArachne łączy się jako użytkownik systemowy zdefiniowany w
DB_USER (np. pgarachne) i przełącza tożsamość za pomocą
SET LOCAL ROLE. Użytkownik systemowy musi być członkiem każdej docelowej roli.
-- Wymagane tylko dla uwierzytelniania JWT / tokenem API:
GRANT demo_user TO pgarachne;To uprawnienie nie jest potrzebne przy użyciu bezpośrednich danych logowania (metoda 4).
Porównanie metod uwierzytelniania
| Metoda | Nagłówek | SET LOCAL ROLE | GRANT … TO pgarachne | Najlepsze dla |
|---|---|---|---|---|
| JWT (/token) | Bearer <jwt> | ✅ Tak | Wymagane | Sesje użytkowników końcowych |
| Token API | Bearer <token> | ✅ Tak | Wymagane | Usługi automatyczne |
| Zewnętrzny JWT | Bearer <jwt> | ✅ Tak | Wymagane | Integracja z zewnętrznym IdP |
| Bezpośrednie dane logowania | Basic <b64> | ❌ Nie | Niewymagane | Rozwój, usługi wewnętrzne |
Które funkcje można wywołać
PgArachne nie ma własnej listy dozwolonych schematów — o tym, co rola może wywołać, decydują wyłącznie uprawnienia
PostgreSQL. Funkcję można wywołać (i jest wymieniana przez capabilities, MCP tools/list oraz
eksport OpenAPI), gdy przyjmuje jeden parametr jsonb, rola ma do niej EXECUTE, a rola ma
USAGE do jej schematu. Funkcje w pg_catalog, information_schema,
pgarachne oraz funkcje należące do rozszerzeń są pomijane na liście dla czytelności, ale obowiązują
je te same uprawnienia.
Domyślne ustawienia PostgreSQL są liberalne
Domyślnie PostgreSQL nadaje EXECUTE do każdej nowej funkcji roli PUBLIC, a każda rola
ma USAGE do schematu public. Funkcja pomocnicza public.something(jsonb)
może więc zostać wywołana przez API przez dowolną uwierzytelnioną rolę, chyba że odbierzesz uprawnienie. Zalecana konfiguracja:
-- Nowe funkcje nie są wykonywalne przez wszystkich (uruchom jako rola, która je tworzy):
ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;
-- Trzymaj funkcje API w dedykowanym schemacie i nadawaj uprawnienia jawnie:
GRANT USAGE ON SCHEMA api TO demo_user;
GRANT EXECUTE ON FUNCTION api.hello_world(jsonb) TO demo_user;Ochrona przed atakami brute-force
LOGIN_RATE_LIMIT i LOGIN_RATE_LIMIT_PER_IP dotyczą każdej metody uwierzytelniania,
na każdym endpoincie (JSON-RPC, MCP, SSE, OpenAPI):
/token: każda próba jest wliczana do limitów na (IP, nazwę użytkownika) i na IP.- Bezpośrednie dane logowania (Basic Auth): nieudane próby są wliczane do limitów na (IP, nazwę użytkownika) i na IP. Udane żądania nie są liczone, więc prawidłowy klient wysyłający dane logowania w każdym żądaniu nigdy nie zostanie ograniczony.
- Tokeny Bearer (JWT lub token API): nieudane próby są wliczane do limitu na IP.
Po wyczerpaniu limitu kolejne próby są odrzucane z HTTP 429 aż do upływu okna
(LOGIN_RATE_WINDOW) — bez jakiegokolwiek sprawdzania danych logowania.