On décrit d’ordinaire l’appliance Notakey comme un serveur d’authentification :
une connexion a lieu, une demande push arrive sur le téléphone, l’utilisateur
approuve. Mais le même canal de distribution accepte un second type de message
(une simple notification) et cela transforme l’appliance en quelque chose de
plus général : un canal de messagerie push vers chaque téléphone enrôlé dans
votre service, appelable depuis n’importe quel script avec un unique curl.
any script ──HTTPS──▶ appliance API ──push──▶ enrolled phone
(cron, monitoring, /notify Notakey Authenticator
home automation…)
Contrairement à une demande d’authentification, une notification ne réclame aucune approbation : elle apparaît simplement sur le téléphone, adressée à un nom d’utilisateur, et elle est délivrée d’un coup à tous les appareils enrôlés de l’utilisateur. Elle remplace ainsi sans effort les endroits où vous auriez sinon branché des SMS (coût par message, expéditeur usurpable) ou des e-mails (ignorés jusqu’à lundi) : surveillance des tâches, alertes d’astreinte, annonces au personnel.
Prérequis
- Une appliance Notakey en fonctionnement (cloud ou sur site) avec un service et au moins un utilisateur dont le téléphone est enrôlé. Si vous exploitez déjà la 2FA VPN ou le SSO, vous disposez de tout cela : les notifications passent par le même service que vos connexions, ou par un service distinct si vous souhaitez une autre identité visuelle.
- Des identifiants d’accès à l’API (un client ID et un client secret), créés dans le tableau de bord sous Access credentials (voir l’étape 1 ci-dessous).
curletjqsur n’importe quelle machine capable de joindre l’appliance. C’est là toute la liste des dépendances.
Étape 1 – Créer des identifiants d’accès à l’API
Dans le tableau de bord, ouvrez Access credentials et créez un identifiant pour vos scripts. Deux points comptent ici :
- Les scopes. Accordez
urn:notakey:notify: c’est le scope dont ce guide a besoin.urn:notakey:authexiste également, pour créer des demandes d’authentification (approbation/refus) ; ne l’ajoutez que si le même identifiant doit faire les deux. Un identifiant limité ànotifyne peut être détourné pour déclencher des approbations de connexion : gardez donc la liste des scopes aussi courte que la tâche le permet. - Vous recevez un client ID et un client secret. Le secret autorise l’envoi de messages à tout le monde dans le service : traitez-le comme un mot de passe root.
Étape 2 – L’échanger contre un jeton, et maintenir le jeton à jour
L’appel de notification lui-même n’utilise pas le client secret : il s’appuie sur un jeton d’accès de type bearer obtenu via le flux standard OAuth 2.0 « client credentials ». Les jetons d’accès ont délibérément une durée de vie courte : prévoyez de les renouveler environ une fois par heure, sans quoi vos scripts finiront par échouer sur des erreurs d’autorisation, quelque part après avoir tourné sans problème pendant 59 minutes.
Le renouvellement du jeton relève donc d’une tâche cron, et non d’une étape d’installation :
#!/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
Le script contient le client secret et écrit le jeton : verrouillez donc les deux :
chmod 700 /usr/local/bin/ntk-token-renew # root-only, holds the secret
install -m 600 /dev/null /etc/notakey/api.token
Si vous avez également accordé urn:notakey:auth, demandez-le sous la forme d’un
jeton distinct dans un fichier distinct (même appel, scope=urn:notakey:auth)
plutôt qu’un seul jeton portant les deux scopes ; ainsi, les scripts de
notification ne détiennent jamais un jeton capable de créer des approbations de
connexion.
Étape 3 – Un seul script de notification réutilisable
Tout le reste de ce guide appelle ce script unique. Il prend un nom d’utilisateur, un titre et un corps de message :
#!/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"
Remplacez ntk.example.com par l’adresse de votre appliance et <service-id>
par l’UUID du service indiqué dans le tableau de bord. Testez :
ntk-notify j.doe "Test" "If you can read this on your phone, the channel works."
La notification push arrive dans l’application Notakey Authenticator (celle-là même que l’utilisateur possède déjà pour ses connexions) : il n’y a donc rien de nouveau à installer, à expliquer ou à faire valider par la gestion des appareils mobiles.
Étape 4 – L’appeler depuis n’importe quoi
Dès lors que le canal tient en une ligne, les cas d’usage s’accumulent. En voici quelques-uns qui tournent en production aujourd’hui :
Une sauvegarde qui rend des comptes. La panne silencieuse par excellence : des sauvegardes qui ont cessé de fonctionner il y a des mois sans que personne ne s’en aperçoive. Deux lignes à la fin de la tâche y remédient :
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
Espace disque, expiration de certificat, tout ce que cron peut vérifier :
#!/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
Une annonce à l’ensemble du personnel. L’API s’adresse à un nom d’utilisateur par appel : un message à toute l’entreprise revient donc à parcourir votre liste d’utilisateurs en boucle : fenêtres de maintenance, fermetures de bureaux, avis d’incident :
while read -r user; do
ntk-notify "$user" "IT maintenance" "VPN unavailable Saturday 06:00–08:00 — planned appliance upgrade."
done < users.txt
Le prix spot de l’électricité, deux fois toutes les deux heures. Tout ce qui mérite une notification n’est pas forcément une panne. Celui-ci s’exécute depuis cron et indique à l’utilisateur ce que coûtera l’heure d’électricité suivante (pratique pour décider quand lancer le lave-vaisselle) :
#!/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 désigne ce qui récupère vos données de marché : une API de bourse,
un CSV en cache. L’essentiel, c’est la distribution du message, pas sa source.)
Deux options documentées méritent d’être connues pour les messages récurrents
comme celui-ci : ajouter un champ fingerprint à la charge utile fait qu’un
nouvel envoi portant la même empreinte met à jour le message existant au lieu
d’en empiler un nouveau ; ainsi, un afficheur de prix reste une seule
notification, et non quarante par jour. Et "type": "sms" envoie le même message
sous forme de SMS, si l’utilisateur dispose d’un numéro de mobile renseigné (un
canal de secours pour celui dont le téléphone a perdu l’application).
La machine à laver a fini. Une prise connectée qui surveille la consommation, une automatisation Home Assistant, un script qui interroge un compteur, quel que soit ce qui détecte la fin du cycle, la notification reste la même ligne unique. Exemple anodin, habitude bien réelle : dès l’instant où envoyer une notification ne coûte rien, on notifie pour tout.
Ce à quoi ce canal convient, et ce à quoi il ne convient pas
Comparé au SMS, le côté destinataire est bien plus solide : un SMS arrive sur le combiné qui détient à cet instant la carte SIM, sous un nom d’expéditeur que n’importe qui peut falsifier, tandis qu’une notification Notakey n’atterrit que dans l’application Authenticator, sur des appareils ayant mené à bien l’enrôlement cryptographique dans votre service. Personne ne peut s’abonner de lui-même à vos alertes, et personne ne peut usurper l’expéditeur.
Une limite qu’il faut assumer, tirée directement de la
documentation de l’API : le corps de la
notification n’est pas chiffré de bout en bout, comme toute notification push
mobile, il transite par les services de notification d’Apple et de Google et
reste lisible par les applications disposant d’un accès aux notifications sur
l’appareil. Traitez donc le corps du message comme un message de pager, et non
comme une enveloppe scellée : « La sauvegarde a échoué sur l’hôte X » convient ;
un mot de passe ou une clé d’API, non. Lorsque vous devez transmettre quelque
chose de véritablement secret, utilisez plutôt une demande d’authentification
(urn:notakey:auth) : là, la notification push n’est qu’un coup frappé à la
porte, et la charge utile est récupérée par l’application via son canal
authentifié par certificat une fois que l’utilisateur a répondu.
Où cela s’inscrit
Si l’appliance protège déjà votre VPN ou vos applications, les notifications sont une capacité gratuite que vous n’exploitez pas : même service, même application, mêmes identifiants d’API, un point d’accès supplémentaire. Et si vous payez jusqu’ici une passerelle SMS pour vos alertes internes, ceci la remplace pour chaque destinataire qui porte un téléphone enrôlé.
Guides connexes
- 2FA VPN avec RADIUS : la configuration complète du proxy d’authentification (le versant authentification de la même appliance)
- Linux SSH 2FA avec pam_radius (des approbations par téléphone pour les serveurs sur lesquels tournent vos scripts)
- Documentation de l’API (l’ensemble de la surface REST, y compris les requêtes sur les appareils et les demandes d’authentification)