Je vérifie les fuites de mes courriels

Objectif

En ce moment, c’est la cata, les cyberattaques et les exfiltration de données sont presque quotidiennes, j’ai besoin d’être rassuré sur les fuites de mes adresses mails.

J’ai donc créé cette carte HA:

Principe

Il existe plusieurs sites qui sont capables de tester si mon adresse mail est compromise ou pas.

La compromission d’une adresse e-mail se produit lorsque les informations associées à cette adresse (comme le mot de passe, les contacts, ou les données personnelles) sont exposées à des tiers non autorisés, généralement à la suite d’une violation de données. Cela peut se produire lorsque des bases de données de services en ligne sont piratées, et les informations des utilisateurs sont volées puis divulguées ou vendues sur des forums ou des sites du darknet. Une adresse e-mail compromise peut être utilisée pour envoyer des spams, des attaques de phishing, ou accéder à d’autres comptes liés à cette adresse, mettant en danger la sécurité et la confidentialité de l’utilisateur.

Le site le plus connu d’entre tous est :

Mais ce site ne fourni plus d’API sans abonnement, j’ai cherché une autre solution et j’ai trouvé le site :

Ce site propose une APIV2 payante mais a laissé son APIV1 en ligne, elle est plus légère mais elle me suffit pour savoir si mon courriel est compromis et s’il est compromis, combien y a t il de fuites. Cette api n’a en plus pas besoin de token d’authentification, c’est donc bien plus simple.

Voici le lien vers la doc de l’API :

Je crée des requêtes REST dans sensors.yaml

J’ai de manière très classique organisé mes fichiers de configurations dans des fichiers YAML qui sont appelés par configuration.yaml.

sensor: !include sensors.yaml

L’appel que je vais faire est au format :

https://leakcheck.io/api/public?check=monmail@mail.fr

Le résultat est au format json, par exemple :

{
  "success": true,
  "found": 7,
  "fields": [
    "last_name",
    "country",
    "first_name",
    "username",
    "dob",
    "password",
    "city"
  ],
  "sources": [
    {
      "name": "Deezer.com",
      "date": "2019-09"
    },
    {
      "name": "Badoo.com",
      "date": "2013-07"
    }
  ]
}
  • found donne le nombre de compromission ou plutôt le nombre de bases de données pirates qui contiennent le mail. 
  • fields est inutile à ce stade
  • sources donne les noms et bases de données des compromissions mais dans la version gratuite, on n’a visiblement pas l’exhaustivité.

Voici le code que j’ajoute pour un mail d’exemple :

- platform: rest
  name: "demo46@mail.comr"
  unique_id: "sensor.fuite_demo46_mail_com"
  resource: https://leakcheck.io/api/public?check=demo46@mail.com
  scan_interval: 86400  # Intervalle de scan en secondes 86400s = 1 jour
  value_template: "{{ value_json.success }}"  
  json_attributes:
    - found
    - sources  

Je renomme le sensor créé

Je dois relancer HA ou au moins recharger la config Yaml, et le sensor arrive.

Je suis toujours surpris que l’unique_id ne soit pas pris en compte, rien de grave, je le corrige manuellement. J’utilise sensor.fuite* car c’est une carte auto-entities que j’utiliserai ensuite.

Je vais créer la carte

Le code est assez complexe, je suis parti du code de l’excellent herveaurel pour ses batteries.

Voici ce que j’ai ajouté dans l’éditeur de configuration pour configurer type: custom:button-card  et template: leak_card

button_card_templates:
  leak_card:
    variables:
      entity: '[[[ return entity.entity_id ]]]'
    entity: '[[[ return variables.entity ]]]'
    icon: |
      [[[
        return entity.state === "True" ? "mdi:car-brake-alert" : "mdi:shield-lock-outline"
      ]]]
    name: '[[[ return entity.attributes.friendly_name ]]]'
    label: |
      [[[
        return entity.state === "True" 
          ? `Compromis<br>${entity.attributes.found} fuites` 
          : "Protégé"
      ]]]
    show_icon: true
    show_state: false
    show_label: true
    template:
      - no_style
      - police
    tap_action:
      action: more-info
    double_tap_action:
      action: toggle
    custom_fields:
      barre:
        card:
          type: custom:bar-card
          entities:
            - entity: '[[[ return variables.entity ]]]'
              color: |
                [[[ 
                  var state = entity.state;
                  if (state === "True") {
                    return "var(--card-red)";
                  } else {
                    return "var(--card-green)";
                  }
                ]]]
          direction: right
          positions:
            name: 'off'
            indicator: 'off'
            value: 'off'
          height: 50px
          width: 100%
          icon: 'off'
          entity_row: true
    styles:
      card:
        - height: 40px
        - padding: 2px
        - animation: blink 0.8s ease infinite
      icon:
        - position: absolute
        - width: 25px
        - color: var(--orange)
        - left: calc((7%) - 5px)
        - margin-bottom: 2px
      name:
        - position: absolute
        - font-size: 13px
        - color: var(--orange)
        - font-weight: 500
        - left: calc((20%) - 15px)
      label:
        - position: absolute
        - font-size: 13px
        - color: |
            [[[ 
              var state = entity.state ;
                if (state === "True")   
                return "var(--red)"              
                else 
                return "var(--green)"
             ]]]
        - font-weight: 600
        - width: 100%
        - text-align: center
        - left: calc((10%) + 70px)
      custom_fields:
        barre:
          - top: '-19%'
          - left: '-50%'
          - width: 100%
          - position: absolute
          - z-index: 0
    state:
      - value: 'False'
        styles:
          icon:
            - color: var(--green)
          name:
            - color: var(--green)
          card:
            - animation: none
      - value: unknown
        styles:
          name:
            - color: var(--grey)
          label:
            - color: var(--grey)
          card:
            - animation: blink 0.8s ease infinite
      - value: unavailable
        styles:
          name:
            - color: var(--grey)
          label:
            - color: var(--grey)
          card:
            - animation: blink 0.8s ease infinite

Et voici le code de la carte :

type: entities
card_mod:
  style: |
    ha-card { 
     background-color: var(--card-background-color);
     border-radius: var(--ha-card-border-radius) !important;
     } 
entities:
  - type: custom:decluttering-card
    template: header
    variables:
      - name: Fuites des courriels
      - icon: mdi:home-battery
  - type: custom:auto-entities
    card:
      type: entities
      show_header_toggle: true
    filter:
      include:
        - entity_id: sensor.fuite*
          options:
            type: custom:button-card
            template: leak_card
    sort:
      method: state
      numeric: true
      ignore_case: false
      ip: false
    show_empty: true

Et la carte terminée apparait