30. pepsi-httpd

Le serveur HTTP/HTTPS : la politique MTA-STS, le Web Key Directory, les métriques Prometheus, le portail des liens sécurisés, l’API et la console d’administration, et les pages des listes de diffusion.

30.1. Rôle

pepsi-httpd répond aux requêtes HTTP du système Pepsi. Il sert entre autres le fichier de politique MTA-STS, le Web Key Directory qui publie les clés OpenPGP de nos utilisateurs, et une page Prometheus /metrics ; la liste complète suit. Il est construit autour d’une table de dispatch générique afin que d’autres points de terminaison puissent être ajoutés sans toucher au cœur du serveur. Exécutez-le avec pepsi-httpd serve.

HTTP/1.1 (RFC 9112) avec la sémantique de la RFC 9110, sur hyper ; TLS est la RFC 8446 sur rustls. Ce qu’il sert est défini ailleurs, et chaque point de terminaison a son propre document de référence :

  • /.well-known/mta-sts.txt — le fichier de politique de la RFC 8461, dont les étapes de relais récupèrent et honorent le contenu en sortant.

  • /.well-known/openpgpkey/… — le Web Key Directory OpenPGP (draft-koch-openpgp-webkey-service, un Internet-Draft plutôt qu’une RFC), dans les deux dispositions, directe et avancée.

  • /mail/config-v1.1.xml et /.well-known/autoconfig/mail/config-v1.1.xml — l’autoconfiguration des comptes de courrier (draft-ietf-mailmaint-autoconfig), décrite ci-dessous.

  • /secure/… — le portail secure-link (Le portail de repli par lien sécurisé), dont le cookie de session suit la RFC 6265.

  • /api/v1/… et /ui — l’API d’administration et la console (L’API d’administration, La console d’administration), servies uniquement sur les listeners marqués ADMIN = yes, authentifiées avec le schéma Bearer de la RFC 6750 ou un cookie de session.

  • POST /resume — le webhook du marchand GNU Taler : une requête Authorization: Bearer portant {"message_id": "<token>"} fait repasser la ligne paused correspondante à pending et réveille le dispatcher, de sorte que pepsi-stage-anti-spam s’exécute de nouveau dès qu’un bon de commande est payé. Le point de terminaison est désactivé (404) à moins que [pepsi-httpd] RESUME_AUTHORIZATION_TOKEN ne soit défini.

  • /addin/manifest.xml et /addin/taskpane.html — le complément Outlook, répondant 404 à moins que [pepsi-httpd] ADDIN ne soit activé.

  • /3.0/… et /3.1/… — l’API REST de GNU Mailman 3 (L’API REST de GNU Mailman 3), servie uniquement sur les listeners marqués LIST_API = yes et authentifiée avec l’unique paire API_USER/API_PASS de [pepsi-list].

  • /lists/…, /archives/list/… et /robots.txt — les pages publiques des listes de diffusion, les comptes des membres et des propriétaires de listes, et l’archive (La console d’administration, Archives), servis uniquement sur les listeners marqués LISTS = yes.

