Salta ai contenuti

Diagnostics e Verifica

Questa pagina fornisce una matrice di verifica UAT a livelli per convalidare la distribuzione della Difesa lato client end-to-end. Ogni caso di test segue la catena delle dipendenze dell’infrastruttura — dalla risoluzione DNS alla telemetria CSD — in modo da poter verificare sistematicamente che ogni componente funzioni correttamente.

Questi comandi sono l’equivalente API della Procedura dettagliata della console CSD — utilizzarli quando è necessario verificare dal terminale, automatizzare il monitoraggio o dimostrare le capacità di CSD senza l’interfaccia utente.

Configurare le variabili di ambiente come descritto in Automazione API — Configurazione dell’ambiente:

Terminal window
set -a && source .env && set +a

Tutti i comandi seguenti utilizzano il formato segnaposto xTOKENx. Sostituire con le proprie variabili di ambiente ($F5XC_API_TOKEN, $F5XC_NAMESPACE, ecc.) oppure utilizzare il modulo interattivo nella parte superiore della pagina.

Molti endpoint CSD richiedono timestamp epoch (secondi dall’epoch Unix). Questi one-liner calcolano i tempi di inizio/fine per gli intervalli più comuni.

Multipiattaforma (macOS + Linux):

Terminal window
# Ora corrente in secondi epoch
NOW=$(date +%s)
# 1 ora fa
START_1H=$(( NOW - 3600 ))
# 24 ore fa
START_24H=$(( NOW - 86400 ))
# 7 giorni fa
START_7D=$(( NOW - 604800 ))
# 30 giorni fa
START_30D=$(( NOW - 2592000 ))
PreimpostazioneSecondiEspressione shell
1 ora3.600$(( $(date +%s) - 3600 ))
24 ore86.400$(( $(date +%s) - 86400 ))
7 giorni604.800$(( $(date +%s) - 604800 ))
30 giorni2.592.000$(( $(date +%s) - 2592000 ))

Ogni test seguente adotta questa struttura:

CampoDescrizione
ID testNumero di livello + ID sequenziale (ad es., DNS-1, TLS-2)
Cosa dimostraIl fatto specifico sull’infrastruttura che viene verificato
ComandoComando curl o dig pronto per l’esecuzione
PASS / FAILOutput atteso per uno stato integro o non integro
CorrezioneLink alla sezione di configurazione o risoluzione dei problemi pertinente

Il DNS è il fondamento — se il dominio non viene risolto nell’IP VIP del bilanciatore del carico, nient’altro funziona.

Cosa dimostra: Il dominio viene risolto nell’indirizzo IP VIP del bilanciatore del carico.

Terminal window
dig +short xF5XC_DOMAINNAMEx A
RisultatoSignificato
PASS — IP VIP restituito (ad es., 72.19.3.185)Il dominio si risolve nell’IP virtuale del LB
FAIL — risposta vuotaRecord A DNS non configurato

Correzione: Automazione API — Passaggio 4: Configurare il DNS

Cosa dimostra: Il record di verifica ACME esiste per il provisioning automatico del certificato TLS.

Terminal window
dig +short _acme-challenge.xF5XC_DOMAINNAMEx CNAME
dig +short _acme-challenge.xF5XC_DOMAINNAMEx TXT
RisultatoSignificato
PASS — CNAME verso *.autocerts.ves.volterra.io. (DNS esterno)Il CNAME di verifica ACME è in atto
PASS — record TXT con valore del dominio (DNS gestito da F5 Distributed Cloud (F5 XC))Verifica ACME gestita dalla Piattaforma tramite record TXT
FAIL — entrambi vuotiRecord ACME non configurato; il certificato rimarrà in PreDomainChallengePending

Correzione: Per il DNS esterno, creare il CNAME: _acme-challenge.xF5XC_DOMAINNAMEx*.autocerts.ves.volterra.io. Per il DNS gestito da F5 XC, abilitare allow_http_lb_managed_records sulla zona DNS — vedere DNS-4. Vedere Automazione API — Passaggio 4.

Cosa dimostra: Se F5 XC è il provider DNS autorevole per il dominio radice.

Terminal window
dig +short NS xF5XC_ROOT_DOMAINx
RisultatoSignificato
Contiene ns1.f5clouddns.com e ns2.f5clouddns.comDNS gestito da F5 XC — i record possono essere creati automaticamente
Altri nameserverDNS esterno — i record devono essere creati manualmente

Correzione: Automazione API — Rilevare l’autorità DNS

Cosa dimostra: La zona DNS di F5 XC consente la creazione automatica di record per i bilanciatori del carico (solo DNS gestito da F5 XC).

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/dns/namespaces/system/dns_zones/xF5XC_ROOT_DOMAINx" \
| jq '.spec.primary.allow_http_lb_managed_records'
RisultatoSignificato
PASStrueLa Piattaforma creerà automaticamente i record A e ACME per i LB
FAILfalse o nullI record gestiti sono disabilitati; abilitarli tramite aggiornamento della zona

