docs: focus public documentation on product usage
This commit is contained in:
+54
-345
@@ -1,356 +1,65 @@
|
||||
# `dwh-auth`: guida server
|
||||
|
||||
`dwh-auth` autentica la route REST `/dwh/` con una chiave per installazione. È un componente Linux
|
||||
opzionale e server-side: usa `systemd`, non `tht` né Docker Compose, non legge risultati clinici e
|
||||
non si collega a PostgreSQL. La chiave serve solo a `rest_api`; `postgres_direct` e `ssh_tunnel`
|
||||
non la usano.
|
||||
`dwh-auth` protegge la route REST `/dwh/` con una chiave distinta per ogni installazione
|
||||
ThothII. Il componente gira come servizio Linux separato, non legge i dati del DWH e non si
|
||||
collega direttamente a PostgreSQL.
|
||||
|
||||
## Prerequisiti e confini
|
||||
|
||||
- Usare un checkout revisionato, Docker per la build e un operatore autorizzato sul server DWH.
|
||||
- Una chiave identifica un'installazione, non una persona. L'`installation-id` è unico, non
|
||||
personale e senza dati clinici.
|
||||
- Chiavi, digest, file di consegna e backup restano in file protetti: mai Git, argv, variabili
|
||||
d'ambiente, log, JSON pubblico o evidenze.
|
||||
- Preparare backup e rollback prima di Nginx. Installare il servizio non autorizza una modifica
|
||||
della route pubblica.
|
||||
|
||||
## Percorsi, owner e mode
|
||||
|
||||
| Oggetto | Percorso | Owner e mode |
|
||||
| --- | --- | --- |
|
||||
| Binario | `/usr/local/sbin/dwh-auth` | `root:root`, `0755` |
|
||||
| Unit | `/etc/systemd/system/dwh-auth.service` | `root:root`, `0644` |
|
||||
| Tmpfiles | `/usr/lib/tmpfiles.d/dwh-auth.conf` | `root:root`, `0644` |
|
||||
| Registro, `active`, `revoked` | `/var/lib/dwh-auth/` | `root:dwh-auth`, `2750` |
|
||||
| Lock | `/var/lib/dwh-auth/.writer.lock` | `root:dwh-auth`, `0640` |
|
||||
| Record | `/var/lib/dwh-auth/{active,revoked}/<public-key-id>.json` | `root:dwh-auth`, `0640` |
|
||||
| Socket runtime | `/run/dwh-auth/verify.sock` | `dwh-auth:www-data`, `0660` |
|
||||
| Consegne e backup | `/root/dwh-auth-provision/` | directory `root:root` `0700`, file `0600` |
|
||||
|
||||
Il record conserva un digest interno (`secret_sha256`) e metadati, mai la chiave in chiaro. Non
|
||||
leggere, stampare, calcolare o mettere quel digest in una prova operativa.
|
||||
|
||||
## Build, installazione e avvio
|
||||
|
||||
Costruire dal commit congelato e registrare solo checksum del binario e SHA sorgente:
|
||||
|
||||
```bash
|
||||
cd /srv/thothii/app
|
||||
bash scripts/build-dwh-auth.sh --output /tmp/dwh-auth-release
|
||||
sha256sum /tmp/dwh-auth-release/dwh-auth-linux-amd64
|
||||
```mermaid
|
||||
flowchart LR
|
||||
CLIENT["Installazione ThothII"] -->|"X-API-Key"| NGINX["Nginx"]
|
||||
NGINX --> AUTH["dwh-auth\nUnix socket"]
|
||||
AUTH --> REGISTRY["Registro chiavi\nactive e revoked"]
|
||||
AUTH -->|"authorized"| REST["DWH REST"]
|
||||
```
|
||||
|
||||
Scegliere l'architettura corretta. Il template PSD usa il gruppo Nginx `www-data`; confermarlo
|
||||
prima dell'installazione su un host diverso.
|
||||
## Confini di sicurezza
|
||||
|
||||
```bash
|
||||
sudo groupadd --system dwh-auth
|
||||
sudo useradd --system --no-create-home --shell /usr/sbin/nologin --gid dwh-auth dwh-auth
|
||||
sudo install -o root -g root -m 0755 /tmp/dwh-auth-release/dwh-auth-linux-amd64 /usr/local/sbin/dwh-auth
|
||||
sudo install -o root -g root -m 0644 deploy/dwh-auth/dwh-auth.service /etc/systemd/system/dwh-auth.service
|
||||
sudo install -o root -g root -m 0644 deploy/dwh-auth/dwh-auth.tmpfiles.conf /usr/lib/tmpfiles.d/dwh-auth.conf
|
||||
sudo install -d -o root -g root -m 0700 /root/dwh-auth-provision
|
||||
sudo systemd-tmpfiles --create /usr/lib/tmpfiles.d/dwh-auth.conf
|
||||
sudo /usr/local/sbin/dwh-auth --registry-root /var/lib/dwh-auth check
|
||||
sudo systemd-analyze verify /etc/systemd/system/dwh-auth.service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now dwh-auth
|
||||
sudo systemctl status dwh-auth --no-pager
|
||||
```
|
||||
- Una chiave identifica un'installazione, non una persona.
|
||||
- Chiavi e backup restano in file protetti e non entrano in Git, log, argomenti o JSON pubblico.
|
||||
- Il registro conserva digest e metadati, mai la chiave in chiaro.
|
||||
- La route REST deve essere esposta esclusivamente tramite TLS verificato.
|
||||
|
||||
Controllare i mode con `stat`. Il servizio apre il registro in sola lettura e crea solo il socket.
|
||||
Non creare JSON, lock o socket a mano: oggetti insicuri devono fallire chiusi.
|
||||
## Installazione
|
||||
|
||||
## Check, elenco e stato
|
||||
Il servizio usa questi percorsi:
|
||||
|
||||
Usare sempre un root assoluto. Questi comandi espongono solo ID pubblici, stato, date e scadenza:
|
||||
|
||||
```bash
|
||||
sudo /usr/local/sbin/dwh-auth --registry-root /var/lib/dwh-auth check
|
||||
sudo /usr/local/sbin/dwh-auth --registry-root /var/lib/dwh-auth key list --json
|
||||
key_id=public-key-id
|
||||
sudo /usr/local/sbin/dwh-auth --registry-root /var/lib/dwh-auth key status --key-id "$key_id" --json
|
||||
```
|
||||
|
||||
Un errore di integrità, permessi, symlink o JSON malformato richiede ripristino da backup protetto,
|
||||
non una correzione manuale del record.
|
||||
|
||||
## Creazione, consegna, scadenza e revoca
|
||||
|
||||
Il comando crea la chiave una volta in un nuovo file assoluto `0600`; stdout contiene solo ID
|
||||
pubblico, installazione e percorso. Il file di output non deve esistere.
|
||||
|
||||
```bash
|
||||
installation_id=psd-mac-primary
|
||||
description=operatore-mac-primario
|
||||
key_output=/root/dwh-auth-provision/psd-mac-primary.key
|
||||
sudo /usr/local/sbin/dwh-auth --registry-root /var/lib/dwh-auth key create \
|
||||
--installation-id "$installation_id" \
|
||||
--description "$description" \
|
||||
--output "$key_output"
|
||||
```
|
||||
|
||||
Aggiungere `--expires-at "YYYY-MM-DDTHH:MM:SSZ"` solo se la policy impone una scadenza; il default è nessuna
|
||||
scadenza. Consegnare il file solo con vault aziendale, secret manager, MDM o trasferimento
|
||||
autenticato ristretto. Mai email, chat, ticket, `cat` o copia-incolla. Il client conferma ID
|
||||
pubblico e ping, poi il materiale temporaneo viene rimosso secondo policy.
|
||||
|
||||
L'import legacy è temporaneo PSD: il file sorgente è già `root:root` `0600` e non viene mai letto o
|
||||
stampato dall'operatore.
|
||||
|
||||
```bash
|
||||
sudo /usr/local/sbin/dwh-auth --registry-root /var/lib/dwh-auth key import \
|
||||
--legacy-raw --installation-id legacy-shared \
|
||||
--from-file /root/dwh-auth-provision/legacy-shared.key
|
||||
```
|
||||
|
||||
Per rotare: creare seconda generazione, consegnarla, configurarla e provare `/rpc/ping`; confermare
|
||||
l'ID pubblico; attendere l'osservazione; poi revocare la precedente e provare nuova=successo,
|
||||
precedente=401.
|
||||
|
||||
```bash
|
||||
previous_key_id=public-key-id
|
||||
revocation_reason=shared-credential-rotation
|
||||
sudo /usr/local/sbin/dwh-auth --registry-root /var/lib/dwh-auth key revoke \
|
||||
--key-id "$previous_key_id" --reason "$revocation_reason"
|
||||
```
|
||||
|
||||
La revoca non è annullabile e un ID revocato non si ricrea.
|
||||
|
||||
## Backup, rollback e disinstallazione
|
||||
|
||||
Prima di mutare, creare un archivio root-only `0600` del registro e copie protette delle sole
|
||||
configurazioni coinvolte. L'archivio contiene digest, quindi è materiale riservato: custodirlo su
|
||||
storage cifrato approvato; l'evidenza ammessa riporta solo percorso, owner, mode, timestamp e
|
||||
checksum dell'archivio. Il rollback dual-key ripristina la route e il servizio revisionati, esegue
|
||||
`nginx -t` e fa reload solo autorizzato; non ripristina chiavi revocate, PostgreSQL, sessioni
|
||||
legacy, indici Qdrant o cache Ollama.
|
||||
|
||||
La disinstallazione richiede autorizzazione esplicita, client REST migrati/revocati e rollback non
|
||||
più necessario. Solo allora disabilitare l'unità; conservare registro e backup fino alla retention
|
||||
approvata. Non inserire `dwh-auth` in Compose o in `tht start`/`tht stop`.
|
||||
|
||||
## Procedure riproducibili e secret-safe
|
||||
|
||||
Eseguire soltanto nel gate autorizzato. Le variabili seguenti contengono percorsi, timestamp e
|
||||
codici, mai una chiave. Il manifest e l'archivio del registro sono `0600`; l'archivio resta
|
||||
materiale riservato su storage cifrato approvato.
|
||||
|
||||
```bash
|
||||
run_id=$(date -u +%Y%m%dT%H%M%SZ)
|
||||
backup_root=/root/dwh-auth-provision
|
||||
registry_root=/var/lib/dwh-auth
|
||||
registry_backup="$backup_root/registry-$run_id.tar"
|
||||
manifest="$backup_root/registry-$run_id.manifest"
|
||||
sudo install -o root -g root -m 0600 /dev/null "$registry_backup"
|
||||
sudo install -o root -g root -m 0600 /dev/null "$manifest"
|
||||
sudo tar --acls --xattrs -C /var/lib -cf "$registry_backup" dwh-auth
|
||||
sudo sh -c 'sha256sum "$1" > "$2"' sh "$registry_backup" "$manifest"
|
||||
if sudo sha256sum -c "$manifest" >/dev/null; then printf 'registry_manifest=PASS\n'; else printf 'registry_manifest=FAIL\n' >&2; exit 1; fi
|
||||
```
|
||||
|
||||
Il ripristino non sovrappone mai un tar al registro attivo. Estrarre prima in staging nello stesso
|
||||
filesystem di `/var/lib`, verificare il candidato, rinominare il registro attuale in una copia
|
||||
recuperabile e sostituirlo. Non cancellare il pre-ripristino: serve al rollback se `check` o
|
||||
l'avvio falliscono.
|
||||
|
||||
```bash
|
||||
registry_staging="/var/lib/.dwh-auth-restore-$run_id"
|
||||
registry_candidate="$registry_staging/dwh-auth"
|
||||
registry_previous="/var/lib/dwh-auth.pre-restore-$run_id"
|
||||
if [ -e "$registry_staging" ] || [ -e "$registry_previous" ]; then printf 'registry_restore=FAIL\n' >&2; exit 1; fi
|
||||
if ! sudo sha256sum -c "$manifest" >/dev/null; then printf 'registry_restore=FAIL\n' >&2; exit 1; fi
|
||||
if ! sudo install -d -o root -g root -m 0700 "$registry_staging"; then printf 'registry_restore=FAIL\n' >&2; exit 1; fi
|
||||
if ! sudo tar --acls --xattrs -C "$registry_staging" -xf "$registry_backup"; then printf 'registry_restore=FAIL\n' >&2; exit 1; fi
|
||||
if ! sudo /usr/local/sbin/dwh-auth --registry-root "$registry_candidate" check; then printf 'registry_restore=FAIL\n' >&2; exit 1; fi
|
||||
if ! sudo systemctl stop dwh-auth; then printf 'registry_restore=FAIL\n' >&2; exit 1; fi
|
||||
if ! sudo mv -T -- "$registry_root" "$registry_previous"; then
|
||||
if sudo systemctl start dwh-auth; then printf 'registry_restore_rollback=PASS\n' >&2; else printf 'registry_restore_rollback=FAIL\n' >&2; fi
|
||||
exit 1
|
||||
fi
|
||||
if ! sudo mv -T -- "$registry_candidate" "$registry_root"; then
|
||||
if ! sudo mv -T -- "$registry_previous" "$registry_root"; then printf 'registry_restore_rollback=FAIL\n' >&2; exit 1; fi
|
||||
if sudo /usr/local/sbin/dwh-auth --registry-root "$registry_root" check && sudo systemctl start dwh-auth; then printf 'registry_restore_rollback=PASS\n' >&2; else printf 'registry_restore_rollback=FAIL\n' >&2; fi
|
||||
exit 1
|
||||
fi
|
||||
if sudo /usr/local/sbin/dwh-auth --registry-root "$registry_root" check && sudo systemctl start dwh-auth; then
|
||||
printf 'registry_restore=PASS\n'
|
||||
else
|
||||
sudo systemctl stop dwh-auth || true
|
||||
if ! sudo mv -T -- "$registry_root" "$registry_staging/failed-dwh-auth"; then printf 'registry_restore_rollback=FAIL\n' >&2; exit 1; fi
|
||||
if ! sudo mv -T -- "$registry_previous" "$registry_root"; then printf 'registry_restore_rollback=FAIL\n' >&2; exit 1; fi
|
||||
if sudo /usr/local/sbin/dwh-auth --registry-root "$registry_root" check && sudo systemctl start dwh-auth; then printf 'registry_restore_rollback=PASS\n' >&2; else printf 'registry_restore_rollback=FAIL\n' >&2; fi
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
Per le prove, creare file header `0600` che contengono esattamente `X-API-Key: valore`. Il valore
|
||||
passa dal file chiave al file header senza argv, ambiente o stdout. I file header sono materiale
|
||||
segreto con la stessa custodia e retention delle chiavi.
|
||||
|
||||
```bash
|
||||
v1_key_file="$key_output"
|
||||
legacy_key_file=/root/dwh-auth-provision/legacy-shared.key
|
||||
v1_header_file=/root/dwh-auth-provision/dwh-auth-v1.header
|
||||
legacy_header_file=/root/dwh-auth-provision/dwh-auth-legacy.header
|
||||
random_header_file=/root/dwh-auth-provision/dwh-auth-random.header
|
||||
if ! sudo python3 -c '
|
||||
import pathlib, sys
|
||||
if any(b"\n" in pathlib.Path(path).read_bytes() for path in sys.argv[1:]):
|
||||
raise SystemExit(1)
|
||||
' "$v1_key_file" "$legacy_key_file"; then
|
||||
printf 'key_file_bytes=FAIL\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
printf 'key_file_bytes=PASS\n'
|
||||
for header_file in "$v1_header_file" "$legacy_header_file" "$random_header_file"; do
|
||||
sudo install -o root -g root -m 0600 /dev/null "$header_file"
|
||||
done
|
||||
sudo sh -c '{ printf "%s" "X-API-Key: "; dd if="$1" bs=65536 status=none; printf "\n"; } > "$2"' sh "$v1_key_file" "$v1_header_file"
|
||||
sudo sh -c '{ printf "%s" "X-API-Key: "; dd if="$1" bs=65536 status=none; printf "\n"; } > "$2"' sh "$legacy_key_file" "$legacy_header_file"
|
||||
sudo sh -c 'printf "%s\n" "X-API-Key: invalid-test" > "$1"' sh "$random_header_file"
|
||||
```
|
||||
|
||||
Il socket `/verify` deve restituire 204 per v1 e legacy durante il dual-key, 401 per file casuale
|
||||
e richiesta senza header. Stampare solo PASS/FAIL.
|
||||
|
||||
```bash
|
||||
status=$(sudo curl --header "@$v1_header_file" --unix-socket /run/dwh-auth/verify.sock --output /dev/null --silent --show-error --write-out '%{http_code}' http://localhost/verify)
|
||||
[ "$status" = 204 ] && printf 'socket_v1=PASS\n' || { printf 'socket_v1=FAIL\n' >&2; exit 1; }
|
||||
status=$(sudo curl --header "@$legacy_header_file" --unix-socket /run/dwh-auth/verify.sock --output /dev/null --silent --show-error --write-out '%{http_code}' http://localhost/verify)
|
||||
[ "$status" = 204 ] && printf 'socket_legacy=PASS\n' || { printf 'socket_legacy=FAIL\n' >&2; exit 1; }
|
||||
status=$(sudo curl --header "@$random_header_file" --unix-socket /run/dwh-auth/verify.sock --output /dev/null --silent --show-error --write-out '%{http_code}' http://localhost/verify)
|
||||
[ "$status" = 401 ] && printf 'socket_random=PASS\n' || { printf 'socket_random=FAIL\n' >&2; exit 1; }
|
||||
status=$(sudo curl --unix-socket /run/dwh-auth/verify.sock --output /dev/null --silent --show-error --write-out '%{http_code}' http://localhost/verify)
|
||||
[ "$status" = 401 ] && printf 'socket_missing=PASS\n' || { printf 'socket_missing=FAIL\n' >&2; exit 1; }
|
||||
```
|
||||
|
||||
Per HTTPS reale usare i file header protetti e la CA approvata contro `/dwh/rpc/ping`: PostgREST
|
||||
può restituire qualsiasi 2xx, non si pretende 204. Prima della revoca, v1 e legacy devono dare
|
||||
2xx; il file casuale deve dare 401.
|
||||
|
||||
```bash
|
||||
ping_url=https://supabase-aritmolab.policlinicosandonato.it/dwh/rpc/ping
|
||||
ca_file=/root/dwh-auth-provision/psd-dwh-ca.pem
|
||||
status=$(sudo curl --header "@$v1_header_file" --cacert "$ca_file" --connect-timeout 5 --max-time 15 --output /dev/null --silent --show-error --write-out '%{http_code}' "$ping_url")
|
||||
case "$status" in 2??) printf 'https_v1_pre_revoke=PASS\n' ;; *) printf 'https_v1_pre_revoke=FAIL\n' >&2; exit 1 ;; esac
|
||||
status=$(sudo curl --header "@$legacy_header_file" --cacert "$ca_file" --connect-timeout 5 --max-time 15 --output /dev/null --silent --show-error --write-out '%{http_code}' "$ping_url")
|
||||
case "$status" in 2??) printf 'https_legacy_pre_revoke=PASS\n' ;; *) printf 'https_legacy_pre_revoke=FAIL\n' >&2; exit 1 ;; esac
|
||||
status=$(sudo curl --header "@$random_header_file" --cacert "$ca_file" --connect-timeout 5 --max-time 15 --output /dev/null --silent --show-error --write-out '%{http_code}' "$ping_url")
|
||||
[ "$status" = 401 ] && printf 'https_random=PASS\n' || { printf 'https_random=FAIL\n' >&2; exit 1; }
|
||||
```
|
||||
|
||||
Dopo l'osservazione, revocare solo la legacy usando il suo ID pubblico già registrato. Dopo la
|
||||
revoca v1 resta 2xx e legacy diventa 401 anche via HTTPS.
|
||||
|
||||
```bash
|
||||
legacy_key_id=legacy-shared
|
||||
sudo /usr/local/sbin/dwh-auth --registry-root "$registry_root" key revoke --key-id "$legacy_key_id" --reason shared-credential-rotation
|
||||
status=$(sudo curl --header "@$v1_header_file" --cacert "$ca_file" --connect-timeout 5 --max-time 15 --output /dev/null --silent --show-error --write-out '%{http_code}' "$ping_url")
|
||||
case "$status" in 2??) printf 'https_v1_post_revoke=PASS\n' ;; *) printf 'https_v1_post_revoke=FAIL\n' >&2; exit 1 ;; esac
|
||||
status=$(sudo curl --header "@$legacy_header_file" --cacert "$ca_file" --connect-timeout 5 --max-time 15 --output /dev/null --silent --show-error --write-out '%{http_code}' "$ping_url")
|
||||
[ "$status" = 401 ] && printf 'https_legacy_post_revoke=PASS\n' || { printf 'https_legacy_post_revoke=FAIL\n' >&2; exit 1; }
|
||||
```
|
||||
|
||||
Per provare 503 in una finestra approvata, registrare l'orario, fermare temporaneamente l'unità,
|
||||
eseguire il ping con timeout e trap di ripristino; il comando deve stampare solo PASS/FAIL.
|
||||
|
||||
```bash
|
||||
was_active=$(sudo systemctl is-active dwh-auth || true)
|
||||
[ "$was_active" = active ] || { printf 'https_auth_down=FAIL\n' >&2; exit 1; }
|
||||
restore_auth() { sudo systemctl start dwh-auth; }
|
||||
trap restore_auth EXIT INT TERM
|
||||
sudo systemctl stop dwh-auth
|
||||
status=$(sudo curl --header "@$random_header_file" --cacert "$ca_file" --connect-timeout 5 --max-time 15 --output /dev/null --silent --show-error --write-out '%{http_code}' "$ping_url" || true)
|
||||
[ "$status" = 503 ] && printf 'https_auth_down=PASS\n' || { printf 'https_auth_down=FAIL\n' >&2; exit 1; }
|
||||
sudo systemctl start dwh-auth
|
||||
trap - EXIT INT TERM
|
||||
```
|
||||
|
||||
Lo scan journal non salva righe grezze: controlla davvero le chiavi v1 e legacy leggendo solo i
|
||||
percorsi dei file da argv, e conserva anche la difesa generica per prefisso e digest. Il filtro
|
||||
emette solo PASS/FAIL.
|
||||
|
||||
```bash
|
||||
since=$(date -u -d '15 minutes ago' +%Y-%m-%dT%H:%M:%SZ)
|
||||
if sudo python3 -c '
|
||||
import pathlib, subprocess, sys
|
||||
max_journal_bytes = 1_048_576
|
||||
max_journal_lines = 10_000
|
||||
max_chunk_bytes = 65_536
|
||||
process = None
|
||||
try:
|
||||
actual_keys = {pathlib.Path(path).read_bytes() for path in sys.argv[2:]}
|
||||
needles = (b"thtdwh_v1", b"secret_sha256", *actual_keys)
|
||||
max_needle_length = max(map(len, needles))
|
||||
process = subprocess.Popen(
|
||||
["journalctl", "-u", "dwh-auth", "--since", sys.argv[1], "--no-pager", "--output=cat"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
except OSError:
|
||||
raise SystemExit(2)
|
||||
def stop_child():
|
||||
if process is not None:
|
||||
if process.poll() is None:
|
||||
process.kill()
|
||||
process.wait()
|
||||
bytes_seen = 0
|
||||
line_count = 0
|
||||
line_open = False
|
||||
carry = b""
|
||||
try:
|
||||
while True:
|
||||
remaining = max_journal_bytes - bytes_seen
|
||||
if remaining == 0:
|
||||
if process.stdout.read1(1):
|
||||
raise SystemExit(2)
|
||||
break
|
||||
chunk = process.stdout.read1(min(max_chunk_bytes, remaining))
|
||||
if not chunk:
|
||||
break
|
||||
bytes_seen += len(chunk)
|
||||
searchable = carry + chunk
|
||||
if any(needle in searchable for needle in needles):
|
||||
raise SystemExit(1)
|
||||
carry = searchable[-(max_needle_length - 1):]
|
||||
for byte in chunk:
|
||||
if byte == 10:
|
||||
line_count += 1
|
||||
line_open = False
|
||||
if line_count > max_journal_lines:
|
||||
raise SystemExit(2)
|
||||
else:
|
||||
line_open = True
|
||||
if line_open:
|
||||
line_count += 1
|
||||
if line_count > max_journal_lines:
|
||||
raise SystemExit(2)
|
||||
finally:
|
||||
stop_child()
|
||||
if process.returncode != 0:
|
||||
raise SystemExit(2)
|
||||
' "$since" "$v1_key_file" "$legacy_key_file"; then
|
||||
printf 'journal_actual_key_scan=PASS\n'
|
||||
else
|
||||
printf 'journal_actual_key_scan=FAIL\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
Dopo rollback verificato e migrazione/revoca di ogni client REST, la disinstallazione resta
|
||||
condizionata all'approvazione: eseguire `sudo systemctl disable --now dwh-auth`, ma mantenere
|
||||
registro, backup, manifest e file header protetti per la retention; non cancellarli durante il
|
||||
rollback.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Sintomo | Interpretazione e azione |
|
||||
| Oggetto | Percorso |
|
||||
| --- | --- |
|
||||
| `401` | Chiave assente, malformata, sconosciuta, scaduta, revocata o errata. Verificare trasporto, ID pubblico e consegna; non cercare dettagli nel messaggio. |
|
||||
| `503` | Servizio, socket o registro non disponibile/sicuro. Controllare `systemctl`, socket, mode e `check`; ripristinare il backup approvato. |
|
||||
| `check` fallisce | Integrità del registro non valida. Fermare le scritture, preservare stato e ripristinare; non editare JSON. |
|
||||
| TLS fallisce | CA o SAN non validi. Seguire [TLS](dwh-auth-tls.md), senza bypass. |
|
||||
| Binario | `/usr/local/sbin/dwh-auth` |
|
||||
| Unit systemd | `/etc/systemd/system/dwh-auth.service` |
|
||||
| Registro | `/var/lib/dwh-auth/` |
|
||||
| Socket | `/run/dwh-auth/verify.sock` |
|
||||
| Consegne protette | `/root/dwh-auth-provision/` |
|
||||
|
||||
Per il rollout PSD con i due gate separati vedere il [runbook PSD](../operations/psd-dwh-auth-rollout.md).
|
||||
Installare binario e unit con owner `root`, creare l'utente di servizio `dwh-auth`, quindi
|
||||
abilitare l'unità con `systemctl enable --now dwh-auth`. Il socket deve essere accessibile al
|
||||
gruppo usato da Nginx.
|
||||
|
||||
## Creazione e revoca delle chiavi
|
||||
|
||||
Esempio per l'installazione ACME Limited:
|
||||
|
||||
```bash
|
||||
sudo dwh-auth --registry-root /var/lib/dwh-auth key create \
|
||||
--installation-id acme-factory-primary \
|
||||
--description acme-factory-primary \
|
||||
--output /root/dwh-auth-provision/acme-factory-primary.key
|
||||
```
|
||||
|
||||
Consegnare il file attraverso un vault aziendale o un canale autenticato. Per la rotazione,
|
||||
creare una nuova chiave, distribuirla, aggiornare il client e revocare la precedente usando il
|
||||
suo ID pubblico:
|
||||
|
||||
```bash
|
||||
sudo dwh-auth --registry-root /var/lib/dwh-auth key revoke \
|
||||
--key-id PUBLIC_KEY_ID \
|
||||
--reason scheduled-rotation
|
||||
```
|
||||
|
||||
La revoca è definitiva. Conservare backup cifrati del registro prima di ogni mutazione.
|
||||
|
||||
## Integrazione Nginx
|
||||
|
||||
Nginx inoltra la chiave al socket di `dwh-auth`. Solo una risposta autorizzata permette il
|
||||
passaggio verso il DWH REST; chiavi assenti, sconosciute, scadute o revocate ricevono `401`,
|
||||
mentre indisponibilità del servizio o del registro producono `503`.
|
||||
|
||||
Reference in New Issue
Block a user