30.2. Fonctionnalités

  • Plusieurs listeners. Chaque section [pepsi-httpd-listener-<name>] lie une socket exactement comme les listeners d’ingress : SERVE = tcp (BIND_TO/PORT, port 443 par défaut), unix (UNIXPATH) ou systemd (activation par socket), avec MODE = plain ou tls.

  • Sélection de certificat par SNI. Un listener TLS choisit son certificat par connexion d’après le nom d’hôte SNI du client : chaque section [pepsi-httpd-cert-<name>] liste un ou plusieurs noms d’hôte SNI et une paire TLS_CERT/TLS_KEY. Le TLS_CERT/TLS_KEY propre à un listener est le repli pour les connexions sans correspondance SNI. (MTA-STS exige un certificat valide pour mta-sts.<domain>.)

  • Matériel de clé via les credentials systemd. Le serveur s’exécute sans privilèges et ne peut pas lire /etc/letsencrypt, réservé à root par certbot ; sous systemd, il n’en a pas besoin. pepsi-setup écrit un drop-in LoadCredential=, systemd ouvre chaque certificat et chaque clé en tant que root au démarrage de l’unité, et le serveur lit la copie privée qui lui est remise sous $CREDENTIALS_DIRECTORY. Un certificat qui ne peut malgré tout pas être chargé est ignoré avec une erreur plutôt que d’emporter le serveur entier — seul un listener sans aucun certificat utilisable est fatal.

  • Routage générique. Les requêtes sont mises en correspondance par méthode et forme d’URL : le chemin d’une route est une liste de segments, chacun étant un littéral, une capture nommée d’un segment, ou une capture du reste. Les routes sont essayées dans l’ordre d’enregistrement, la première correspondance gagne, de sorte que GET /.well-known/mta-sts.txt, GET /.well-known/openpgpkey/$DOMAIN/hu/$HASH et un futur GET /foo/$ID sont chacun une seule entrée de table.

  • Politique MTA-STS. GET /.well-known/mta-sts.txt renvoie la politique RFC 8461 (construite à partir de [pepsi] MTA_STS_* et du HOSTNAME de l’ingress) lorsque le Host de la requête est mta-sts.<domain> pour un domaine de ACCEPTED_DOMAINS ; tout autre hôte donne 404.

  • Web Key Directory. GET /.well-known/openpgpkey/... publie les clés OpenPGP de nos propres utilisateurs, dans la forme directe comme dans la forme avancée, la réponse venant du magasin de clés par une consultation indexée (domain, local-part hash). La réponse est la clé binaire avec Access-Control-Allow-Origin: * ; le fichier de politique est un 200 de longueur nulle (son absence fait abandonner GnuPG avant qu’il ne demande une clé) ; une empreinte inconnue est un 404 au corps vide. Il ne sert que les identités que ce déploiement détient et a marquées published — jamais une clé de correspondant mise en cache — et n’applique délibérément aucune limitation de débit, car le protocole est par conception un oracle public. Voir Gestion des clés.

  • Métriques Prometheus. GET /metrics expose des jauges par étape en direct (messages actifs et en pause, lus directement depuis la file d’attente) et des compteurs écrits par pepsi-dispatch (timeouts, plantages, nombre de messages et temps de traitement total par étape pour les moyennes, et les totaux globaux d’étapes et de messages). Ces chiffres — et les noms d’étapes qui les étiquettent — décrivent la quantité de courrier que porte le déploiement et la façon dont son pipeline est construit : le point de terminaison est donc administratif. Il n’est servi que sur un listener ADMIN = yes et répond ailleurs par le 404 ordinaire. Il ne demande aucun identifiant propre, car un collecteur n’en a aucun à présenter ; l’indicateur du listener est le contrôle d’accès. Lier le serveur de façon privée n’est pas une solution de rechange : le même processus doit répondre pour mta-sts.<domain> et openpgpkey.<domain> depuis l’internet public.

  • La surface d’administration. Un listener marqué ADMIN = yes sert en outre l’API d’administration /api/v1 (L’API d’administration), la console d’administration /ui (La console d’administration) et /metrics. Sur tout autre listener, ces chemins répondent par le 404 ordinaire. La console est cliente de l’API — même authentification, mêmes portées, même journal d’audit — et n’exerce aucun contrôle de service.

30.3. Autoconfiguration des clients de messagerie

Configurer un compte de courrier à la main revient à répondre à huit questions — deux noms d’hôte, deux ports, deux notions de sécurité de transport, deux méthodes d’authentification — auxquelles la personne titulaire du compte est en général la moins équipée pour répondre. draft-ietf-mailmaint-autoconfig y remédie en faisant publier les réponses par le fournisseur, le client les récupérant à partir de la seule adresse.

Pepsi sert les deux échelons de cette chaîne qu’un fournisseur est censé publier. L’en-tête Host décide lequel est demandé :

https://autoconfig.example.org/mail/config-v1.1.xml             (required)
https://example.org/.well-known/autoconfig/mail/config-v1.1.xml (optional)