Correzione: Automazione API — Opzione A: DNS gestito da F5 XC


Dopo la risoluzione DNS, il bilanciatore del carico deve avere un certificato TLS valido.

Cosa dimostra: Il certificato TLS automatico è stato emesso sul LB HTTPS.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq '.spec.cert_state'
RisultatoSignificato
PASS"CertificateValid" o "AutoCertRenewing"Il certificato è valido e attivo
WARN"DomainChallengePending" o "DomainChallengeStarted"Verifica ACME in corso — attendere 5–10 minuti
INFO"AutoCertDomainRateLimited"Limite di frequenza di Let’s Encrypt raggiunto — previsto negli ambienti demo, non influisce sul LB HTTP
FAIL"PreDomainChallengePending"Record di verifica ACME mancante — vedere DNS-2

Correzione: Assicurarsi che il record di verifica ACME sia in atto (CNAME per DNS esterno, o abilitare i record gestiti per DNS F5 XC). Il provisioning del certificato richiede 5–10 minuti dopo la configurazione del record. Se bloccato oltre 15 minuti, vedere Certificato bloccato — Ricreazione pulita. Se il limite di frequenza è raggiunto, il LB HTTP non è interessato.

Cosa dimostra: Il certificato copre il dominio previsto e mostra le informazioni sulla scadenza. Applicabile solo al LB HTTPS.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq '{
cert_state: .spec.cert_state,
auto_cert_info: .spec.auto_cert_info
}'
RisultatoSignificato
PASSauto_cert_info contiene dns_records e metadati del certificatoDettagli del provisioning del certificato disponibili
FAILauto_cert_info è null o vuotoCertificato non ancora fornito

Cosa dimostra: Il certificato TLS è valido e l’handshake viene completato lato client. Applicabile solo quando il LB HTTPS ha un certificato valido.

Terminal window
curl -sv "https://xF5XC_DOMAINNAMEx/" 2>&1 \
| grep -E 'SSL connection|subject:|expire date:|issuer:'
RisultatoSignificato
PASS — mostra SSL connection using TLSv1.3, soggetto e scadenza validiTLS end-to-end funzionante
FAIL — connessione rifiutata o errore di certificatoVerificare la risoluzione DNS e lo stato del certificato; se il limite di frequenza è raggiunto, utilizzare HTTP

Cosa dimostra: Il bilanciatore del carico HTTPS riporta il target ACME corretto per la convalida del certificato.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq '{
vip_ip: .spec.dns_info[0].ip_address,
acme_target: .spec.auto_cert_info.dns_records
}'
RisultatoSignificato
PASSvip_ip e acme_target popolatiI record DNS possono essere verificati rispetto a questi valori
FAIL — valori nullIl LB potrebbe non avere https_auto_cert configurato

Il bilanciatore del carico deve essere in uno stato pronto e correttamente configurato.

Cosa dimostra: Il bilanciatore del carico HTTP (primario) è completamente operativo e accetta traffico.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '.spec.state'
RisultatoSignificato
PASS"VIRTUAL_HOST_READY"Il LB è operativo
FAIL"VIRTUAL_HOST_PENDING_A_RECORD"Record A DNS non configurato — vedere DNS-1

Correzione: LB bloccato in VIRTUAL_HOST_PENDING_A_RECORD

Cosa dimostra: Il bilanciatore del carico HTTP è configurato per il/i dominio/i corretto/i.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '.spec.domains'
RisultatoSignificato
PASS — l’array contiene il proprio FQDN (ad es., ["app.example.com"])Il LB è configurato per il dominio previsto
FAIL — dominio mancante o erratoAggiornare la specifica del LB con il dominio corretto

Cosa dimostra: La Difesa lato client è abilitata sul bilanciatore del carico con la policy di iniezione JS corretta.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '{
csd_enabled: (if .spec.client_side_defense then true else false end),
js_policy: .spec.client_side_defense.policy
}'
RisultatoSignificato
PASScsd_enabled: true con js_insert_all_pages nella policyCSD attivo con iniezione JS su tutte le pagine
FAILcsd_enabled: falseCSD non configurato sul LB

Correzione: Riferimento API — Abilitare CSD su un bilanciatore del carico

Cosa dimostra: Il bilanciatore del carico fa riferimento al pool di origine corretto con peso e priorità attesi.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '.spec.default_route_pools[] | {
pool: .pool.name,
namespace: .pool.namespace,
weight: .weight,
priority: .priority
}'
RisultatoSignificato
PASS — mostra il nome del pool di origine con peso/prioritàIl LB instrada verso il backend corretto
FAIL — pool vuoto o erratoAggiornare la configurazione default_route_pools del LB

LB-5: Stato di distribuzione (condizioni per sito)

Sezione intitolata “LB-5: Stato di distribuzione (condizioni per sito)”

