No necessiteu un fitxer temporal per generar una clau OpenVPN
Capturar el material de la clau en memòria evita un cicle de vida de fitxer, no una fuita. Manteniu separats els fluxos de sortida i d'error, i tracteu la clau com un secret després.
Generar una clau no necessita un fitxer temporal, i saltar-se'l arregla menys del que insinuen la majoria de guies. El que elimina és un cicle de vida de fitxer i la cursa de neteja al seu voltant. El que deixa intacte és cada oportunitat de filtrar el secret després. El problema de correcció en aquests scripts sol estar en un altre lloc, perquè el diagnòstic i el material de la clau viatgen per fluxos diferents.
El fitxer mai no era l'exposició que pensàveu
Un fitxer temporal és un risc concret quan és llegible per tothom, quan sobreviu a una caiguda o quan es fa un salt en una passa de neteja després d'una excepció. Aquests són reals i val la pena arreglar-los. També són locals, visibles i fàcils de provar. Anomeneu cada un al vostre propi script abans de concloure que el canvi era cosmètic.
Els riscos més silenciosos seuen més avall: la clau impresa durant la depuració, l'excepció que serialitza tot l'objecte de resultat, el gestor de caigudes que escriu un bolcat de memòria, l'agregador de registres que rep la ruta del fitxer i després el contingut. Evitar un fitxer temporal no fa res per cap d'aquests, i creure el contrari és com una reescriptura ben intencionada deixa el secret més exposat que abans. Tracteu el canvi com una millora en una seqüència, no com la solució.
Què escriu el client quan no es dona cap nom de fitxer
Les versions actuals del client envien la clau generada a la sortida estàndard quan la comanda de clau es dona sense una ruta de sortida. Aquest comportament documentat és el que fa viable l'enfocament en memòria, i elimina la necessitat del truc més antic d'apuntar l'eina a una ruta de dispositiu.
import subprocess
proc = subprocess.run(
["openvpn", "--genkey", "tls-crypt"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=True,
)
key_material = proc.stdout
Passeu la comanda com una llista. Aquí no cal cap expansió de l'intèrpret, i habilitar-lo faria que el límit dels arguments depengués de cometes que no controleu. Utilitzeu l'executable previst per ruta absoluta si l'script pot executar-se amb una ruta de cerca diferent de la que espereu.
La comprovació del codi de retorn evita que el camí d'èxit continuï després d'una invocació fallida. Sense ella, una cadena de bytes buida pot fluir endavant i només fallar molt més tard, en el punt on s'usa la clau i on el missatge d'error ja no esmenta gens la generació.
Dos fluxos, dos significats
La sortida estàndard porta la clau. L'error estàndard porta tot el que l'eina us vol dir, incloent-hi avisos sobre la configuració, la versió i el tipus de clau. Redirigir tots dos a un sol búfer és l'error que produeix una clau d'aspecte plausible amb una frase cosida al mig.
Manteniu també separat el camí de fallada. Quan la crida falla, informeu de la comanda que ha fallat i de l'estat de sortida, i després decidiu deliberadament si alguna part de l'error estàndard és segura de mostrar. Abocar tot l'objecte de resultat a un registre és la drecera habitual, i pot endur-se la clau amb ell.
Una lectura segura per a binaris importa si després feu un hash del material o el compareu. El mode text amb una codificació inesperada pot alterar bytes que mai no havien de ser text, i una clau alterada és indistingible d'una de dolenta fins que falla un intercanvi de salutació.
Si tot i així el persistiu, feu-ho deliberadament
La majoria de desplegaments finalment necessiten la clau al disc, a la passarel·la o en un magatzem de secrets. Escriviu-la una vegada, amb permisos restrictius des de la creació en lloc d'un chmod posterior, i feu l'escriptura atòmica perquè un fitxer parcial no esdevingui mai el que un servei llegeix en arrencar. Un reanomenament des d'una ruta al mateix directori sol ser suficient per a això. Elimineu la ruta de preparació a la branca de fallada, ja que l'escriptura fallida és exactament la còpia que la gent oblida.
Definiu el mode del fitxer quan es crea, i manteniu també restrictiu el mode del directori. Eviteu qualsevol ruta sota una ubicació que un treball de còpia de seguretat escombra sense pensar, perquè un secret en una còpia nocturna és un secret en cada còpia d'aquella còpia. El mateix raonament s'aplica a un volum compartit que altres serveis poden llegir.
Una clau compartida no és una identitat
Generar aquest material no emet cap certificat, no inscriu cap client i no estableix qui es connecta. La clau compartida protegeix un canal entre parts que ja es fien les unes de les altres; la identitat encara ve del certificat i de qualsevol autenticació que se li posi al davant.
Els tipus de clau tampoc no són intercanviables. Una clau simètrica per a una funció no és un substitut directe per a una altra, i les versions més noves afegeixen les seves variants amb fitxers diferents a cada extrem. Genereu el tipus que la vostra configuració anomena realment, i després useu-lo en el paper que aquell tipus defineix.
Proveu el resultat amb una connexió real en lloc d'inspeccionar la mida del fitxer. Si l'intercanvi de salutació es completa i els registres no mostren avisos de clau, el camí de generació és correcte; si la clau s'hagués truncat per un flux fusionat, la connexió fallaria d'una manera que assenyalaria l'altre extrem en lloc del script.