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
This commit is contained in:
Lorenzo Blasa
2023-09-14 04:15:18 -07:00
committed by Facebook GitHub Bot
parent cf599f9c3c
commit 2b4c631652
3 changed files with 33 additions and 27 deletions

View File

@@ -21,6 +21,7 @@ import {isTest} from 'flipper-common';
import {flipperDataFolder} from '../../utils/paths'; import {flipperDataFolder} from '../../utils/paths';
import * as jwt from 'jsonwebtoken'; import * as jwt from 'jsonwebtoken';
import {getFlipperServerConfig} from '../../FlipperServerConfig'; import {getFlipperServerConfig} from '../../FlipperServerConfig';
import {Mutex} from 'async-mutex';
const tmpFile = promisify(tmp.file) as ( const tmpFile = promisify(tmp.file) as (
options?: FileOptions, options?: FileOptions,
@@ -152,32 +153,30 @@ const certificateSetup = async () => {
} }
}; };
const mutex = new Mutex();
const ensureServerCertExists = async (): Promise<void> => { const ensureServerCertExists = async (): Promise<void> => {
const allExist = await Promise.all([ return mutex.runExclusive(async () => {
fs.pathExists(serverKey), const allExist = await Promise.all([
fs.pathExists(serverCert), fs.pathExists(serverKey),
fs.pathExists(caCert), fs.pathExists(serverCert),
]).then((exist) => exist.every(Boolean)); fs.pathExists(caCert),
]).then((exist) => exist.every(Boolean));
if (!allExist) { if (!allExist) {
console.info('No certificates were found, generating new ones'); console.info('No certificates were found, generating new ones');
await generateServerCertificate();
await generateServerCertificate(); } else {
await generateAuthToken(); try {
console.info('Checking for certificates validity');
return; await checkCertIsValid(serverCert);
} console.info('Checking certificate was issued by current CA');
await verifyServerCertWasIssuedByCA();
try { } catch (e) {
console.info('Checking for certificates validity'); console.warn('Not all certificates are valid, generating new ones', e);
await checkCertIsValid(serverCert); await generateServerCertificate();
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();
}
}; };
const generateServerCertificate = async (): Promise<void> => { const generateServerCertificate = async (): Promise<void> => {
@@ -309,6 +308,9 @@ const exportTokenToManifest = async (
export const generateAuthToken = async () => { export const generateAuthToken = async () => {
console.info('Generate client authentication token'); console.info('Generate client authentication token');
await ensureServerCertExists();
const config = getFlipperServerConfig(); const config = getFlipperServerConfig();
const privateKey = await fs.readFile(serverKey); const privateKey = await fs.readFile(serverKey);

View File

@@ -235,6 +235,9 @@ async function start() {
`[flipper-server][bootstrap] FlipperServer created (${serverCreatedMS} ms)`, `[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 t6 = performance.now();
const launchedMS = t6 - t5; const launchedMS = t6 - t5;
@@ -263,9 +266,6 @@ async function start() {
} }
await flipperServer.connect(); await flipperServer.connect();
// At this point, the HTTP server is ready and configuration is set.
await launch();
const t8 = performance.now(); const t8 = performance.now();
const appServerStartedMS = t8 - t7; const appServerStartedMS = t8 - t7;
console.info( console.info(
@@ -309,6 +309,8 @@ async function launch() {
console.info('[flipper-server] Launch UI'); console.info('[flipper-server] Launch UI');
const token = await getAuthToken(); const token = await getAuthToken();
console.info('[flipper-server] Token is available: ' + token !== undefined);
const searchParams = new URLSearchParams({token: token ?? ''}); const searchParams = new URLSearchParams({token: token ?? ''});
const url = new URL(`http://localhost:${argv.port}?${searchParams}`); const url = new URL(`http://localhost:${argv.port}?${searchParams}`);

View File

@@ -41,6 +41,8 @@ async function start() {
token = manifest.token; token = manifest.token;
} }
console.info('Token is available: ' + token !== undefined && token?.length);
const openPlugin = params.get('open-plugin'); const openPlugin = params.get('open-plugin');
if (openPlugin) { if (openPlugin) {
function removePrefix(input: string, prefix: string): string { function removePrefix(input: string, prefix: string): string {