Cosa dimostra: Il bilanciatore del carico è distribuito e riporta condizioni di integrità su tutti i siti.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '{
state: .spec.state,
dns_info: .spec.dns_info,
host_name: .spec.host_name
}'
RisultatoSignificato
PASSstate è VIRTUAL_HOST_READY, dns_info popolatoLB completamente distribuito con VIP assegnato
FAIL — stato in attesa o dns_info vuotoProblema DNS o certificato che blocca la distribuzione

Cosa dimostra: Snapshot completo di entrambe le configurazioni del LB per il debug.

LB HTTP (primario):

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '{
name: .metadata.name,
state: .spec.state,
domains: .spec.domains,
csd_enabled: (if .spec.client_side_defense then true else false end),
route_pools: [.spec.default_route_pools[] | .pool.name],
advertise: (if .spec.advertise_on_public_default_vip then "public_default_vip" else "custom" end)
}'

LB HTTPS (secondario — include lo stato del certificato):

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq '{
name: .metadata.name,
state: .spec.state,
cert_state: .spec.cert_state,
domains: .spec.domains,
csd_enabled: (if .spec.client_side_defense then true else false end),
route_pools: [.spec.default_route_pools[] | .pool.name]
}'

Il pool di origine definisce i server backend verso cui il bilanciatore del carico instrada il traffico.

Cosa dimostra: Il pool di origine esiste con il server backend, la porta e l’algoritmo di LB corretti.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/xF5XC_ORIGIN_POOLx" \
| jq '{
name: .metadata.name,
origin_servers: [.spec.origin_servers[] | {
ip: .public_ip.ip,
labels: .labels
}],
port: .spec.port,
lb_algorithm: .spec.loadbalancer_algorithm,
endpoint_selection: .spec.endpoint_selection
}'
RisultatoSignificato
PASS — mostra IP, porta e algoritmo correttiPool di origine configurato correttamente
FAIL404 o valori erratiPool di origine mancante o non configurato correttamente

Correzione: Automazione API — Passaggio 2: Creare il pool di origine

Cosa dimostra: Se TLS è configurato per la connessione tra il LB e il Server di origine.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/xF5XC_ORIGIN_POOLx" \
| jq '{
tls_config: (if .spec.no_tls then "no_tls (plaintext)" elif .spec.use_tls then "use_tls (encrypted)" else "unknown" end)
}'
RisultatoSignificato
no_tls (plaintext)Il LB si connette all’origine tramite HTTP (previsto per la demo Juice Shop)
use_tls (encrypted)Il LB si connette all’origine tramite HTTPS

Cosa dimostra: Il pool di origine ha il controllo di integrità corretto collegato (se applicabile).

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/xF5XC_ORIGIN_POOLx" \
| jq '.spec.healthcheck'
RisultatoSignificato
PASS — array con riferimento al controllo di integrità (nome, namespace, tipo)Il controllo di integrità è collegato
OK — array vuoto []Nessun controllo di integrità (accettabile — CSD non ne richiede uno)
FAIL — era atteso un controllo di integrità ma l’array è vuotoIl controllo di integrità non è stato trovato al momento della creazione — vedere Controllo di integrità non collegato

Cosa dimostra: Il Server di origine è raggiungibile lato client (non verifica il percorso dal LB all’origine).

Terminal window
curl -s -o /dev/null -w '%{http_code}' \
"http://xF5XC_ORIGIN_IPx:xF5XC_ORIGIN_PORTx/"
RisultatoSignificato
PASS200 (o altro codice HTTP valido)Il server di origine risponde
FAIL000 o connessione rifiutataServer di origine irraggiungibile da questa rete

I controlli di integrità monitorano la disponibilità del backend. Sono opzionali per CSD ma utili per le distribuzioni in produzione.

Cosa dimostra: Il controllo di integrità esiste con il tipo, il percorso, la tempistica e le soglie corrette.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks/xF5XC_HC_NAMEx" \
| jq '{
name: .metadata.name,
type: (if .spec.http_health_check then "HTTP" elif .spec.tcp_health_check then "TCP" else "unknown" end),
path: .spec.http_health_check.path,
expected_status: .spec.http_health_check.expected_status_codes,
timeout: .spec.timeout,
interval: .spec.interval,
unhealthy_threshold: .spec.unhealthy_threshold,
healthy_threshold: .spec.healthy_threshold
}'
RisultatoSignificato
PASS — mostra tipo HTTP con percorso / e 200 attesoControllo di integrità configurato correttamente
FAIL — risposta 404Il controllo di integrità non esiste (potrebbe essere stato saltato — vedere Fase 1 Passaggio 1)

Cosa dimostra: Enumera tutti i controlli di integrità nel namespace per verificare la denominazione e il conteggio.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks" \
| jq -r '
["NAME", "NAMESPACE", "DESCRIPTION"],
(.items[] | [
.name,
.namespace,
(.description | if length == 0 then "—" else . end)
])
| @tsv' | column -t

