From 2b4c6316527e1ecb4338f48f0935d977458e43e1 Mon Sep 17 00:00:00 2001 From: Lorenzo Blasa Date: Thu, 14 Sep 2023 04:15:18 -0700 Subject: [PATCH] Certificate and token generation fixes Summary: A few things need to be done which are on this change: - Certificate generation should execute as an atomic operation, hence, it needs to be synchronised. - Do not generate client token as part of certificate generation. This causes a deadlock now. - Add more logs for troubleshooting Reviewed By: aigoncharov Differential Revision: D49269624 fbshipit-source-id: 071a8e5b895198730b7d914cc4622837e9094e2f --- .../certificate-utils.tsx | 50 ++++++++++--------- desktop/flipper-server/src/index.tsx | 8 +-- desktop/flipper-ui-browser/src/index.tsx | 2 + 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/desktop/flipper-server-core/src/app-connectivity/certificate-exchange/certificate-utils.tsx b/desktop/flipper-server-core/src/app-connectivity/certificate-exchange/certificate-utils.tsx index 11beafd78..4b69cfc58 100644 --- a/desktop/flipper-server-core/src/app-connectivity/certificate-exchange/certificate-utils.tsx +++ b/desktop/flipper-server-core/src/app-connectivity/certificate-exchange/certificate-utils.tsx @@ -21,6 +21,7 @@ import {isTest} from 'flipper-common'; import {flipperDataFolder} from '../../utils/paths'; import * as jwt from 'jsonwebtoken'; import {getFlipperServerConfig} from '../../FlipperServerConfig'; +import {Mutex} from 'async-mutex'; const tmpFile = promisify(tmp.file) as ( options?: FileOptions, @@ -152,32 +153,30 @@ const certificateSetup = async () => { } }; +const mutex = new Mutex(); const ensureServerCertExists = async (): Promise => { - const allExist = await Promise.all([ - fs.pathExists(serverKey), - fs.pathExists(serverCert), - fs.pathExists(caCert), - ]).then((exist) => exist.every(Boolean)); + return mutex.runExclusive(async () => { + const allExist = await Promise.all([ + fs.pathExists(serverKey), + fs.pathExists(serverCert), + fs.pathExists(caCert), + ]).then((exist) => exist.every(Boolean)); - if (!allExist) { - console.info('No certificates were found, generating new ones'); - - await generateServerCertificate(); - await generateAuthToken(); - - return; - } - - try { - console.info('Checking for certificates validity'); - await checkCertIsValid(serverCert); - console.info('Checking certificate was issued by current CA'); - await verifyServerCertWasIssuedByCA(); - } catch (e) { - console.warn('Not all certs are valid, generating new ones', e); - await generateServerCertificate(); - await generateAuthToken(); - } + if (!allExist) { + console.info('No certificates were found, generating new ones'); + await generateServerCertificate(); + } else { + try { + console.info('Checking for certificates validity'); + await checkCertIsValid(serverCert); + console.info('Checking certificate was issued by current CA'); + await verifyServerCertWasIssuedByCA(); + } catch (e) { + console.warn('Not all certificates are valid, generating new ones', e); + await generateServerCertificate(); + } + } + }); }; const generateServerCertificate = async (): Promise => { @@ -309,6 +308,9 @@ const exportTokenToManifest = async ( export const generateAuthToken = async () => { console.info('Generate client authentication token'); + + await ensureServerCertExists(); + const config = getFlipperServerConfig(); const privateKey = await fs.readFile(serverKey); diff --git a/desktop/flipper-server/src/index.tsx b/desktop/flipper-server/src/index.tsx index dc2e324bc..45e296aac 100644 --- a/desktop/flipper-server/src/index.tsx +++ b/desktop/flipper-server/src/index.tsx @@ -235,6 +235,9 @@ async function start() { `[flipper-server][bootstrap] FlipperServer created (${serverCreatedMS} ms)`, ); + // At this point, the HTTP server is ready and configuration is set. + await launch(); + const t6 = performance.now(); const launchedMS = t6 - t5; @@ -263,9 +266,6 @@ async function start() { } await flipperServer.connect(); - // At this point, the HTTP server is ready and configuration is set. - await launch(); - const t8 = performance.now(); const appServerStartedMS = t8 - t7; console.info( @@ -309,6 +309,8 @@ async function launch() { console.info('[flipper-server] Launch UI'); const token = await getAuthToken(); + console.info('[flipper-server] Token is available: ' + token !== undefined); + const searchParams = new URLSearchParams({token: token ?? ''}); const url = new URL(`http://localhost:${argv.port}?${searchParams}`); diff --git a/desktop/flipper-ui-browser/src/index.tsx b/desktop/flipper-ui-browser/src/index.tsx index 11e9837fc..617a5073a 100644 --- a/desktop/flipper-ui-browser/src/index.tsx +++ b/desktop/flipper-ui-browser/src/index.tsx @@ -41,6 +41,8 @@ async function start() { token = manifest.token; } + console.info('Token is available: ' + token !== undefined && token?.length); + const openPlugin = params.get('open-plugin'); if (openPlugin) { function removePrefix(input: string, prefix: string): string {