Non necesitas un ficheiro temporal para xerar unha chave OpenVPN
Capturar o material da chave en memoria evita un ciclo de vida de ficheiro, non unha fuga. Mantén separados os fluxos de saída e de erro, e trata a chave como un segredo despois.
A xeración de chaves non necesita un ficheiro temporal, e prescindir del arranxa menos do que insinúan a maioría das guías. O que elimina é un ciclo de vida de ficheiro e a carreira de limpeza ao seu redor. O que deixa intacto é cada oportunidade de filtrar o segredo despois. O problema de corrección nestes scripts adoita estar noutro sitio, porque o diagnóstico e o material da chave viaxan por fluxos distintos.
O ficheiro nunca foi a exposición que pensabas
Un ficheiro temporal é un risco concreto cando é lexible por todos, cando sobrevive a unha caída ou cando se omite un paso de limpeza tras unha excepción. Iso é real e paga a pena arranxalo. Tamén son locais, visibles e fáciles de probar. Nomea cada un no teu propio script antes de concluír que o cambio era cosmético.
Os riscos máis silenciosos están augas abaixo: a chave impresa durante a depuración, a excepción que serializa todo o obxecto de resultado, o xestor de fallos que escribe un volcado de memoria, o agregador de rexistros que recibe a ruta do ficheiro e despois o contido. Evitar un ficheiro temporal non fai nada por ningún deles, e crer o contrario é como unha reescritura benintencionada deixa o segredo máis exposto que antes. Trata o cambio como unha mellora nunha secuencia, non como a solución.
Que escribe o cliente cando non se dá un nome de ficheiro
As versións actuais do cliente envían a chave xerada á saída estándar cando o comando de chave se dá sen unha ruta de saída. Ese comportamento documentado é o que fai viable o enfoque en memoria, e elimina a necesidade do truco máis antigo de apuntar a ferramenta a unha ruta de dispositivo.
import subprocess
proc = subprocess.run(
["openvpn", "--genkey", "tls-crypt"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=True,
)
key_material = proc.stdout
Pasa o comando como unha lista. Aquí non fai falta ningunha expansión do intérprete, e habilitar un faría que o límite dos argumentos dependese de comiñas que non controlas. Usa o executábel previsto por ruta absoluta se o script pode executarse cunha ruta de busca distinta da que esperas.
A comprobación do código de retorno impide que a ruta de éxito continúe tras unha invocación fallida. Sen ela, unha cadea de bytes baleira pode fluír adiante e fallar só moito despois, no punto en que se usa a chave e a mensaxe de erro xa non menciona en absoluto a xeración.
Dous fluxos, dous significados
A saída estándar leva a chave. O erro estándar leva todo o que a ferramenta quere dicirche, incluídos os avisos sobre a configuración, a versión e o tipo de chave. Redirixir ambos a un só búfer é o erro que produce unha chave de aspecto plausible cunha frase costurada no medio.
Mantén tamén separada a ruta de fallo. Cando a chamada falla, informa do comando que fallou e do estado de saída, e despois decide a conciencia se algunha parte do erro estándar é segura de mostrar. Volcar todo o obxecto de resultado a un rexistro é o atallo habitual, e pode levar a chave consigo.
Unha lectura segura para binarios importa se despois calculas o hash do material ou o comparas. O modo texto cunha codificación inesperada pode alterar bytes que nunca debían ser texto, e unha chave alterada é indistinguible dunha equivocada ata que falla un saúdo.
Se aínda así o persiste, faino a conciencia
A maioría dos despregamentos acaban necesitando a chave no disco, na pasarela ou nun almacén de segredos. Escríbea unha vez, con permisos restritivos desde a creación en lugar dun chmod posterior, e fai a escritura atómica para que un ficheiro parcial nunca sexa o que un servizo le á hora de arrincar. Un renomeado desde unha ruta no mesmo directorio adoita abondar para iso. Elimina a ruta de preparación na rama de fallo, porque a escritura fallida é exactamente a copia que a xente esquece.
Define o modo do ficheiro cando se crea, e mantén tamén restritivo o modo do directorio. Evita calquera ruta baixo unha localización que un traballo de copia de seguridade varre sen pensar, porque un segredo nunha copia nocturna é un segredo en cada copia desa copia. O mesmo razoamento se aplica a un volume compartido que outros servizos poden ler.
Unha chave compartida non é unha identidade
Xerar este material non emite un certificado, non inscribe un cliente e non establece quen se conecta. A chave compartida protexe unha canle entre partes que xa confían as unhas nas outras; a identidade segue a vir do certificado e de calquera autenticación que se lle poña diante.
Os tipos de chave tampouco son intercambiables. Unha chave simétrica para unha función non é un substituto directo para outra, e as versións máis recentes engaden as súas propias variantes con ficheiros distintos en cada extremo. Xera o tipo que a túa configuración nomea de verdade, e despois úsao no papel que ese tipo define.
Proba o resultado cunha conexión real en vez de inspeccionar o tamaño do ficheiro. Se o saúdo se completa e os rexistros non mostran avisos de chave, a ruta de xeración é correcta; se a chave se truncase por un fluxo fusionado, a conexión fallaría dun xeito que sinala o par en lugar do script.