CSD deve essere abilitato a livello di tenant e avere configurato il tag di iniezione JavaScript.

Cosa dimostra: CSD è configurato e abilitato per il tenant.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/status" \
| jq '{isConfigured, isEnabled}'
RisultatoSignificato
PASS — entrambi trueCSD è attivo per questo tenant
FAILisConfigured: falseCSD non abilitato a livello di tenant — contattare l’amministratore F5 XC
FAILisEnabled: falseCSD configurato ma non attivo

Cosa dimostra: Il tag di iniezione JavaScript di CSD è generato e pronto per l’iniezione.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/js_configuration" \
| jq '{has_script_tag: (.scriptTag | length > 0)}'
RisultatoSignificato
PASShas_script_tag: trueIl tag di iniezione JS è configurato
FAILhas_script_tag: falseNessun tag script — verificare che CSD sia abilitato e che un dominio protetto sia registrato

Cosa dimostra: Mostra il tag script completo per la verifica o l’iniezione manuale.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/js_configuration" \
| jq '.scriptTag'

Cosa dimostra: Il dominio radice è registrato come dominio protetto CSD nel tenant.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains" \
| jq '.items[] | {name, namespace, description}'
RisultatoSignificato
PASS — mostra un elemento con name non vuotoIl dominio è protetto
FAIL — gli elementi hanno campi name e namespace vuotiNessun dominio protetto registrato — vedere Fase 1 Passaggio 6

CSD-5: Verifica dell’iniezione JS in tempo reale

Sezione intitolata “CSD-5: Verifica dell’iniezione JS in tempo reale”

Cosa dimostra: Il JavaScript di CSD viene effettivamente iniettato nelle risposte delle pagine servite dal bilanciatore del carico.

Terminal window
curl -s "http://xF5XC_DOMAINNAMEx/" \
| grep -oE '(zeronaught|shape)\.com[^"]*' | head -1
RisultatoSignificato
PASS — restituisce un frammento URL zeronaught.com o shape.com (ad es., zeronaught.com/__imp_apg__/js/...)Il JavaScript CSD viene iniettato nelle pagine
FAIL — output vuotoJS non iniettato — verificare LB-3 e CSD-1

Verificare che il traffico in tempo reale stia raggiungendo il bilanciatore del carico e venga elaborato correttamente.

Cosa dimostra: Il traffico sta raggiungendo il bilanciatore del carico. Zero risultati significa che non arriva traffico.

Terminal window
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"start_time": "'"$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-24H +%Y-%m-%dT%H:%M:%SZ)"'",
"end_time": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"
}' \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs/aggregation" \
| jq '{total_requests: .total_hits}'
RisultatoSignificato
PASStotal_requests è una stringa non zero (ad es., "380")Il traffico scorre attraverso il LB
FAIL"0" o nessun datoNessun traffico raggiunge il LB — verificare DNS-1 e LB-1

Cosa dimostra: Il dettaglio dei codici di stato delle risposte rivela i pattern di errore.

Terminal window
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"start_time": "'"$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-24H +%Y-%m-%dT%H:%M:%SZ)"'",
"end_time": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'",
"sort": "DESCENDING",
"limit": 100
}' \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs" \
| jq -r '
[.logs[] | fromjson | .rsp_code_class]
| group_by(.) | map({class: .[0], count: length})
| sort_by(-.count)
| ["STATUS_CLASS", "COUNT"], (.[] | [.class, .count])
| @tsv' | column -t

Output atteso per un sito integro:

STATUS_CLASS COUNT
2xx 82
downstream_remote_disconnect 18
RisultatoSignificato
PASS — maggioranza 2xxIl sito serve risposte con successo
WARN — alto conteggio 4xxErrori client (URL errati, risorse mancanti)
FAIL — alto conteggio 5xxErrori server — verificare l’integrità del server di origine

La classe downstream_remote_disconnect indica che il client ha chiuso la connessione prima del completamento della risposta (comune per richieste di long-polling o aggiornamento WebSocket).

Cosa dimostra: Le singole richieste vengono registrate con i campi corretti.

Terminal window
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"start_time": "'"$(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-1H +%Y-%m-%dT%H:%M:%SZ)"'",
"end_time": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'",
"sort": "DESCENDING",
"limit": 10
}' \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs" \
| jq -r '
["TIMESTAMP", "METHOD", "PATH", "STATUS", "SRC_IP"],
(.logs[] | fromjson | [.["@timestamp"], .method, .req_path, .rsp_code, .src_ip])
| @tsv' | column -t

Cosa dimostra: I log di accesso confermano che il JavaScript CSD viene iniettato nelle risposte.

Terminal window
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"start_time": "'"$(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-1H +%Y-%m-%dT%H:%M:%SZ)"'",
"end_time": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'",
"sort": "DESCENDING",
"limit": 20
}' \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs" \
| jq '[.logs[] | fromjson | select(.csd_js_injection == "true")] | length as $injected |
{injected_count: $injected, total_sampled: 20}'
RisultatoSignificato
PASSinjected_count > 0Il JS CSD viene iniettato nelle risposte delle pagine
FAILinjected_count: 0JS non iniettato — verificare CSD-1 e LB-3

