Come avere un Vulnerability Assessment di Docker automatizzato con Grype
Scopri come automatizzare la sicurezza del tuo ambiente Docker: una guida pratica per configurare scansioni periodiche con Grype e ricevere report sulle vulnerabilità tramite Apprise.
Mantenere i propri container aggiornati non è sempre sinonimo di sicurezza. Spesso, le immagini Docker che utilizziamo nei nostri homelab o in produzione si portano dietro vulnerabilità note (CVE) che possono essere sfruttate da malintenzionati. Controllare manualmente ogni immagine è un lavoro proibitivo, ma la sicurezza non può essere un'attività sporadica.
In questo articolo vedremo come implementare un sistema di Vulnerability Assessment automatizzato utilizzando Grype, un tool di scansione open-source estremamente rapido ed efficace. Integreremo il tutto con systemd per la pianificazione e Apprise per ricevere report dettagliati direttamente sui nostri canali di messaggistica preferiti (come Telegram, e-mail e Discord tramite Apprise).
Il risultato sarà una notifica periodica ricevuta comodamente sul nostro canale preferito, come la seguente (in questo caso, ricevuta tramite email):



Prerequisiti
Per raggiungere il nostro obiettivo creeremo uno script bash che verrà richiamato regolarmente tramite un servizio systemd, il quale si occuperà poi di eseguire il Vulnerability Assessment lanciando Grype verso ogni container.
Infine, riceveremo il Vulnerability Assessment tramite Apprise.
Pertanto, per utilizzare lo script con le sue funzionalità previste, sono necessari:
- Un macchina con Docker installato, e l'accesso amministrativo su questa macchina
- Una istanza di Apprise API (può anche essere installato sulla stessa macchina Docker) con i canali di notifica già configurati
Non hai Apprise? Segui la mia guida per scoprire come installarlo ed utilizzarlo!