Les deux renvoient le même document text/xml, et les deux sont publics : le brouillon l’exige, et la raison n’est pas un oubli mais un problème de séquencement — un client doit apprendre quel mécanisme d’authentification employer avant de pouvoir s’authentifier. Le document ne contient donc aucun secret, et Pepsi le maintient ainsi en nommant %EMAILADDRESS%, l’espace réservé que le client substitue, plutôt qu’une adresse réelle. Le paramètre facultatif ?emailaddress= du brouillon est accepté et ignoré, ce qui signifie aussi qu’aucun texte contrôlé par la requête n’est jamais interpolé dans un document servi depuis l’origine propre du domaine de courrier.

<?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
  <emailProvider id="example.org">
    <domain>example.org</domain>
    <displayName>Example Mail</displayName>
    <displayShortName>Example</displayShortName>
    <incomingServer type="imap">
      <hostname>mail.example.org</hostname>
      <port>993</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </incomingServer>
    <outgoingServer type="smtp">
      <hostname>mail.example.org</hostname>
      <port>587</port>
      <socketType>STARTTLS</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </outgoingServer>
  </emailProvider>
</clientConfig>

La moitié sortante est dérivée, non configurée. Son port, sa sécurité de transport et son authentification sont lus sur le [pepsi-ingress-listener-*] marqué SUBMISSION = yes, de sorte qu’un déploiement qui déplace la soumission de STARTTLS sur 587 vers du TLS implicite sur 465 obtient un document corrigé sans y toucher — la façon la plus courante dont une configuration publiée devient fausse est qu’elle a cessé de correspondre au serveur, et il n’y a rien ici que l’on puisse oublier de mettre à jour. SMTP_HOST redéfinit la dérivation pour un déploiement dont le point de terminaison public est un répartiteur de charge plutôt que le listener.

La moitié entrante ne peut pas être dérivée, car Pepsi ne sert pas de boîtes aux lettres ; il les remet à un MDA (pepsi-stage-relay-to-lmtp). Aussi IMAP_HOST ou POP3_HOST doit-il nommer ce à quoi le déploiement s’associe, et tant que ni l’un ni l’autre ne le fait, les deux points de terminaison répondent 404. C’est délibéré : un client qui trouve un document de configuration cesse de parcourir la chaîne de repli, de sorte qu’un document incomplet laisse l’utilisateur plus mal loti que pas de document du tout.

La publication exige deux choses hors du fichier de configuration : un enregistrement DNS autoconfig.<domain> pointant ici, et un certificat couvrant ce nom — les clients essaient d’abord l’URL https://autoconfig.…, et une erreur de certificat à cet endroit n’est qu’une consultation infructueuse. Un déploiement peu disposé à ajouter le nom peut se reposer sur la forme /.well-known/, au prix de n’être trouvé que par les clients qui l’essaient.

30.4. Configuration

[pepsi-httpd] : MAX_CONNECTIONS (par défaut 256), DB_POOL_SIZE, RESUME_AUTHORIZATION_TOKEN, ADDIN (par défaut no) et ADDIN_URL (qui doit être une origine https:// — un simple http:// est refusé au démarrage à moins que l’hôte ne soit la boucle locale, de sorte qu’un test n’ait besoin d’aucun certificat). La surface d’administration lit [pepsi-admin], et le portail [pepsi-secure-link]. Les listeners et certificats résident dans les sections [pepsi-httpd-listener-<name>] et [pepsi-httpd-cert-<name>]. Les domaines servis, l’hôte mx de MTA-STS et la politique elle-même proviennent des sections partagées [pepsi-ingress] et [pepsi]. Voir Configuration.

Le Web Key Directory n’a besoin d’aucune configuration propre — il suit l’indicateur published de chaque identité — mais la méthode avancée exige un enregistrement DNS openpgpkey.<domain> par domaine servi, et le certificat du listener HTTPS doit couvrir ce nom. pepsi-setup run le demande à certbot et signale tout nom qui ne se résout pas.

[pepsi-autoconfig] configure le document d’autoconfiguration : IMAP_HOST / POP3_HOST (l’un ou l’autre active la fonctionnalité) avec leurs _PORT, _SOCKET et _AUTH ; les redéfinitions facultatives SMTP_* ; et DISPLAY_NAME, DISPLAY_SHORT_NAME et DOCUMENTATION_URL. Voir pepsi.conf(5).

30.5. Voir aussi

Architecture, Gestion des clés, pepsi-dispatch, pepsi-keys, pepsi-setup, pepsi.conf(5).