mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
A release-readiness QA pass over the whole product. The commits split into defects a user would hit and gates that were reporting green while measuring nothing. ## Fixes that change behaviour Rate limiting was bypassable on every install: TRUST_PROXY defaulted to true, so request.ip came from a client-set header and a forged X-Forwarded-For got past the login limiter. The default is now a private-network trust list. A transient Postgres outage stranded in-flight jobs, leaving finished output on disk with no row pointing at it. A reconciler now resolves those rows and adopts the bytes rather than dropping the work. A Redis connection that moved to a new address wedged every read-blocked consumer, so completions stopped signalling while health still answered 200. Socket timeouts plus subscriber pings recover it. Installing more than one AI bundle left the shared venv multi-versioned and silently broke three tools. The installer now reconciles distributions to one version each. Converting an image to JXL at quality 1 through 4 returned a 500, because libjxl 0.7 rejects the distance those values compute. The quality is floored at what the encoder honours. A missing ffmpeg was also reported to the user as a corrupt upload; it now says the engine is unavailable. RAW uploads reached an unpatched LibRaw on arm64, so it is built from source at 0.22.2, and the release scan was split so it can fail on an unfixed critical instead of hiding it behind ignore-unfixed. ## Gates that could not fail Two mutation lanes ran zero mutants because Stryker crawled the gitignored docs build; coverage discarded its whole report on any failing test; the lint gate skipped root tests, scripts, and two workspaces; and several generated matrices counted a host missing ffmpeg as a passing tool. Each now measures what it claims. Full evidence and the outstanding release items are tracked locally and are not part of this branch.
268 lines
13 KiB
Markdown
268 lines
13 KiB
Markdown
---
|
|
description: "Gestisci utenti, ruoli integrati e personalizzati, permessi, chiavi API, team, sessioni e il log di audit in SnapOtter."
|
|
i18n_source_hash: bea8955f3aff
|
|
i18n_provenance: human
|
|
i18n_output_hash: 317e535b9400
|
|
i18n_hash_version: 2
|
|
---
|
|
|
|
# Utenti, ruoli e permessi {#users-roles-permissions}
|
|
|
|
SnapOtter include tre ruoli integrati, 17 permessi granulari e il supporto per ruoli personalizzati con controllo opzionale dell'accesso per singolo strumento. Questa pagina copre l'intero modello di autorizzazione, lo scope delle chiavi API, la gestione dei team e il logging di audit.
|
|
|
|
::: tip Pagine correlate
|
|
[OIDC / SSO](/it/guide/oidc) | [SAML SSO](/it/guide/saml) | [Provisioning SCIM](/it/guide/scim) | [Sicurezza e hardening](/it/guide/security)
|
|
:::
|
|
|
|
## Utenti {#users}
|
|
|
|
### Creazione degli utenti {#creating-users}
|
|
|
|
Gli amministratori possono creare utenti tramite il pannello di amministrazione o l'endpoint `POST /api/auth/register`. Ogni utente ha un nome utente, un ruolo, un'assegnazione a un team e un indirizzo email opzionale.
|
|
|
|
### Amministratore predefinito {#default-admin}
|
|
|
|
Al primo avvio SnapOtter crea un account amministratore predefinito. Le credenziali provengono da variabili d'ambiente:
|
|
|
|
| Variabile | Predefinito | Descrizione |
|
|
|---|---|---|
|
|
| `DEFAULT_USERNAME` | `admin` | Nome utente per l'account amministratore iniziale |
|
|
| `DEFAULT_PASSWORD` | `admin` | Password per l'account amministratore iniziale |
|
|
|
|
L'amministratore predefinito è tenuto a cambiare la propria password al primo accesso.
|
|
|
|
### Provider di autenticazione {#authentication-providers}
|
|
|
|
Gli utenti possono autenticarsi tramite diversi metodi:
|
|
|
|
- **Locale** - nome utente e password memorizzati nel database di SnapOtter
|
|
- **OIDC** - qualsiasi provider OpenID Connect (vedi [OIDC / SSO](/it/guide/oidc))
|
|
- **SAML** - provider di identità SAML 2.0 (vedi [SAML SSO](/it/guide/saml))
|
|
- **SCIM** - provisioning automatizzato da un provider di identità (vedi [Provisioning SCIM](/it/guide/scim))
|
|
|
|
### Disabilitare l'autenticazione {#disabling-authentication}
|
|
|
|
Imposta `AUTH_ENABLED=false` per disabilitare completamente l'autenticazione. In questa modalità viene usato un utente anonimo sintetico con ruolo `admin` per tutte le richieste. Non è richiesto alcun accesso.
|
|
|
|
::: warning
|
|
Disabilitare l'autenticazione concede pieno accesso da amministratore a chiunque possa raggiungere l'istanza. Usalo solo in ambienti fidati.
|
|
:::
|
|
|
|
## Ruoli integrati {#built-in-roles}
|
|
|
|
SnapOtter include tre ruoli integrati. Non possono essere modificati né eliminati.
|
|
|
|
### Admin {#admin}
|
|
|
|
Tutti e 17 i permessi. Controllo completo sull'istanza.
|
|
|
|
`tools:use` `files:own` `files:all` `apikeys:own` `apikeys:all` `pipelines:own` `pipelines:all` `settings:read` `settings:write` `users:manage` `teams:manage` `features:manage` `system:health` `audit:read` `compliance:manage` `webhooks:manage` `security:manage`
|
|
|
|
### Editor {#editor}
|
|
|
|
7 permessi. Può usare tutti gli strumenti e gestire tutti i file e le pipeline, ma non può accedere alle funzioni di amministrazione.
|
|
|
|
`tools:use` `files:own` `files:all` `apikeys:own` `pipelines:own` `pipelines:all` `settings:read`
|
|
|
|
### User {#user}
|
|
|
|
5 permessi. Può usare gli strumenti e gestire le proprie risorse.
|
|
|
|
`tools:use` `files:own` `apikeys:own` `pipelines:own` `settings:read`
|
|
|
|
## Riferimento dei permessi {#permissions-reference}
|
|
|
|
| Permesso | Descrizione |
|
|
|---|---|
|
|
| `tools:use` | Usare qualsiasi strumento di elaborazione |
|
|
| `files:own` | Visualizzare e gestire i propri file |
|
|
| `files:all` | Visualizzare e gestire i file di tutti gli utenti |
|
|
| `apikeys:own` | Creare e gestire le proprie chiavi API |
|
|
| `apikeys:all` | Visualizzare le chiavi API di tutti gli utenti |
|
|
| `pipelines:own` | Creare e gestire le proprie pipeline |
|
|
| `pipelines:all` | Visualizzare e gestire le pipeline di tutti gli utenti |
|
|
| `settings:read` | Visualizzare le impostazioni dell'istanza |
|
|
| `settings:write` | Modificare le impostazioni dell'istanza |
|
|
| `users:manage` | Crea e gestisci gli account utente entro i limiti di autorità dell'attore |
|
|
| `teams:manage` | Creare, aggiornare ed eliminare team |
|
|
| `features:manage` | Installare e gestire i bundle di funzionalità AI |
|
|
| `system:health` | Accedere agli endpoint di salute e prontezza |
|
|
| `audit:read` | Visualizzare il log di audit ed elencare i ruoli |
|
|
| `compliance:manage` | Gestire il ciclo di vita e le funzionalità di conformità del GDPR; le operazioni utente distruttive rimangono limitate all'autorità |
|
|
| `webhooks:manage` | Configurare i webhook in uscita |
|
|
| `security:manage` | Gestire le impostazioni di sicurezza (allowlist IP, imposizione SSO) |
|
|
|
|
## Ruoli personalizzati {#custom-roles}
|
|
|
|
Gli amministratori con il permesso `security:manage` possono creare ruoli personalizzati tramite il pannello di amministrazione o l'API dei ruoli. L'elenco dei ruoli richiede `audit:read`.
|
|
|
|
### Creazione di un ruolo personalizzato {#creating-a-custom-role}
|
|
|
|
```bash
|
|
curl -X POST http://localhost:1349/api/v1/roles \
|
|
-H "Authorization: Bearer si_..." \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "reviewer",
|
|
"description": "Can use tools and view all files",
|
|
"permissions": ["tools:use", "files:own", "files:all", "settings:read"]
|
|
}'
|
|
```
|
|
|
|
I nomi dei ruoli devono avere da 2 a 30 caratteri, alfanumerici minuscoli con trattini e trattini bassi.
|
|
|
|
### I confini dell'amministrazione delegata {#delegated-administration-boundaries}
|
|
|
|
Tutte le 17 autorizzazioni possono essere delegate tramite ruoli personalizzati, ma un'autorizzazione amministrativa non rende tale ruolo equivalente al ruolo `admin` integrato. Le mutazioni dell'utente autorizzate da `users:manage`, le operazioni distruttive autorizzate da `compliance:manage` e la gestione dei ruoli personalizzati autorizzata da `security:manage` sono vincolate dall'attuale autorità dell'attore:
|
|
|
|
- I ruoli integrati seguono `admin` > `editor` > `user`; i ruoli personalizzati sono sotto i ruoli integrati.
|
|
- Le autorizzazioni del target devono essere contenute nelle autorizzazioni **effettive** dell'attore. Una chiave API con ambito pertanto non può esercitare le autorizzazioni omesse dal suo ambito.
|
|
- L'accesso allo strumento di un ruolo target deve essere contenuto dall'accesso allo strumento stesso dell'attore.
|
|
- Un account disabilitato viene confrontato con il suo ruolo originale quando tale ruolo viene registrato come `disabled:<original-role>`.
|
|
- L'eliminazione di un ruolo personalizzato richiede anche l'autorizzazione per assegnare il fallback `user` integrato; i membri disabili rimangono disabilitati come `disabled:user`.
|
|
|
|
Le credenziali globali e la configurazione sono più rigorose: l'emissione o la revoca del token SCIM e l'importazione della configurazione dell'istanza richiedono il ruolo `admin` integrato con completa autorità di amministrazione effettiva.
|
|
|
|
### Permessi a livello di strumento {#tool-level-permissions}
|
|
|
|
I ruoli personalizzati possono facoltativamente limitare quali strumenti gli utenti possono usare. Sono disponibili due modalità:
|
|
|
|
| Modalità | Comportamento | Requisito di licenza |
|
|
|---|---|---|
|
|
| `category` | Limita per modalità (immagine, video, audio, documento, file) | Nessuno (gratuito) |
|
|
| `tool` | Limita per ID del singolo strumento | Richiede la funzionalità enterprise `per_tool_permissions` |
|
|
|
|
Quando è impostata la modalità `tool` ma la funzionalità enterprise non è disponibile, SnapOtter si degrada in modo controllato e consente l'accesso a tutti gli strumenti.
|
|
|
|
```json
|
|
{
|
|
"name": "image-only",
|
|
"permissions": ["tools:use", "files:own"],
|
|
"toolPermissions": {
|
|
"mode": "category",
|
|
"allowed": ["image"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Eliminazione di un ruolo personalizzato {#deleting-a-custom-role}
|
|
|
|
Quando un ruolo personalizzato viene eliminato, tutti gli utenti ad esso assegnati vengono automaticamente riassegnati al ruolo `user`.
|
|
|
|
## Team {#teams}
|
|
|
|
I team raggruppano gli utenti per la gestione dell'archiviazione e della conservazione. Un team `Default` viene creato al primo avvio.
|
|
|
|
| Campo | Tipo | Descrizione |
|
|
|---|---|---|
|
|
| `name` | string | Nome univoco del team (1-50 caratteri) |
|
|
| `storageQuota` | number | Limite di archiviazione per team in byte (funziona senza enterprise) |
|
|
| `retentionHours` | number | Elimina automaticamente gli output dopo questo numero di ore (richiede `team_retention_overrides`, enterprise) |
|
|
| `legalHold` | boolean | Impedisce l'eliminazione automatica dei file dei membri del team (richiede `legal_hold`, enterprise) |
|
|
|
|
::: info
|
|
Il team `Default` non può essere eliminato. I team che hanno ancora membri non possono essere eliminati. Riassegna prima i membri.
|
|
:::
|
|
|
|
## Chiavi API {#api-keys}
|
|
|
|
Gli utenti possono generare chiavi API per l'accesso programmatico. Ogni chiave usa il prefisso `si_` e viene mostrata una sola volta al momento della creazione.
|
|
|
|
### Permessi con scope {#scoped-permissions}
|
|
|
|
Le chiavi API possono facoltativamente portare un array `permissions`. Quando è impostato, i permessi effettivi per una richiesta sono l'**intersezione** tra i permessi del ruolo dell'utente e i permessi con scope della chiave. Questo significa che una chiave API non può mai superare i permessi propri dell'utente.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:1349/api/v1/api-keys \
|
|
-H "Authorization: Bearer si_..." \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "CI pipeline key",
|
|
"permissions": ["tools:use", "files:own"],
|
|
"expiresAt": "2027-01-01T00:00:00Z"
|
|
}'
|
|
```
|
|
|
|
### Scadenza {#expiration}
|
|
|
|
Le chiavi accettano un timestamp `expiresAt` opzionale. Le chiavi scadute vengono rifiutate al momento dell'autenticazione.
|
|
|
|
## Log di audit {#audit-log}
|
|
|
|
SnapOtter registra gli eventi rilevanti per la sicurezza in un log di audit strutturato memorizzato nella tabella di database `audit_log`.
|
|
|
|
### Visualizzazione del log di audit {#viewing-the-audit-log}
|
|
|
|
```
|
|
GET /api/v1/audit-log?page=1&limit=50&action=LOGIN_FAILED&from=2026-01-01T00:00:00Z&to=2026-12-31T23:59:59Z
|
|
```
|
|
|
|
Richiede il permesso `audit:read`. Supporta la paginazione (`page`, `limit`) e i filtri (`action`, `ip`, `from`, `to`).
|
|
|
|
### Audit delle operazioni sugli strumenti {#tool-operation-auditing}
|
|
|
|
::: warning
|
|
Gli eventi `TOOL_EXECUTED` **non** vengono registrati per impostazione predefinita. Sono attivabili tramite uno di due percorsi:
|
|
|
|
1. Imposta l'impostazione di amministrazione `auditToolOperations` su `true`.
|
|
2. Possiedi una licenza attiva con la funzionalità `audit_export` (disponibile sia sui piani team sia enterprise).
|
|
|
|
Senza uno di questi, le singole esecuzioni degli strumenti non vengono registrate nel log di audit.
|
|
:::
|
|
|
|
### Esportazione {#exporting}
|
|
|
|
```
|
|
GET /api/v1/enterprise/audit/export?format=csv&from=2026-01-01T00:00:00Z
|
|
```
|
|
|
|
Richiede il permesso `audit:read` e la funzionalità enterprise `audit_export` (disponibile sia sui piani team sia enterprise). Supporta i formati CSV e JSON, filtrati per `action`, `actorId`, `targetType`, `targetId`, `from` e `to`.
|
|
|
|
### Firma resistente alla manomissione {#tamper-resistant-signing}
|
|
|
|
Quando è abilitata, ogni voce del log di audit viene firmata con un HMAC derivato da `DATA_ENCRYPTION_KEY`. Questo richiede:
|
|
|
|
1. Impostare `DATA_ENCRYPTION_KEY` nel tuo ambiente.
|
|
2. Abilitare l'impostazione di amministrazione `tamperResistantAudit`.
|
|
3. Una licenza enterprise con la funzionalità `tamper_resistant_audit`.
|
|
|
|
### Conservazione {#retention}
|
|
|
|
Imposta `AUDIT_RETENTION_DAYS` per eliminare automaticamente le voci vecchie. Il valore predefinito è `0`, il che significa che le voci vengono conservate a tempo indeterminato.
|
|
|
|
### Riferimento degli eventi {#event-reference}
|
|
|
|
| Evento | Categoria |
|
|
|---|---|
|
|
| `LOGIN_SUCCESS`, `LOGIN_FAILED` | Autenticazione |
|
|
| `OIDC_LOGIN_SUCCESS`, `OIDC_LOGIN_FAILED` | Autenticazione |
|
|
| `SAML_LOGIN_SUCCESS`, `SAML_LOGIN_FAILED` | Autenticazione |
|
|
| `LOGOUT` | Autenticazione |
|
|
| `USER_CREATED`, `USER_UPDATED`, `USER_DELETED` | Gestione utenti |
|
|
| `PASSWORD_CHANGED`, `PASSWORD_RESET` | Gestione utenti |
|
|
| `MFA_ENROLLED`, `MFA_DISABLED`, `MFA_VERIFIED`, `MFA_VERIFY_FAILED` | MFA |
|
|
| `MFA_CHALLENGE_ISSUED`, `MFA_RECOVERY_USED`, `MFA_RESET` | MFA |
|
|
| `ROLE_CREATED`, `ROLE_UPDATED`, `ROLE_DELETED` | Ruoli |
|
|
| `API_KEY_CREATED`, `API_KEY_DELETED` | Chiavi API |
|
|
| `SETTINGS_UPDATED`, `IP_ALLOWLIST_UPDATED` | Impostazioni |
|
|
| `FILE_UPLOADED`, `FILE_DELETED` | File |
|
|
| `TOOL_EXECUTED` | Strumenti (opt-in) |
|
|
| `SCIM_USER_PROVISIONED`, `SCIM_USER_UPDATED`, `SCIM_USER_DEPROVISIONED` | SCIM |
|
|
| `SCIM_GROUP_SYNCED` | SCIM |
|
|
| `LEGAL_HOLD_APPLIED`, `LEGAL_HOLD_RELEASED` | Conformità |
|
|
| `GDPR_EXPORT_INITIATED`, `GDPR_USER_PURGED`, `GDPR_TEAM_PURGED` | Conformità |
|
|
| `CONFIG_EXPORTED`, `CONFIG_IMPORTED` | Configurazione |
|
|
|
|
## Gestione delle sessioni {#session-management}
|
|
|
|
Le sessioni sono basate su cookie, controllate da `SESSION_DURATION_HOURS` (predefinito: 168 ore / 7 giorni).
|
|
|
|
### Le modifiche di ruolo invalidano le sessioni {#role-changes-invalidate-sessions}
|
|
|
|
Quando un amministratore cambia il ruolo di un utente, tutte le sessioni attive di quell'utente vengono eliminate. L'utente deve accedere di nuovo per acquisire i nuovi permessi.
|
|
|
|
### Protezioni di sicurezza {#safety-guards}
|
|
|
|
- **Protezione dell'ultimo amministratore**: l'ultimo amministratore rimasto non può essere retrocesso a un ruolo inferiore. L'API restituisce un errore se ci provi.
|
|
- **Prevenzione dell'auto-eliminazione**: gli amministratori non possono eliminare il proprio account tramite l'API.
|