Installazione
- Per prima cosa, installiamo Grype
curl -sSfL https://get.anchore.io/grype | sudo sh -s -- -b /usr/local/bin
- Installiamo il pacchetto jq, che verrà utilizzato dallo script per contare le vulnerabilità all'interno del report
sudo apt install jq
- Adesso, creiamo lo script
sudo mkdir /opt/grype-scan
sudo touch /opt/grype-scan/grype-scan.sh
- Modifichiamolo ed incolliamoci il contenuto dello script che ho preparato
sudo nano grype-scan.sh
grype-scan.sh:
#!/usr/bin/env bash
set -euo pipefail
APPRISE_URL="http://indirizzo.IP.di.Apprise:porta/notify/apprise"
APPRISE_TAG="Grype"
HOST_NAME="Docker (192.168.1.x)"
REPORT_FILE="$(mktemp /tmp/grype-report-XXXXXX.txt)"
TMP_VULN_LIST="$(mktemp /tmp/grype-vulnlist-XXXXXX.txt)"
# Header
{
echo "=== Report vulnerabilità immagini Docker ==="
echo "Host: $HOST_NAME"
echo "Data/Ora: $(date '+%Y-%m-%d %H:%M:%S')"
echo "Container running: $(docker ps --format '{{.ID}}' | wc -l)"
echo
} > "$REPORT_FILE"
# Scansione container
docker ps --format '{{.ID}} {{.Names}} {{.Image}}' | while read -r cid cname img; do
img_id=$(docker inspect --format '{{.Image}}' "$cid")
echo "Scansiono $cname ($cid)..." >&2
echo "===== $cname ($cid) =====" >> "$REPORT_FILE"
echo "Image: $img" >> "$REPORT_FILE"
echo "Image ID: $img_id" >> "$REPORT_FILE"
GRYPE_JSON=$(mktemp /tmp/grype-json-XXXXXX.json)
if grype "docker:$img_id" -o json --only-fixed=false -q > "$GRYPE_JSON" 2>>"$REPORT_FILE"; then
:
fi
VCOUNT=$(jq '.matches | length' "$GRYPE_JSON" 2>/dev/null || echo 0)
echo "Vulnerabilità trovate: $VCOUNT" >> "$REPORT_FILE"
echo >> "$REPORT_FILE"
grype "docker:$img_id" --only-fixed=false -q >> "$REPORT_FILE" 2>>"$REPORT_FILE"
echo >> "$REPORT_FILE"
echo "$cname:$VCOUNT" >> "$TMP_VULN_LIST"
rm -f "$GRYPE_JSON"
done
# Costruzione body
BODY="Scansione settimanale delle immagini Docker su $HOST_NAME
Sono state trovate le seguenti vulnerabilità:
"
if [[ -s "$TMP_VULN_LIST" ]]; then
while IFS=':' read -r cname vcount; do
BODY+=$'\n'"- ${cname}: ${vcount} vulnerabilità"
done < "$TMP_VULN_LIST"
else
BODY+=$'\n'"- Nessun container analizzato."
fi
BODY+=$'\n\n'"Per maggiori dettagli consulta il report completo in allegato."
echo "Invio report ad Apprise..." >&2
# Invio notifica
curl -sS -X POST \
-F "body=$BODY" \
-F "title=Grype - Scansione periodica delle Vulnerabilità di Docker ($HOST_NAME)" \
-F "tags=$APPRISE_TAG" \
-F "attachments=@$REPORT_FILE;name=grype-full-report.txt" \
"$APPRISE_URL"
echo "Fatto. Report: $REPORT_FILE" >&2
- Modifichiamo lo script valorizzando le tre variabili presenti all'inizio del file:
- APPRISE_URL: l'URL verso cui inviare le chiamate POST ad Apprise. Per ottenerlo, basta aprire la pagina web di Apprise API ed andare in Configuration Manager → Overview.
- APPRISE_TAG: il tag di apprise da utilizzare per inviare la notifica. Tutti i canali di notifica che hanno configurato questo tag su Apprise verranno utilizzati per l'invio della notifica.
- HOST_NAME: questa variabile ha valore puramente cosmetico e viene usata nella notifica per identificare a quale macchina Docker è riferito il Vulnerability Assessment.
- Rendiamo lo script eseguibile
sudo chmod +x /opt/grype-scan/grype-scan.sh
Adesso creiamo il Servizio ed il Timer di systemd per avviare automaticamente lo script
- Creiamo entrambi i file
touch /etc/systemd/system/grype-scan.service
touch /etc/systemd/system/grype-scan.timer
- Impostiamo il servizio
[Unit]
Description=Scansione periodica delle immagini Docker con Grype
[Service]
Type=oneshot
ExecStart=/opt/grype-scan/grype-scan.sh
User=root
Group=root
[Install]
WantedBy=multi-user.target
- Impostiamo il timer (in questo esempio, ogni Lunedì alle 09:30)
[Unit]
Description=Esegui grype-scan ogni lunedì alle 09:30
[Timer]
OnCalendar=Mon *-*-* 09:30:00
Persistent=true
[Install]
WantedBy=timers.target
- Infine, attiviamo il timer
sudo systemctl daemon-reload
sudo systemctl enable grype-scan.timer
sudo systemctl start grype-scan.timer

Funzionamento
Lo script grype-scan.sh contenuto in questa guida effettua i seguenti passaggi:
- Ottiene la lista dei container di Docker che sono attualmente avviati
- Per ogni container rilevato, ottiene l'ID dell'immagine
- Avvia Grype e gli fa analizzare l'immagine associata al container
- Se vengono rilevate vulnerabilità, le aggiunge al report
- Una volta che ha analizzato tutti i container e le relative immagini, invia una notifica tramite Apprise
Al primo avvio, Grype dovrà scaricare il database delle vulnerabilità che utilizzerà poi per effettuare il VA delle immagini di Docker. Pertanto, la prima esecuzione di Grype potrebbe impiegare più tempo del normale.

Conclusioni
Adesso che abbiamo un VA completamente automatizzato su regime periodico, possiamo impiegare il tempo che abbiamo risparmiato nella rilevazione delle vulnerabilità, spendendolo nelle riparazioni.
Le immagini di Docker "pronte all'uso" che sono facilmente reperibili su directory come le awesome-list e selfh.st sono infatti un modo fantastico per tirare su con poco sforzo alcuni dei progetti migliori
Questo script può ovviamente essere personalizzato per modificarne il comportamento, per esempio per effettuare il Vulnerability Assessment di macchine remote, oppure anche delle immagini scaricate ma non istanziate.
