SMS alerting with Free Mobile

🇬🇧 As Free Mobile is a French Mobile/Internet Access Provider, this wiki entry is in French.

🥐 Free Mobile propose une API très simple pour s'envoyer des SMS à soi-même, quand on a un abonnement mobile.

Il faut d'abord activer les Notifications par SMS sur son espace client.

On reçoit une clé d'API, qu'on appellera PASS.

Il suffit ensuite d'envoyer une requête HTTP GET :

https://smsapi.free-mobile.fr/sendmsg?user=USER&pass=PASS&msg=MSG

Il serait donc possible de faire un simple cURL :

curl https://smsapi.free-mobile.fr/sendmsg?user=12345678&pass=abcdefghijlkmnop&msg=coucou

Cependant :

  • Comme le paramètre msg est dans l'URL, il doit être encodé avec les %20 caractères qui vont bien.
  • Si on veut garder reaction.jsonnet dans un repository Git, on préfèrera garder les secrets (user, pass) dans des fichiers externes lisibles seulement par root (ou par reaction, si vous lui avez créé un user spécfique)

cURL permet de faire tout ça en une commande, donc pas besoin de faire un script shell.

Sans plus attendre, voilà une fonction JSONnet avec la commande cURL complète :

local sendsms(message) = {
  sendsms: {
    cmd: [
      "${pkgs.curl}/bin/curl",
      // Retourner un code d'erreur si le code de retour HTTP indique une erreur
      "--fail",
      // Ne rien afficher par défaut
      "--silent",
      // Quand même afficher les erreurs
      "--show-error",
      // Stocker dans la variable USER le contenu de /var/secrets/mobileapi-user
      "--variable", "USER@/var/secrets/mobileapi-user",
      // Stocker dans la variable PASS le contenu de /var/secrets/mobileapi-pass
      "--variable", "PASS@/var/secrets/mobileapi-pass",
      // Stocker dans la variable MSG  le contenu du message
      "--variable", "MSG=" + message,
      // Enlever les espaces et retours à la ligne des USER et PASS
      // Encoder au format URL le MSG à envoyer
      "--expand-url", "https://smsapi.free-mobile.fr/sendmsg?user={{USER:trim}}&pass={{PASS:trim}}&msg={{MSG:trim:url}}",
    ],
  },
};

Exemples de la vraie vie

Quand le service myservice affiche une erreur, me l'envoyer par SMS.

local sendsms(message) = {
  sendsms: {
    cmd: [
      "${pkgs.curl}/bin/curl",
      "--fail",
      "--silent",
      "--show-error",
      "--variable", "USER@/var/secrets/mobileapi-user",
      "--variable", "PASS@/var/secrets/mobileapi-pass",
      "--variable", "MSG=" + message,
      "--expand-url", "https://smsapi.free-mobile.fr/sendmsg?user={{USER:trim}}&pass={{PASS:trim}}&msg={{MSG:trim:url}}",
    ],
  },
};

{
  patterns: {
    untilEOL: '.*$'
  },

  streams: {
    myservice: {
      cmd: [' journalctl', '-fn0', '-u', 'myservice.service'],
      filters: {
        errors: {
          regex: [ @'ERROR <untilEOL>' ],
          actions: sendsms('<untilEOL>'),
        },
      },
    },
  },
}

Quand on bannit une IP, me l'envoyer par SMS aussi.

local sendsms(message) = {
  sendsms: {
    cmd: [
      "${pkgs.curl}/bin/curl",
      "--fail",
      "--silent",
      "--show-error",
      "--variable", "USER@/var/secrets/mobileapi-user",
      "--variable", "PASS@/var/secrets/mobileapi-pass",
      "--variable", "MSG=" + message,
      "--expand-url", "https://smsapi.free-mobile.fr/sendmsg?user={{USER:trim}}&pass={{PASS:trim}}&msg={{MSG:trim:url}}",
    ],
  },
};

local banFor(time) = {
  // la configuration de son firewall qui va bien
};

{
  patterns: {
    untilEOL: '.*$'
  },

  streams: {
    myservice: {
      cmd: [' journalctl', '-fn0', '-u', 'myservice.service'],
      filters: {
        errors: {
          regex: [ @'ERROR <untilEOL>' ],
          actions: banFor('48h') + sendsms('<ip> banned for 48h'),
        },
      },
    },
  },
}