Skip to content

Runbook: DO API & Database správa

🗄️ VYŘAZENO — cluster už neexistuje (ověřeno 2026-08-27)

Na DO účtu je nula databázových clusterů. Token je přitom platný (GET /v2/account200), takže to není chyba přístupu — cluster 530f1c9e-… byl zrušen (patrně v rámci CR-141 DO PG cleanup). GET …/databases/530f1c9e-…/firewall vrací cluster not found.

Důsledek: žádné „trusted sources" k údržbě nejsou. Postup níže si nech jako referenci pro případný nový cluster, ale neaplikuj ho na tenhle ID.

Ověření, než na tomhle runbooku začneš stavět:

DO_TOKEN=$(cat /root/secrets/digitalocean/api_token)
curl -s -H "Authorization: Bearer $DO_TOKEN" https://api.digitalocean.com/v2/databases \
  | python3 -c 'import sys,json; print(len(json.load(sys.stdin).get("databases") or []), "clusteru")'

DO API

  • Token: /root/secrets/digitalocean/api_token
  • Cluster ID: 530f1c9e-9ae7-4d0f-a531-0e490c9b9135 ⚠️ neexistuje
  • Cluster name: s60-postgres-dev
  • Base URL: https://api.digitalocean.com/v2

Trusted sources (IP whitelist)

# Zobrazit aktuální
DO_TOKEN=$(cat /root/secrets/digitalocean/api_token)
curl -s -H "Authorization: Bearer $DO_TOKEN" \
  "https://api.digitalocean.com/v2/databases/530f1c9e-9ae7-4d0f-a531-0e490c9b9135/firewall" | python3 -m json.tool

# Aktualizovat — POZOR: PUT nahrazuje VŠECHNA pravidla!
curl -s -X PUT -H "Authorization: Bearer $DO_TOKEN" -H "Content-Type: application/json" \
  "https://api.digitalocean.com/v2/databases/530f1c9e-9ae7-4d0f-a531-0e490c9b9135/firewall" \
  -d '{"rules":[
    {"type":"ip_addr","value":"178.104.40.167"},
    {"type":"ip_addr","value":"178.104.36.211"},
    {"type":"ip_addr","value":"23.88.96.73"},
    {"type":"ip_addr","value":"178.63.52.57"},
    {"type":"ip_addr","value":"178.104.15.77"}
  ]}'

Cílový stav trusted sources (aktualizováno 2026-08-27):

IP Server
178.104.40.167 sentinel
178.104.36.211 prod-alfa
23.88.96.73 hub-alfa
178.63.52.57 cerebro
178.104.15.77 ⚠️ dřív cortex — dnes mailserver ([[feedback_ip_reuse_stale_allowlists]]), ověřit než se to zase odsouhlasí

⚠️ Tabulka výše je jen referenční — živý firewall neexistuje (viz box na začátku: nula clusterů). Dřívější verze tohohle odstavce tvrdila, že v něm „pořád je 49.13.168.234"; to bylo napsáno z runbooku, ne z ověření proti API. Skutečnost: cluster je zrušený, takže stará IP tudy zděděná být nemůže a žádný úklid tu není co dělat ([[feedback_facts_not_memory]]).

Kdyby se někdy zakládal nový cluster: doctl na sentinelu není, jede se přes curl výše, a změna trusted sources je DB přístup ⇒ schvaluje Libor ([[feedback_pg_access_approval]]).

DB Users — Access matrix

User Přístup Kdo používá
doadmin ALL (admin) POUZE sentinel + Libor
s60_infra_user všechny dev DB, CREATEDB, NE hub/prod infra agent
s60_cs_user POUZE bwcs cs agent (cortex)
s60_hub_user s60_auth_hub hub-alfa auth
s60_prod_user s60_auth_prod prod-alfa auth
s60_*_hub_user per-service hub DB hub-alfa per-service
s60_*_prod_user per-service prod DB prod-alfa per-service

Credentials

Soubor Obsah
/root/secrets/digitalocean/api_token DO API token
/root/secrets/digitalocean/doadmin.env PG admin (doadmin)
/root/secrets/digitalocean/infra_user.env s60_infra_user

Bezpečnostní model

PUBLIC role — KRITICKÉ

PostgreSQL nové usery dědí CONNECT od PUBLIC role. Musíme:

-- 1. Odebrat PUBLIC přístup na VŠECH databázích
REVOKE CONNECT ON DATABASE <db_name> FROM PUBLIC;

-- 2. Explicitně udělit přístup konkrétnímu userovi
GRANT CONNECT ON DATABASE <db_name> TO <user>;

Toto se musí udělat pro KAŽDOU novou databázi!

Přidání nového DB usera

  1. Vytvořit user přes DO API nebo psql
  2. REVOKE CONNECT FROM PUBLIC na všech relevantních DB
  3. GRANT CONNECT pouze na DB, ke kterým má mít přístup
  4. Otestovat: přihlásit se jako nový user a ověřit, že vidí jen povolené DB
  5. Credentials uložit do /root/secrets/digitalocean/<user>.env

Změna hesla

DO_TOKEN=$(cat /root/secrets/digitalocean/api_token)
curl -s -X POST -H "Authorization: Bearer $DO_TOKEN" -H "Content-Type: application/json" \
  "https://api.digitalocean.com/v2/databases/530f1c9e-9ae7-4d0f-a531-0e490c9b9135/users/<username>/reset_auth" \
  -d '{"mysql_settings":{"auth_plugin":"caching_sha2_password"}}'

Připojení k DB

source /root/secrets/digitalocean/doadmin.env
psql "postgresql://doadmin:${PGPASSWORD}@s60-postgres-dev-do-user-28025597-0.f.db.ondigitalocean.com:25060/defaultdb?sslmode=require"