Kaptain Hook

2017-11-14

Mit Minio habe ich einen eigenen S3 Server realisiert. Minio unterstützt für Bucket Notifications diverse Endpunkte und neben den ganzen hipster Datenbanken Gedöhns kann man auch einfache Webhooks konfigurieren. So habe ich mir ein System zusammen gebaut, bei dem Aktivitäten im Bucket an einen Webhook Server weitergegeben werden, der daraufhin eine Slack Nachricht erzeugt. Ich bin kein uneingeschränkter Fan von Slack, da ich die Daten nicht kontrollieren kann, jedoch ist das der einzigste Push Dienst der bei mir geräteübergreifend funktioniert.

Webhook Server

Auf Github habe ich einen Webhook Server gefunden, der enorm flexibel ist. Mit einer Json Datei erstellt man sich einen Endpunkt, der mit einem Regelwerk noch feiner granuliert werden kann, der dann ein Shell Script ausfĂĽhrt.

$ cat hooks.json
[
  {
    "id": "s3-monitor",
    "execute-command": "~/run/webhook/scripts/s3.sh",
    "command-working-directory": "~/run/webhook",
    "pass-arguments-to-command": [{
        "source": "payload",
        "name":"EventType"
        },{
        "source":"payload",
        "name":"Key"
        }
    ]
  }
]

In obigen Beispiel wird aus dem Payload gegen <SERVER>:<PORT>/<PREFIX>/s3-monitor die Werte EventType und Key als Argumente an das s3.sh Script ĂĽbergeben.

Slack

Damit externe Dienste mit Slack kommunizieren können, bietet Slack so genannte Incoming Webhooks an. Man konfiguriert sich einfach einen neuen Incoming Webhook und erhält einen Token in Form einer URL, gegen die man feuern kann.

curl \
    -X POST \
    -s \
    --data-urlencode "payload={ \
        \"channel\": \"#monitor\", \
        \"username\": \"Dein Monitor\", \
        \"pretext\": \"wichtige Nachricht\", \
        \"color\": \"danger\", \
        \"icon_emoji\": \":bell:\", \
        \"text\": \"ne, ist doch nicht so schlimm\" \
    }" \
    https://hooks.slack.com/services/TXXXXXXX/BXXXXXX/XXXXXXXXXXXXXXXXXX

Minio

Die Konfigurationsdatei von Minio enthält bereits alle nötigen Einträge, die man nur noch an seine Bedürfnisse anpassen muss.

$cat config.json
"webhook": {
	"1": {
		"enable": true,
		"endpoint": "http://<SERVER>:<PORT>/<PREFIX>/s3-monitor"
    }
}

Und die entsprechenden Events fĂĽr das Bucket setzen.

$mc events add <SERVER>/<BUCKET> arn:minio:sqs::1:webhook

Slack Script

Das s3.sh Script nimmt zwei Argumente auf, EventType welches die Bucket Aktion beschreibt und Key enthält den zugehörigen Dateinamen.

$cat s3.sh
#!/bin/sh
if [ -z "$2" ]; then
  exit 0
fi
IFS=':' read -a a <<< "$1"
color="good"
case ${a[2]} in
    "Put")
        color="good"
    ;;
    "Delete")
        color="danger"
    ;;
    "Get")
        color="#439FE0"
    ;;
    "Head")
        exit 0
    ;;
    *)
        color="warning"
    ;;
esac
/usr/bin/curl \
    -X POST \
    -s \
    --data-urlencode "payload={ \
        \"channel\": \"#s3\", \
        \"username\": \"Monitor\", \
        \"pretext\": \"S3 | $(date +"%F %T %Z %:::z")\", \
        \"color\": \"$color\", \
        \"icon_emoji\": \":bell:\", \
        \"text\": \"$1 - $2\" \
    }" \
    https://hooks.slack.com/services/TXXXXXXX/BXXXXXX/XXXXXXXXXXXXXXXXXX

Result

Am Ende fällt dann so eine Slack Nachricht heraus.