Un formulaire public qui ne parle jamais au réseau privé produit malgré tout des données que le réseau privé doit juger. Le tunnel ne change que l'identité de l'appelant. Tout ce qui suit le téléchargement est une décision d'import, et elle appartient au côté privé. Cette présentation suit un envoi depuis le navigateur jusqu'à un enregistrement interne validé.

Commencez là où l'envoi atterrit

Le navigateur publie vers un point de terminaison public, qui écrit une ligne dans un magasin d'entrée contrôlé et ne renvoie rien de plus qu'un accusé de réception. Ce magasin est le point de remise, et il devrait être la seule chose dans laquelle la couche publique peut écrire. Conservez-y la charge brute inchangée, avec l'heure d'arrivée et un identifiant d'enregistrement stable.

Ensuite, un travailleur privé tire les lignes en attente par le tunnel et décide quoi faire de chacune. Il s'exécute sous sa propre identité, ce qui fait l'objet de la section suivante.

curl --silent --fail \
  --cert /etc/importer/client.crt --key /etc/importer/client.key \
  "https://intake.corp.internal/api/pending?limit=20" \
  -o /var/lib/importer/pending.json

N'accordez à l'importateur que l'autorité dont il a besoin

Le processus web public et l'identité qui écrit dans l'application interne devraient être deux principaux distincts. Un serveur public n'a pas besoin d'administration interne simplement parce qu'il doit livrer des données de formulaire, et un compte unique partagé entre les deux côtés transforme toute faille web en écriture interne. Délivrez au travailleur ses propres identifiants, limitez-les à l'unique opération d'import et enregistrez quel principal a effectué chaque import. C'est cette séparation qui rend la frontière du tunnel significative plutôt que décorative.

Limitez aussi la source depuis laquelle le travailleur peut lire. Si l'implémentation utilise une file ou un service de transfert, ce service conserve sa propre authentification et sa politique d'accès, car le VPN n'authentifie rien à l'intérieur de la charge.

Une fonction éphémère n'est pas dispensée du même examen. Pendant qu'elle s'exécute, sa position réseau et ses identifiants accordent encore une autorité, et une durée de vie plus courte ne fait que réduire la fenêtre. La durée ne remplace pas la décision des opérations que l'identité peut effectuer.

Validez avant que quoi que ce soit d'interne ne change

Les champs des formulaires publics sont du texte contrôlé par l'attaquant jusqu'à preuve du contraire, et les recommandations d'OWASP sur la validation des entrées classent les flux backend parmi les sources non fiables précisément pour cette raison. Un transport chiffré dit que les octets sont arrivés intacts, pas qu'ils décrivent une requête autorisée. Analysez et validez avant toute étape privilégiée, afin qu'une mauvaise ligne n'atteigne jamais un chemin de code capable d'agir.

Définissez les champs autorisés, leurs formats, leurs tailles et les règles métier qui doivent tenir. Une date peut être bien formée et rester incorrecte pour l'opération demandée, et une charge qui nomme un compte interne ou un statut d'approbation ne doit pas pouvoir s'accorder l'un ou l'autre.

Envoyez les lignes rejetées vers un résultat de revue au lieu de deviner une correction ou de les transmettre à un interpréteur de commandes ou à une interface de base de données brute. Journalisez l'identifiant d'enregistrement et la règle en échec, pas chaque champ saisi par le demandeur.

Placez un point de reprise sur une seule opération

Si l'enregistrement submission-1042 est tiré deux fois parce que le premier accusé a été perdu, le travailleur a besoin d'un moyen durable de reconnaître l'enregistrement source et son résultat validé. Une planification qui exécute la tâche une fois ne prouve pas que chaque ligne a été appliquée une fois. La livraison en double est normale, donc la conception doit l'absorber.

Utilisez le mécanisme propre de transactions et de gestion des doublons de l'application interne, et gardez l'identifiant source, le résultat et l'accusé dans une séquence cohérente. N'accusez réception qu'une fois l'opération prévue validée ou durablement attribuée, et ne supprimez jamais la ligne d'entrée simplement parce que les octets ont été téléchargés.

Prouvez-le ensuite avec trois fichiers de test : une ligne valide, une ligne mal formée et le même identifiant source contrôlé livré deux fois. Chacun passe par le même point de terminaison que celui utilisé par le travailleur.

for f in fixtures/valid-submission.json fixtures/bad-date.json; do
  curl --silent --fail --cert /etc/importer/client.crt \
    -X POST --data @"$f" https://intake.corp.internal/api/records
done
curl --silent --fail --cert /etc/importer/client.crt \
  -X POST --data @fixtures/valid-submission.json https://intake.corp.internal/api/records

Les deux premières lignes doivent finir dans des états internes différents, et la troisième doit renvoyer l'identifiant déjà validé pour cet enregistrement source plutôt que d'en créer un second. Toute autre issue signifie que l'import n'est pas encore reproductible.

Articles similaires