Notakey Authentication Appliance opisuje się zwykle jako serwer
uwierzytelniania: następuje logowanie, na telefonie pojawia się żądanie push,
użytkownik je zatwierdza. Ten sam kanał dostarczania przyjmuje jednak jeszcze
drugi typ wiadomości, zwykłe powiadomienie, i zamienia appliance w coś
bardziej uniwersalnego: kanał wiadomości push do każdego telefonu
zarejestrowanego w Państwa usłudze, wywoływany z dowolnego skryptu jednym
poleceniem curl.
any script ──HTTPS──▶ appliance API ──push──▶ enrolled phone
(cron, monitoring, /notify Notakey Authenticator
home automation…)
W odróżnieniu od żądania uwierzytelnienia powiadomienie nie prosi o zatwierdzenie: po prostu pojawia się na telefonie, zaadresowane do nazwy użytkownika, i trafia jednocześnie na wszystkie zarejestrowane urządzenia danej osoby. Dzięki temu staje się gotowym zamiennikiem tam, gdzie inaczej podłączaliby Państwo SMS (koszt za wiadomość, łatwy do podrobienia nadawca) lub e-mail (przeczytany dopiero w poniedziałek): monitorowanie zadań, powiadomienia dla dyżurnych, ogłoszenia dla pracowników.
Wymagania
- Działający Notakey Appliance (w chmurze lub on-premise) z usługą i co najmniej jednym użytkownikiem, który zarejestrował telefon. Jeśli już korzystają Państwo z VPN 2FA lub SSO, mają Państwo to wszystko: powiadomienia idą przez tę samą usługę co logowania albo przez osobną, jeśli potrzebny jest inny branding.
- Dane logowania do API (client ID i client secret), utworzone w panelu w sekcji Access credentials (patrz krok 1 poniżej).
curlijqna czymkolwiek, co ma dostęp do appliance. To cała lista zależności.
Krok 1: Utworzenie danych logowania do API
W panelu należy otworzyć Access credentials i utworzyć dane logowania dla skryptów. Liczą się tu dwie rzeczy:
- Zakresy (scopes). Należy przyznać
urn:notakey:notify. To zakres, którego wymaga ten przewodnik. Istnieje teżurn:notakey:auth, służący do tworzenia żądań uwierzytelnienia (zatwierdź/odrzuć); należy go dodać tylko wtedy, gdy te same dane logowania mają robić jedno i drugie. Danych z uprawnieniem wyłącznie do powiadomień nie da się nadużyć do wywoływania zatwierdzeń logowania, więc listę zakresów warto utrzymywać tak krótką, jak pozwala na to zadanie. - Otrzymają Państwo client ID oraz client secret. Secret uprawnia do wysyłania wiadomości do wszystkich w usłudze, należy go więc traktować jak hasło roota.
Krok 2: Wymiana danych na token i utrzymywanie tokena świeżym
Samo wywołanie notify nie używa client secret. Korzysta z tokena dostępu typu bearer, uzyskanego standardowym grantem OAuth 2.0 typu client-credentials. Tokeny dostępu są celowo krótkotrwałe: należy zaplanować odnawianie mniej więcej raz na godzinę, w przeciwnym razie Państwa skrypty w pewnym momencie zaczną kończyć się błędami autoryzacji, akurat wtedy, gdy przez 59 minut działały bez zarzutu.
Odnawianie tokena jest więc zadaniem cron, a nie jednorazowym krokiem konfiguracyjnym:
#!/bin/bash
# /usr/local/bin/ntk-token-renew — cron: 0 * * * *
curl -s -X POST https://ntk.example.com/api/token \
-d 'grant_type=client_credentials&client_id=<client-id>&client_secret=<client-secret>&scope=urn:notakey:notify' \
| jq -r .access_token > /etc/notakey/api.token
Skrypt zawiera client secret i zapisuje token, więc należy zabezpieczyć jedno i drugie:
chmod 700 /usr/local/bin/ntk-token-renew # root-only, holds the secret
install -m 600 /dev/null /etc/notakey/api.token
Jeśli przyznali Państwo także urn:notakey:auth, warto poprosić o niego jako osobny token
do osobnego pliku (to samo wywołanie, scope=urn:notakey:auth), zamiast
jednego tokena z oboma zakresami; skrypty powiadomień nigdy nie będą wtedy
trzymać tokena, którym dałoby się utworzyć zatwierdzenia logowania.
Krok 3: Jeden skrypt notify wielokrotnego użytku
Wszystko dalej w tym przewodniku wywołuje ten jeden skrypt. Przyjmuje on nazwę użytkownika, tytuł oraz treść wiadomości:
#!/bin/bash
# /usr/local/bin/ntk-notify <username> <title> <description>
token=$(cat /etc/notakey/api.token)
curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer $token" \
-d '{ "username": "'"$1"'", "title": "'"$2"'", "description": "'"$3"'", "type": "notification" }' \
"https://ntk.example.com/api/v3/services/<service-id>/notify"
ntk.example.com należy zastąpić adresem swojego appliance, a <service-id> –
numerem UUID usługi z panelu. Następnie należy to przetestować:
ntk-notify j.doe "Test" "If you can read this on your phone, the channel works."
Push trafia do aplikacji Notakey Authenticator, tej samej, której użytkownik używa już do logowań, więc nie ma niczego nowego do zainstalowania, wytłumaczenia ani przepchnięcia przez system zarządzania urządzeniami mobilnymi.
Krok 4: Wywołanie skądkolwiek
Gdy kanał sprowadza się do jednej linijki, zastosowania zbierają się same. Kilka takich, które działają dziś produkcyjnie:
Zadanie kopii zapasowej, które melduje o wyniku. Klasyczna cicha awaria: kopie, które przestały działać wiele miesięcy temu i nikt tego nie zauważył. Dwie linijki na końcu zadania rozwiązują problem:
if ! /usr/local/bin/backup-run; then
ntk-notify admin "Backup FAILED" "Nightly backup on $(hostname) exited with an error — check /var/log/backup.log"
fi
Miejsce na dysku, wygasające certyfikaty – wszystko, co potrafi sprawdzić cron:
#!/bin/bash
# cron: 0 8 * * *
used=$(df --output=pcent / | tail -1 | tr -dc '0-9')
if [ "$used" -gt 90 ]; then
ntk-notify admin "Disk warning" "Root filesystem on $(hostname) is at ${used}% — time to clean up."
fi
Ogłoszenie do każdego pracownika. API adresuje jedną nazwę użytkownika na wywołanie, więc wiadomość dla całej firmy to pętla po liście użytkowników (okna serwisowe, zamknięcia biura, powiadomienia o awariach):
while read -r user; do
ntk-notify "$user" "IT maintenance" "VPN unavailable Saturday 06:00–08:00 — planned appliance upgrade."
done < users.txt
Ceny spot energii, dwie ceny co dwie godziny. Nie wszystko, co warto wypchnąć jako push, jest awarią. Ten skrypt uruchamia się z crona i mówi użytkownikowi, ile będzie kosztować prąd w najbliższej godzinie, co przydaje się przy decyzji, kiedy włączyć zmywarkę:
#!/bin/bash
# cron: 5 * * * * — sends on even hours, 06–23 only
hour=$(( $(date +%H) + 1 ))
next=$(( hour + 1 ))
if [ "$hour" -gt 5 ] && [ "$hour" -lt 24 ] && (( $(date +%H) % 2 == 0 )); then
ntk-notify "$1" "Electricity" \
"Next hour: $(spot_price "$hour")€/kWh. After that: $(spot_price "$next")€/kWh."
fi
(spot_price to cokolwiek, co pobiera Państwa dane rynkowe: API giełdy, plik
CSV z pamięci podręcznej. Istotne jest dostarczenie, a nie źródło.)
Dla powtarzających się wiadomości, jak ta powyżej, warto znać dwa
udokumentowane dodatki: dodanie pola fingerprint do ładunku sprawia, że
ponowne wysłanie z tym samym odciskiem aktualizuje istniejącą wiadomość,
zamiast piętrzyć kolejną; dzięki temu ticker cen pozostaje jednym
powiadomieniem, a nie czterdziestoma dziennie. Z kolei "type": "sms" wysyła
tę samą wiadomość jako SMS, o ile użytkownik ma zdefiniowany numer telefonu:
kanał zapasowy dla kogoś, kto stracił aplikację na telefonie.
Pralka skończyła. Inteligentne gniazdko śledzące pobór mocy, automatyzacja w Home Assistant, skrypt odpytujący licznik – cokolwiek wykryje koniec cyklu, powiadomieniem pozostaje ta sama linijka. Błahy przykład, a nawyk prawdziwy: gdy wysłanie pusha nic nie kosztuje, powiadamia się o wszystkim.
Do czego ten kanał się nadaje (a do czego nie)
W porównaniu z SMS strona odbiorcy jest znacznie mocniejsza: SMS trafia na dowolny aparat, w którym akurat tkwi karta SIM, od nadawcy, którego nazwę każdy może podrobić, podczas gdy powiadomienie Notakey ląduje wyłącznie w aplikacji Authenticator na urządzeniach, które ukończyły kryptograficzną rejestrację w Państwa usłudze. Nikt nie zapisze się sam do Państwa alertów i nikt nie podrobi nadawcy.
Jedno uczciwe ograniczenie, prosto z
dokumentacji API: sama treść
powiadomienia nie jest szyfrowana end-to-end: jak każdy mobilny push,
przechodzi przez usługi push Apple i Google i jest czytelna dla aplikacji
mających na urządzeniu dostęp do powiadomień. Treść wiadomości należy więc
traktować jak komunikat na pager, a nie jak zapieczętowaną kopertę: „Kopia zapasowa na
hoście X nie powiodła się” jest w porządku; hasło lub klucz API – już nie. Gdy
trzeba dostarczyć coś naprawdę tajnego, należy użyć zamiast tego żądania
uwierzytelnienia (urn:notakey:auth). Tam push jest jedynie zapukaniem do
drzwi, a właściwy ładunek aplikacja pobiera po reakcji użytkownika własnym
kanałem uwierzytelnianym certyfikatem.
Gdzie to pasuje
Jeśli appliance chroni już Państwa VPN lub aplikacje, powiadomienia to funkcja, którą mają Państwo za darmo i z której nie korzystają: ta sama usługa, ta sama aplikacja, te same dane logowania do API, jeden dodatkowy punkt końcowy. A jeśli do tej pory płacili Państwo za bramkę SMS na potrzeby wewnętrznych alertów, ten kanał zastępuje ją dla każdego odbiorcy, który nosi przy sobie zarejestrowany telefon.
Powiązane przewodniki
- VPN 2FA z RADIUS – pełna konfiguracja proxy uwierzytelniania: strona uwierzytelniania tego samego appliance
- Linux SSH 2FA z pam_radius: zatwierdzanie z telefonu dla serwerów, na których działają Państwa skrypty
- Dokumentacja API: pełny interfejs REST, w tym zapytania o urządzenia i żądania uwierzytelnienia