mTLS avec Cloudflare : mise en œuvre et intégration avec Prometheus

mTLS avec Cloudflare : mise en œuvre et intégration avec Prometheus

Après les précédents articles consacrés à Cloudflare et à sa mise en place, nous allons poursuivre avec l’authentification mTLS.

Qu’est-ce que l’authentification mTLS ?

L’authentification mTLS (Mutual TLS) est une extension du protocole TLS classique dans laquelle le client et le serveur présentent chacun un certificat afin de s’authentifier mutuellement.

Contrairement au HTTPS standard, où seul le serveur est authentifié auprès du client, le mTLS ajoute une vérification du client par le serveur. Cela permet de garantir que seules des entités autorisées peuvent accéder à une ressource.

Ce mécanisme est particulièrement utilisé pour :

  • sécuriser des API internes,
  • protéger des endpoints sensibles (metrics, administration, etc.),
  • mettre en place une authentification forte entre services (machine-to-machine).

Contexte

Dans mon cas, j’ai plusieurs services qui exposent des métriques que je souhaite scraper depuis mon NAS afin de les visualiser dans Grafana.

Les applications tournant sur plusieurs ports, j’utilise Apache comme reverse proxy.

Afin de ne pas exposer ces métriques publiquement, j’avais mis en place une authentification par certificat, fonctionnelle avant la migration vers Cloudflare.

Avant cette migration, Prometheus et Apache communiquaient directement et s’échangeaient leurs certificats afin de s’authentifier mutuellement.

Passage à Cloudflare

Une fois basculé sous Cloudflare, l’architecture évolue légèrement :

  • une authentification mTLS est mise en place entre Prometheus et Cloudflare,
  • l’authentification de Cloudflare auprès de mon serveur web est déléguée à une chaîne de certificats (Authenticated Origin Pulls).

Cette partie ayant déjà été détaillée dans un précédent article, nous allons ici nous concentrer sur la mise en place du mTLS entre une application (Prometheus) et Cloudflare.

Je ne me suis pas compliqué la tâche avec du BYOC (Bring Your Own Certificate) et j’ai utilisé les certificats clients fournis par Cloudflare.

Il suffit de définir le périmètre (le ou les domaines concernés) pour lesquels ce certificat sera valide.

Certificats client émis par Cloudflare
Certificats client émis par Cloudflare

Ensuite, il faut mettre en place une règle de sécurité afin de forcer l’authentification mTLS sur le ou les endpoints concernés.

Nouvelle règle personnalisée
Nouvelle règle personnalisée

Une fois cette configuration appliquée, le domaine n’est plus accessible directement sans authentification : toute requête doit présenter un certificat valide.

Configuration côté Prometheus

Côté Prometheus, j’ai récupéré la clé privée et le certificat (format PEM) afin de les intégrer dans la configuration du scraper.

scrape_configs:

  # crowdsec
  - job_name: "crowdsec_axanar"
    scrape_interval: 60s
    metrics_path: /crowdsec
    scheme: https
    tls_config:
      cert_file: ../tls/cloudflared.pem
      key_file: ../tls/cloudflared.key
    static_configs:
      - targets: ["metrics.domain.ltd"]
        labels:
          host: "server.domain.ltd"
          network: "domain.ltd"
          type: "server"
          container: "no"
    relabel_configs:
      - source_labels: [__name__]
        regex: "(.*)"
        replacement: "crowdsec"
        target_label: job
 
  # node_exporter
  - job_name: "node_exporter_axanar"
    scheme: https
    tls_config:
      cert_file: ../tls/cloudflared.pem
      key_file: ../tls/cloudflared.key
    static_configs:
      - targets: ["metrics.domain.ltd"]
        labels:
          host: "server.domain.ltd"
          network: "domain.ltd"
          type: "server"
          container: "no"
    relabel_configs:
      - source_labels: [__name__]
        regex: "(.*)"
        replacement: "node_exporter"
        target_label: job

  # postfix
  - job_name: "postfix_axanar"
    scrape_interval: 60s
    metrics_path: /postfix
    scheme: https
    tls_config:
      cert_file: ../tls/cloudflared.pem
      key_file: ../tls/cloudflared.key
    static_configs:
      - targets: ["metrics.domain.ltd"]
        labels:
          host: "server.domain.ltd"
          network: "domain.ltd"
          type: "server"
          container: "no"
    relabel_configs:
      - source_labels: [__name__]
        regex: "(.*)"
        replacement: "postfix"
        target_label: job

Résultat

À présent, j’ai un accès à mes métriques depuis mon NAS, sécurisé par une authentification mutuelle.

Seuls les clients disposant d’un certificat valide peuvent interroger les endpoints exposés, ce qui réduit fortement la surface d’attaque.

Avatar de Guillaume Kulakowski

À propos de l’auteur

Commentaires

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. Découvrez comment les données de vos commentaires sont traitées.

Derniers articles sur le journal

Articles à la une