Un playbook non è uno script che lanci: è un oggetto che il Playbook Engine esegue come servizio indipendente dall’Application Engine, in modo asincrono. Da qui la reattività della GUI mentre girano decine di automazioni, e il fatto che l’ordine degli step non sia sempre quello che leggi sul canvas.
Chi esegue davvero il playbook
Per impostazione predefinita ogni playbook gira nel contesto della Playbook Appliance (PBA). I permessi che contano non sono i tuoi: sono quelli della PBA. Se il playbook estrae indicatori da un incident, alla PBA servono almeno Read sul modulo Incidents e Create su Indicators, altrimenti lo step fallisce anche se tu quei record li vedi benissimo dalla GUI. Lo step Set API Keys cambia contesto a metà flusso: da lì in avanti valgono i privilegi di quella chiave per tutti gli step successivi, non solo per quello immediatamente dopo. È anche l’unico modo per far scrivere record a un playbook il cui Custom API Endpoint è configurato senza autenticazione.
Sull’RBAC del modulo Playbooks l’esame è secco: Create, Read e Update per creare; Read e Update per modificare gli step; solo Read per vedere il designer senza aprire gli step; Delete per cancellare; Execute per lanciarli. Execute è un permesso a sé — con Read e Update modifichi un playbook e non riesci a eseguirlo.
I playbook vivono dentro le Collection e il nome deve essere unico dentro la collection. Nascono Active e Public; rendendolo Private e assegnandolo a dei team lo mostri nel menu Execute solo a quei team. Dettaglio che vale il punto intero: esportando una collection, o anche un singolo playbook privato, tutto torna Public e gli owner si svuotano — dopo l’import devi rimettere Private e riassegnare i team a mano.
I sei trigger e cosa lasciano nell’ambiente
I tipi di trigger sono sei: On Create, On Update, On Delete, Custom API Endpoint, Referenced e Manual. Il trigger è sempre il primo step, e finché non lo salvi il designer non mostra nemmeno gli step disponibili.
I tre trigger di database accettano condizioni (AND oppure OR, mutuamente esclusivi) e gruppi annidati. On Update ha l’operatore Is Changed e un comportamento da ricordare alla lettera: una singola azione di update fa scattare il playbook una volta sola anche se colleghi più record o cambi più campi insieme, e un bulk edit lo fa scattare una volta, ma più inline edit lo fanno scattare più volte. Su una relazione On Update scatta solo se il collegamento è nato aggiornando il record su cui è definito il trigger.
Il Custom API Endpoint accetta soltanto POST, non è discoverable nella definizione JSON-LD/Hydra (devi conoscerne il nome) e offre tre autenticazioni: token o API key (default), Basic, oppure nessuna. Il Manual Trigger ha due modalità di esecuzione e il default è Run once for all selected records: se lo scenario descrive un’azione che deve girare una volta per ogni record selezionato, quel default va cambiato di proposito.
Gli input sono consolidati sotto vars.input: i record stanno in vars.input.records per i trigger di database e per il manuale, il corpo della richiesta API nei parametri con chiave api_body. La vecchia vars.request.data è deprecata dalla 6.0.0.
{{ vars.input.records[0].sourceIP }}
{{ vars.input.params['api_body'] }}
Gli step e il disegno del flusso
Find Records preleva 30 record di default, non tutti: per averne di più devi alzare Record Limit, entro il tetto di 5000. Include Correlated Records è disattivo per prestazioni, e senza spuntarlo non puoi selezionare campi dei record correlati. Ingest Bulk Feed è molto più veloce di Create Record sui feed di threat intel, ma paga un prezzo che l’esame adora: i playbook con trigger On Create e On Update non scattano sui record inseriti o aggiornati con Ingest Bulk Feed. Genera inoltre un solo audit per lotto e record non replicabili in multi-tenancy.
Reference a Playbook richiama un playbook che ha un trigger Referenced. Il campo Parent Data Reference ha tre valori — Full ENV, Pass Input Record Only e Not Required — e il default è Not Required: il figlio non vede nulla del padre finché non lo cambi. Spuntando Run Asynchronously il padre prosegue e l’output del figlio diventa inutilizzabile. Al contrario uno step Wait dentro un figlio rende quel figlio sincrono: il padre aspetta.
Ingestione: dal wizard ai playbook
Il wizard di Data Ingestion genera i playbook al posto tuo. Le modalità sono tre: Notification Based (IMAP, Exchange, Syslog), Schedule Based (QRadar, ServiceNow, Anomali, con polling ogni 5 minuti di default) e App Push, dove un add-on installato sulla sorgente spinge i dati verso FortiSOAR. Regola operativa che è anche una trappola: per una stessa sorgente ne configuri una sola — attivando notifica e schedule insieme entrambi tirano gli stessi dati e perdi record per conflitto.
Serve il Solution Pack SOAR Framework, più Read e Update su Connectors e Create, Read, Update ed Execute su Playbooks (e su Schedules se pianifichi). Nel field mapping i campi diventano Jinja: la chiave normale è vars.sourcedata, ma se il connettore supporta insert o upsert in bulk diventa vars.item.
{{vars.sourcedata["destination_networks"]}}
{{vars.item["destination_networks"]}}
Le picklist si mappano anche per intervalli, con due punti fra i numeri, valori numerici separati da spazio e stringhe separate da virgola.