Cosa dimostra: Una richiesta completa fluisce dal client attraverso DNS, LB e origine e restituisce una risposta valida.

Terminal window
curl -sv "http://xF5XC_DOMAINNAMEx/" 2>&1 \
| grep -E 'Connected to|< HTTP|< content-type'
RisultatoSignificato
PASS — mostra connessione, HTTP 200 e content-typeL’intero stack è operativo
FAIL — connessione rifiutata o errore DNSIniziare il debug al Livello 1: DNS

Questi comandi interrogano gli stessi dati visualizzati nel dashboard della Console CSD, nell’elenco degli script, nei campi modulo e nelle viste di rete.

Cosa dimostra: CSD sta rilevando e catalogando gli script in esecuzione sul dominio protetto.

Terminal window
NOW=$(date +%s)
START=$(( NOW - 604800 ))
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{
\"startTime\": \"${START}\",
\"endTime\": \"${NOW}\"
}" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts" \
| jq -r '
["SCRIPT", "RISK", "STATUS", "FIELDS", "USERS"],
(.scripts[] | [
(.script_name | if length > 50 then .[:47] + "..." else . end),
.risk_level,
.status,
(.form_fields_read // 0),
(.affected_users_count // 0)
])
| @tsv' | column -t
RisultatoSignificato
PASS — script elencati con livelli di rischioCSD sta monitorando attivamente gli script
FAIL — array vuotoVedere Risoluzione dei problemi: Array degli script vuoto

Cosa dimostra: CSD ha rilevato i domini di origine degli script e li ha classificati per stato.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/detected_domains" \
| jq '{
summary: {
action_needed: .domain_summary.actionNeededCount.count,
mitigated: .domain_summary.mitigatedDomains.count,
allowed: .domain_summary.allowedDomains.count,
total: .domain_summary.totalDomains.count
},
domains: [.domains_list[] | {
domain: .domain,
category: .category,
status: .status,
first_seen: (.firstSeenDate | tonumber | todate),
latest_seen: (.latestSeenDate | tonumber | todate)
}]
}'
RisultatoSignificato
PASStotal > 0 con domini elencatiCSD sta monitorando i domini degli script
WARNaction_needed > 0Alcuni domini necessitano di revisione
FAIL — risposta vuotaNessun dato di telemetria — verificare CSD-5

Cosa dimostra: Mostra la distribuzione dei domini consentiti vs. mitigati e se la policy è coerente.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/detected_domains" \
| jq '{
action_needed: .domain_summary.actionNeededCount.count,
mitigated: .domain_summary.mitigatedDomains.count,
allowed: .domain_summary.allowedDomains.count,
total: .domain_summary.totalDomains.count,
domains_needing_action: [.domains_list[] | select(.status == "AN") | .domain]
}'
RisultatoSignificato
PASSaction_needed: 0Tutti i domini sono stati rivisti e classificati
WARNaction_needed > 0I domini elencati in domains_needing_action richiedono revisione

Cosa dimostra: CSD ha rilevato i campi modulo che gli script stanno leggendo, con classificazione della sensibilità.

