Unsere interne API für SMS-Versand

Bei uns gibt es einige Anwendungen, die SMS verschicken:

  • Icinga verschickt Monitoring-Alerts
  • ein 2FA-Service verschickt Login-TANs
  • Jira verschickt Alerts für bestimmte Tickets

Bis vor kurzem haben wir dafür Hardware-Maschinen mit Mobilfunk-Modems betrieben.

Das hatte leider einige Nachteile:

  • Diese Maschinen brauchen spezialisierte Hardware und können nicht virtualisiert werden
  • Aufwand bei Updates; insbesondere hatten wir einen gepatchten gsmmuxd

Unser Ziel war es, diese Maschinen loszuwerden. Um weiterhin SMS versenden zu können, brauchten wir also einen externen Dienstleister mit einer API.

Die neue API

Wir wollten uns bei der neuen Lösung nicht fest an einen Anbieter binden. In den Begriffen der Softwareentwicklung würde man sagen: wir wollen Loose Coupling.

Deswegen haben wir eine interne API geschaffen, die zwischen unseren Anwendungen und dem Versender steht. Diese API ist ein stabiles Interface; worüber eine SMS versendet wird ist dann nur ein Implementierungsdetail.

Es ist eine einfache HTTP-API mit nur einem einzigen Endpoint: dem Versand einer SMS:

POST /api/v1/sms
Content-Type: application/x-www-form-urlencoded
 
to=+49…&body=…

Sie lässt sich sehr leicht benutzen, z.B. auch mit curl:

echo Hello World from SMS-API | curl --data-urlencode 'to=+49…' --data-urlencode body@- --user test:… https://sms-api.rz.babiel.com/api/v1/sms

Der neue sms-api-server ist komplett stateless. Auch das ist eine Vereinfachung gegenüber vorher, wo es diverse Queues gab. Dadurch kann er bequem in Kubernetes betrieben werden. Der Code sind nur knapp 1000 Zeilen Go. (Authentication und Authorization sind in einem Standard-Proxy als Sidecar umgesetzt.)

Der Server speichert oder loggt keine Telefonnummern. Das macht die Datenschutzmodellierung für die Komponente einfacher. Für vorgelagerte Anwendungen, welche die Telefonnummer speichern, und für das Versand-Backend, muss natürlich Datenschutz ebenfalls berücksichtigt werden.

Bonus-Features

Die zentrale API hat uns ermöglicht nützliche zusätzliche Features zu implementieren:

  • Prometheus-Metrics für die Menge an SMS, Fehlern, usw.
  • Rate-Limit pro Clientanwendung, damit Kosten nicht explodieren können
  • Fake-Nummern

Die Fake-Nummern sind Teil der „Drama Numbers“ – Nummberblöcke welche die Bundesnetzagentur explizit nicht vergibt und welche z.B. für Verwendung in Filmen vorgesehen sind. Wir haben diesen Nummern spezielle Bedeutungen zugewiesen:

  • +4915228817386: erfolgreichen Versand simulieren.
  • +4915228895456: fehlerhaften Versand simulieren.

Wenn man eine dieser Nummern verwendet, wird keine SMS versendet, aber man kann die Anbindung eines Clients an die API trotzdem testen.

Fazit

Initial haben wir das TCP-Protokoll der alten Gateways als Backend für die SMS-API verwendet. Dadurch konnten wir unsere Clients bereits auf die neue API umstellen, während wir noch einen Dienstleister für den Versand ausgewählt haben. Das ist ein weiterer Gewinn durch das Loose Coupling.

Seit der schrittweisen Einführung der API haben wir erfolgreiche tausende SMS damit verschickt.

Falls du auch Interesse hast solche Lösungen zu finden und an diesen zu arbeiten, bewirb dich doch bei uns.