Terminal window
NOW=$(date +%s)
START=$(( NOW - 604800 ))
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/formFields?startTime=${START}&endTime=${NOW}" \
| jq -r '
["FIELD", "SENSITIVITY", "SCRIPTS"],
(.form_fields[] | [
.name,
.analysis,
(.scripts_count // 0)
])
| @tsv' | column -t
RisultatoSignificato
PASS — campi modulo elencati con sensibilitàCSD sta monitorando l’accesso ai campi modulo
INFO — array vuotoNessun campo modulo rilevato (previsto se non ci sono form sul sito)

Cosa dimostra: Informazioni dettagliate su uno script specifico, inclusi rischio, comportamenti e interazioni di rete.

Prima, ottenere un ID script da TEL-1, quindi interrogare i suoi dettagli:

Terminal window
SCRIPT_ID="your-script-id"
# Panoramica (livello di rischio, tipo, dominio di origine)
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts/${SCRIPT_ID}/dashboard" \
| jq '{script_name, risk_level, type, source_domain, status}'
# Comportamenti nel tempo
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts/${SCRIPT_ID}/behaviors" \
| jq '.behaviors'
# Interazioni di rete (domini con cui lo script comunica)
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts/${SCRIPT_ID}/networkInteractions" \
| jq '.network_interactions'

Cosa dimostra: Elenca gli utenti impattati da uno script specifico, mostrando l’estensione dell’esposizione.

Terminal window
SCRIPT_ID="your-script-id"
NOW=$(date +%s)
START=$(( NOW - 604800 ))
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{
\"startTime\": \"${START}\",
\"endTime\": \"${NOW}\"
}" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts/${SCRIPT_ID}/affectedUsers" \
| jq -r '
["IP_ADDRESS", "DEVICE_ID", "GEO", "CHANNEL", "USER_AGENT"],
(.affected_users[] | [
.ip_address,
(.device_id | if length > 12 then .[:12] + "..." else . end),
.geolocation,
.channel,
(.user_agent | if length > 30 then .[:27] + "..." else . end)
])
| @tsv' | column -t

TEL-7: Conteggio degli script per livello di rischio

Sezione intitolata “TEL-7: Conteggio degli script per livello di rischio”

Cosa dimostra: Distribuzione aggregata del rischio su tutti gli script rilevati.

Terminal window
NOW=$(date +%s)
START=$(( NOW - 604800 ))
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{
\"startTime\": \"${START}\",
\"endTime\": \"${NOW}\"
}" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts" \
| jq '[.scripts[] | .risk_level] | group_by(.) | map({risk_level: .[0], count: length}) | sort_by(-.count)'
RisultatoSignificato
PASS — tutti No RiskNessuno script rischioso rilevato
WARN — presenti Low Risk o High RiskRivedere gli script segnalati in TEL-5

Cosa dimostra: I dati di telemetria CSD sono recenti, confermando il monitoraggio attivo.

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/detected_domains" \
| jq '{
total_domains: .domain_summary.totalDomains.count,
latest_update: (.domain_summary.totalDomains.lastUpdated // "unknown"),
most_recent_domain: (.domains_list | sort_by(.latestSeenDate) | last | {
domain: .domain,
latest_seen: (.latestSeenDate | tonumber | todate)
})
}'
RisultatoSignificato
PASSlatest_seen è nelle ultime 24 oreLa telemetria sta raccogliendo attivamente dati
WARNlatest_seen è più vecchio di 24 oreIl traffico potrebbe essersi interrotto o l’elaborazione CSD è in ritardo

Eseguire un singolo comando che verifica tutti gli indicatori di integrità critici su ogni livello e produce una tabella di riepilogo:

Terminal window
echo "=== CSD Verification Dashboard ==="
echo ""
# Livello 1: DNS
DNS_A=$(dig +short xF5XC_DOMAINNAMEx A | head -1)
DNS_ACME=$(dig +short _acme-challenge.xF5XC_DOMAINNAMEx CNAME | head -1)
# Livelli 2-3: LB + TLS
LB=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http")
LB_HTTPS=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https")
LB_STATE=$(echo "$LB" | jq -r '.spec.state // "UNKNOWN"')
CERT_STATE=$(echo "$LB_HTTPS" | jq -r '.spec.cert_state // "UNKNOWN"')
CSD_ON_LB=$(echo "$LB" | jq -r 'if .spec.client_side_defense then "ENABLED" else "DISABLED" end')
DOMAINS=$(echo "$LB" | jq -r '.spec.domains | join(", ")')
ROUTE_POOL=$(echo "$LB" | jq -r '[.spec.default_route_pools[] | .pool.name] | join(", ")')
# Livello 6: stato CSD
CSD=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/status")
CSD_CONFIGURED=$(echo "$CSD" | jq -r '.isConfigured // false')
CSD_ENABLED=$(echo "$CSD" | jq -r '.isEnabled // false')
# Livello 6: configurazione JS
JS_TAG=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/js_configuration" \
| jq -r 'if (.scriptTag | length) > 0 then "PRESENT" else "MISSING" end')
# Livello 7: traffico (ultime 24h)
TRAFFIC=$(curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{
\"start_time\": \"$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-24H +%Y-%m-%dT%H:%M:%SZ)\",
\"end_time\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"
}" \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs/aggregation" \
| jq -r '.total_hits // "0"')
printf "%-28s %s\n" "CHECK" "STATUS"
printf "%-28s %s\n" "----------------------------" "----------------------------"
printf "%-28s %s\n" "[DNS] A Record" "${DNS_A:-NOT_FOUND}"
printf "%-28s %s\n" "[DNS] ACME CNAME" "${DNS_ACME:-NOT_FOUND}"
printf "%-28s %s\n" "[TLS] Certificate" "$CERT_STATE"
printf "%-28s %s\n" "[LB] State" "$LB_STATE"
printf "%-28s %s\n" "[LB] Domains" "$DOMAINS"
printf "%-28s %s\n" "[LB] Route Pool" "$ROUTE_POOL"
printf "%-28s %s\n" "[LB] CSD on LB" "$CSD_ON_LB"
printf "%-28s %s\n" "[CSD] Configured (tenant)" "$CSD_CONFIGURED"
printf "%-28s %s\n" "[CSD] Enabled" "$CSD_ENABLED"
printf "%-28s %s\n" "[CSD] JS Script Tag" "$JS_TAG"
printf "%-28s %s\n" "[Traffic] Requests (24h)" "$TRAFFIC"

CampoTipoDescrizione
@timestampstringaTimestamp della richiesta (ISO 8601). Notare il prefisso @ — accedere con .["@timestamp"] in jq
methodstringaMetodo HTTP (GET, POST, ecc.)
req_pathstringaPercorso URI della richiesta
rsp_codestringaCodice di stato HTTP della risposta come stringa (ad es., "200", "404")
rsp_code_classstringaClasse del codice di stato (2xx, 3xx, 4xx, 5xx, o downstream_remote_disconnect)
src_ipstringaIndirizzo IP sorgente del client
dst_ipstringaIndirizzo IP di destinazione (VIP)
domainstringaValore dell’intestazione Host della richiesta
user_agentstringaStringa User-Agent del client
rsp_sizestringaDimensione del corpo della risposta in byte (restituita come stringa)
req_sizestringaDimensione del corpo della richiesta in byte (restituita come stringa)
duration_with_data_tx_delaystringaDurata totale della richiesta in secondi (restituita come stringa, ad es., "0.024219")
csd_js_injectionstringa"true" quando il JavaScript CSD è stato iniettato (presente solo quando attivo)
CampoEndpointDescrizione
isConfiguredstatusCSD abilitato a livello di tenant
isEnabledstatusCSD attivo per questo namespace
scripts[]scriptsArray di oggetti script rilevati
.script_namescriptsURL completo del file JavaScript
.risk_levelscriptsLivello di rischio (No Risk, Low Risk, High Risk)
.statusscriptsAN (Action Needed) o NA (No Action Needed)
.form_fields_readscriptsNumero di campi modulo letti dallo script
.affected_users_countscriptsNumero di utenti/sessioni unici interessati
domain_summarydetected_domainsConteggi per stato: .actionNeededCount.count, .mitigatedDomains.count, .allowedDomains.count, .totalDomains.count (ciascuno ha .count e .lastUpdated)
domains_list[]detected_domainsArray di oggetti dominio rilevati con .domain, .status, .category, .firstSeenDate, .latestSeenDate (secondi epoch come stringhe)
form_fields[]formFieldsArray di oggetti campo modulo rilevati
.analysisformFieldsClassificazione della sensibilità (Sensitive, Not Sensitive)

Se TV-1 restituisce 0:

  1. Verificare la risoluzione DNS — controllare che il dominio si risolva nel VIP del LB:

    Terminal window
    dig +short xF5XC_DOMAINNAMEx A

    Se vuoto, il DNS non è configurato. Vedere Automazione API — Passaggio 4.

  2. Verificare lo stato del LB — il bilanciatore del carico deve essere in VIRTUAL_HOST_READY:

    Terminal window
    curl -s \
    -H "Authorization: APIToken xF5XC_API_TOKENx" \
    "xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
    | jq '.spec.state'
  3. Inviare una richiesta di test — generare traffico per confermare la connettività end-to-end:

    Terminal window
    curl -sv "http://xF5XC_DOMAINNAMEx/" 2>&1 | head -20

    Cercare una risposta HTTP riuscita. Utilizzare https:// solo se il certificato del LB HTTPS è valido.

Se DNS-4 restituisce false, la creazione automatica dei record è disabilitata anche se F5 XC è il provider DNS autorevole. Si tratta di una configurazione errata comune che causa l’assenza sia del record A che del CNAME ACME, bloccando il bilanciatore del carico nel raggiungimento di VIRTUAL_HOST_READY e l’emissione del certificato.

Per abilitare i record gestiti, aggiornare la configurazione della zona DNS impostando allow_http_lb_managed_records: true. Vedere Automazione API — Opzione A: DNS gestito da F5 XC per la chiamata API.

Il bilanciatore del carico è in attesa di un record A DNS che punti al suo VIP. Vedere LB bloccato in VIRTUAL_HOST_PENDING_A_RECORD per i passaggi dettagliati di risoluzione.

Il certificato TLS automatico richiede un record di verifica ACME. Il metodo dipende dal provider DNS:

DNS gestito da F5 XC: Abilitare allow_http_lb_managed_records sulla zona DNS (DNS-4). La piattaforma crea automaticamente un record di verifica ACME basato su TXT nel gruppo di record RR x-ves-io-managed. Se il certificato rimane bloccato dopo aver abilitato i record gestiti, eliminare e ricreare il bilanciatore del carico per avviare una nuova richiesta di certificato.

DNS esterno: Creare un record CNAME presso il provider DNS:

_acme-challenge.xF5XC_DOMAINNAMEx CNAME *.autocerts.ves.volterra.io

Verificare che il record esista:

Terminal window
dig +short _acme-challenge.xF5XC_DOMAINNAMEx CNAME
dig +short _acme-challenge.xF5XC_DOMAINNAMEx TXT

Se entrambi sono vuoti, il record ACME non è configurato. Il provisioning del certificato richiede 5–10 minuti dopo che il record è in atto. Verificare lo stato di errore del LB per errori specifici di convalida ACME:

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '[.status[]? | select(.virtual_host_status != null) | .virtual_host_status.error_description]'

CSD deve essere abilitato a livello di tenant da un amministratore F5 XC. Si tratta di un’impostazione a livello di tenant che non può essere configurata tramite l’API del namespace. Contattare l’amministratore per abilitare la Difesa lato client.

Se TEL-1 restituisce un array vuoto:

  1. Verificare il dominio protetto — CSD monitora gli script solo sui domini registrati:

    Terminal window
    curl -s \
    -H "Authorization: APIToken xF5XC_API_TOKENx" \
    "xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains" \
    | jq '.items[] | {name, namespace}'
  2. Verificare l’iniezione JS — confermare che il tag script CSD venga iniettato nelle pagine:

    Terminal window
    curl -s "http://xF5XC_DOMAINNAMEx/" | grep -oE '(zeronaught|shape)\.com[^"]*' | head -1

    Se non c’è corrispondenza, il JavaScript CSD non viene iniettato. Verificare che il LB abbia client_side_defense abilitato.

  3. Attendere il tempo di elaborazione — dopo aver abilitato CSD per la prima volta o aver registrato un nuovo dominio protetto, il rilevamento degli script può richiedere 5–15 minuti. Generare traffico verso il sito e attendere prima di ricontrollare.

PeriodoOffset epochISO 8601 (Linux)ISO 8601 (macOS)
1 ora$(( $(date +%s) - 3600 ))date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZdate -u -v-1H +%Y-%m-%dT%H:%M:%SZ
24 ore$(( $(date +%s) - 86400 ))date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZdate -u -v-24H +%Y-%m-%dT%H:%M:%SZ
7 giorni$(( $(date +%s) - 604800 ))date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZdate -u -v-7d +%Y-%m-%dT%H:%M:%SZ
30 giorni$(( $(date +%s) - 2592000 ))date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZdate -u -v-30d +%Y-%m-%dT%H:%M:%SZ
LivelloTestCosa copre
1. Risoluzione DNSDNS-1 fino a DNS-4Record A, CNAME ACME, autorità nameserver, record gestiti
2. Certificato TLSTLS-1 fino a TLS-4Stato certificato, dettagli certificato, handshake in tempo reale, target ACME
3. Bilanciatore del carico HTTPLB-1 fino a LB-6Stato, domini, flag CSD, pool di route, distribuzione, riepilogo
4. Pool di origineOP-1 fino a OP-4Configurazione, modalità TLS, associazione HC, connettività origine
5. Controllo di integritàHC-1 fino a HC-2Configurazione HC, elenco di tutti gli HC
6. Configurazione CSDCSD-1 fino a CSD-5Stato tenant, tag JS, domini protetti, iniezione in tempo reale
7. Verifica del trafficoTV-1 fino a TV-5Conteggio richieste, codici di stato, campioni, JS nei log, test E2E
8. Telemetria CSDTEL-1 fino a TEL-8Script, domini, policy, campi modulo, analisi approfondita, utenti, rischio, aggiornamento
DiagnosticaEndpointMetodoFormato ora
Conteggio richieste/api/data/namespaces/\{ns\}/access_logs/aggregationPOSTISO 8601
Codici di stato/api/data/namespaces/\{ns\}/access_logsPOSTISO 8601
Richieste recenti/api/data/namespaces/\{ns\}/access_logsPOSTISO 8601
Stato LB/api/config/namespaces/\{ns\}/http_loadbalancers/\{name\}GETNessuno
Pool di origine/api/config/namespaces/\{ns\}/origin_pools/\{name\}GETNessuno
Controllo di integrità/api/config/namespaces/\{ns\}/healthchecks/\{name\}GETNessuno
Zona DNS/api/config/dns/namespaces/system/dns_zones/\{zone\}GETNessuno
Stato CSD/api/shape/csd/namespaces/\{ns\}/statusGETNessuno
Configurazione JS/api/shape/csd/namespaces/\{ns\}/js_configurationGETNessuno
Domini protetti/api/shape/csd/namespaces/\{ns\}/protected_domainsGETNessuno
Elenco script/api/shape/csd/namespaces/\{ns\}/scriptsPOSTSecondi epoch
Domini rilevati/api/shape/csd/namespaces/\{ns\}/detected_domainsGETNessuno
Campi modulo/api/shape/csd/namespaces/\{ns\}/formFieldsGETSecondi epoch (parametri query)
Dettagli script/api/shape/csd/namespaces/\{ns\}/scripts/\{id\}/dashboardGETNessuno
Comportamenti script/api/shape/csd/namespaces/\{ns\}/scripts/\{id\}/behaviorsGETNessuno
Rete script/api/shape/csd/namespaces/\{ns\}/scripts/\{id\}/networkInteractionsGETNessuno
Utenti interessati/api/shape/csd/namespaces/\{ns\}/scripts/\{id\}/affectedUsersPOSTSecondi epoch