certificate provider

Summary: _typescript_

Reviewed By: passy

Differential Revision: D17096517

fbshipit-source-id: a6e69e8b9a82fe76bb1de51a3a93182f35f40b3f
This commit is contained in:
Daniel Büchele
2019-08-28 20:33:23 -07:00
committed by Facebook Github Bot
parent 9970c50daf
commit 5868946818
25 changed files with 81 additions and 38 deletions

View File

@@ -61,6 +61,7 @@
"@types/react-window": "^1.8.1", "@types/react-window": "^1.8.1",
"@types/redux-persist": "^4.3.1", "@types/redux-persist": "^4.3.1",
"@types/rsocket-core": "^0.0.2", "@types/rsocket-core": "^0.0.2",
"@types/tmp": "^0.1.0",
"@types/uuid": "^3.4.5", "@types/uuid": "^3.4.5",
"@typescript-eslint/eslint-plugin": "^1.11.0", "@typescript-eslint/eslint-plugin": "^1.11.0",
"@typescript-eslint/parser": "^1.13.0", "@typescript-eslint/parser": "^1.13.0",

View File

@@ -32,7 +32,7 @@ import {
ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT, ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT,
ACTIVE_SHEET_PLUGIN_SHEET, ACTIVE_SHEET_PLUGIN_SHEET,
} from './reducers/application'; } from './reducers/application';
import {Logger} from './fb-interfaces/Logger.js'; import {Logger} from './fb-interfaces/Logger';
import BugReporter from './fb-stubs/BugReporter'; import BugReporter from './fb-stubs/BugReporter';
import BaseDevice from './devices/BaseDevice'; import BaseDevice from './devices/BaseDevice';
import {State as Store} from './reducers/index'; import {State as Store} from './reducers/index';

View File

@@ -8,7 +8,7 @@
import {FlipperPlugin, FlipperDevicePlugin} from './plugin'; import {FlipperPlugin, FlipperDevicePlugin} from './plugin';
import BaseDevice, {OS} from './devices/BaseDevice'; import BaseDevice, {OS} from './devices/BaseDevice';
import {App} from './App.js'; import {App} from './App.js';
import {Logger} from './fb-interfaces/Logger.js'; import {Logger} from './fb-interfaces/Logger';
import {Store} from './reducers/index'; import {Store} from './reducers/index';
import {setPluginState} from './reducers/pluginStates'; import {setPluginState} from './reducers/pluginStates';
import {RSocketClientSocket} from 'rsocket-core/RSocketClient'; import {RSocketClientSocket} from 'rsocket-core/RSocketClient';

View File

@@ -18,7 +18,7 @@ import {
} from 'flipper'; } from 'flipper';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {setExportStatusComponent, unsetShare} from '../reducers/application'; import {setExportStatusComponent, unsetShare} from '../reducers/application';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import {Idler} from '../utils/Idler'; import {Idler} from '../utils/Idler';
import {shareFlipperData, DataExportResult} from '../fb-stubs/user'; import {shareFlipperData, DataExportResult} from '../fb-stubs/user';
import {exportStore, EXPORT_FLIPPER_TRACE_EVENT} from '../utils/exportData'; import {exportStore, EXPORT_FLIPPER_TRACE_EVENT} from '../utils/exportData';

View File

@@ -19,7 +19,7 @@ import {setExportStatusComponent, unsetShare} from '../reducers/application';
import {reportPlatformFailures} from '../utils/metrics'; import {reportPlatformFailures} from '../utils/metrics';
import CancellableExportStatus from './CancellableExportStatus'; import CancellableExportStatus from './CancellableExportStatus';
import {performance} from 'perf_hooks'; import {performance} from 'perf_hooks';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import {Idler} from '../utils/Idler'; import {Idler} from '../utils/Idler';
import { import {
exportStoreToFile, exportStoreToFile,

View File

@@ -9,7 +9,7 @@ import AndroidDevice from '../devices/AndroidDevice';
import child_process from 'child_process'; import child_process from 'child_process';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import BaseDevice from '../devices/BaseDevice'; import BaseDevice from '../devices/BaseDevice';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import {registerDeviceCallbackOnPlugins} from '../utils/onRegisterDevice'; import {registerDeviceCallbackOnPlugins} from '../utils/onRegisterDevice';
import {getAdbClient} from '../utils/adbClient'; import {getAdbClient} from '../utils/adbClient';
import {default as which} from 'which'; import {default as which} from 'which';

View File

@@ -8,7 +8,7 @@
import {remote, ipcRenderer} from 'electron'; import {remote, ipcRenderer} from 'electron';
import {toggleAction} from '../reducers/application'; import {toggleAction} from '../reducers/application';
import {Store} from '../reducers/index.js'; import {Store} from '../reducers/index.js';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import {parseFlipperPorts} from '../utils/environmentVariables'; import {parseFlipperPorts} from '../utils/environmentVariables';
import { import {
importDataToStore, importDataToStore,

View File

@@ -6,7 +6,7 @@
*/ */
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import MacDevice from '../devices/MacDevice'; import MacDevice from '../devices/MacDevice';
import WindowsDevice from '../devices/WindowsDevice'; import WindowsDevice from '../devices/WindowsDevice';

View File

@@ -7,7 +7,7 @@
import {ChildProcess} from 'child_process'; import {ChildProcess} from 'child_process';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import {DeviceType} from '../devices/BaseDevice'; import {DeviceType} from '../devices/BaseDevice';
import {promisify} from 'util'; import {promisify} from 'util';
import path from 'path'; import path from 'path';

View File

@@ -15,7 +15,7 @@ import notifications from './notifications';
import plugins from './plugins'; import plugins from './plugins';
import user from './user'; import user from './user';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Dispatcher} from './types'; import {Dispatcher} from './types';

View File

@@ -6,7 +6,7 @@
*/ */
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import {PluginNotification} from '../reducers/notifications'; import {PluginNotification} from '../reducers/notifications';
import {FlipperPlugin, FlipperDevicePlugin} from '../plugin'; import {FlipperPlugin, FlipperDevicePlugin} from '../plugin';
import isHeadless from '../utils/isHeadless'; import isHeadless from '../utils/isHeadless';

View File

@@ -6,7 +6,7 @@
*/ */
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import {FlipperPlugin, FlipperDevicePlugin} from '../plugin'; import {FlipperPlugin, FlipperDevicePlugin} from '../plugin';
import {State} from '../reducers/plugins'; import {State} from '../reducers/plugins';
import React from 'react'; import React from 'react';

View File

@@ -8,7 +8,7 @@
import Server from '../server'; import Server from '../server';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import Client from '../Client.js'; import Client from '../Client.js';
import {UninitializedClient} from '../UninitializedClient'; import {UninitializedClient} from '../UninitializedClient';

View File

@@ -10,7 +10,7 @@ import {ipcRenderer} from 'electron';
import {performance} from 'perf_hooks'; import {performance} from 'perf_hooks';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import Client from '../Client'; import Client from '../Client';
export default (store: Store, logger: Logger) => { export default (store: Store, logger: Logger) => {

View File

@@ -6,7 +6,7 @@
*/ */
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
import {login} from '../reducers/user'; import {login} from '../reducers/user';
import {getUser, logoutUser} from '../fb-stubs/user'; import {getUser, logoutUser} from '../fb-stubs/user';

View File

@@ -14,9 +14,9 @@ export type TrackType =
| 'operation-cancelled'; | 'operation-cancelled';
export interface Logger { export interface Logger {
track(type: TrackType, event: string, data: ?any, plugin?: string): void; track(type: TrackType, event: string, data?: any, plugin?: string): void;
trackTimeSince(mark: string, eventName: ?string): void; trackTimeSince(mark: string, eventName?: string | null | undefined): void;
info(data: any, category: string): void; info(data: any, category: string): void;

View File

@@ -10,7 +10,7 @@ export type ScribeMessage = {
message: string; message: string;
}; };
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger';
export default class ScribeLogger { export default class ScribeLogger {
constructor(logger: Logger) {} constructor(logger: Logger) {}

View File

@@ -7,7 +7,7 @@
import {KeyboardActions} from './MenuBar'; import {KeyboardActions} from './MenuBar';
import {App} from './App'; import {App} from './App';
import {Logger} from './fb-interfaces/Logger.js'; import {Logger} from './fb-interfaces/Logger';
import Client from './Client'; import Client from './Client';
import {Store, MiddlewareAPI} from './reducers/index'; import {Store, MiddlewareAPI} from './reducers/index';
import {MetricType} from './utils/exportMetrics'; import {MetricType} from './utils/exportMetrics';

View File

@@ -8,7 +8,7 @@
import type {Element} from 'flipper'; import type {Element} from 'flipper';
import type {PluginClient} from 'flipper'; import type {PluginClient} from 'flipper';
import type Client from '../../Client.tsx'; import type Client from '../../Client.tsx';
import type {Logger} from '../../fb-interfaces/Logger.js'; import type {Logger} from '../../fb-interfaces/Logger.tsx';
import { import {
ManagedDataInspector, ManagedDataInspector,

View File

@@ -8,7 +8,7 @@
import {Element} from './ElementsInspector'; import {Element} from './ElementsInspector';
import {PluginClient} from '../../../plugin'; import {PluginClient} from '../../../plugin';
import Client from '../../../Client'; import Client from '../../../Client';
import {Logger} from '../../../fb-interfaces/Logger.js'; import {Logger} from '../../../fb-interfaces/Logger';
import Panel from '../Panel'; import Panel from '../Panel';
import ManagedDataInspector from '../data-inspector/ManagedDataInspector'; import ManagedDataInspector from '../data-inspector/ManagedDataInspector';
import {Component} from 'react'; import {Component} from 'react';

View File

@@ -14,16 +14,19 @@ import {
isInstalled as opensslInstalled, isInstalled as opensslInstalled,
} from './openssl-wrapper-with-promises'; } from './openssl-wrapper-with-promises';
import path from 'path'; import path from 'path';
import tmp from 'tmp'; import tmp, {DirOptions, FileOptions} from 'tmp';
const tmpFile = promisify(tmp.file);
const tmpDir = promisify(tmp.dir);
import iosUtil from '../fb-stubs/iOSContainerUtility'; import iosUtil from '../fb-stubs/iOSContainerUtility';
import {reportPlatformFailures} from './metrics'; import {reportPlatformFailures} from './metrics';
import {getAdbClient} from './adbClient'; import {getAdbClient} from './adbClient';
import * as androidUtil from './androidContainerUtility'; import * as androidUtil from './androidContainerUtility';
import os from 'os';
const tmpFile = promisify(tmp.file) as (
options?: FileOptions,
) => Promise<string>;
const tmpDir = promisify(tmp.dir) as (options?: DirOptions) => Promise<string>;
// Desktop file paths // Desktop file paths
const os = require('os');
const caKey = getFilePath('ca.key'); const caKey = getFilePath('ca.key');
const caCert = getFilePath('ca.crt'); const caCert = getFilePath('ca.crt');
const serverKey = getFilePath('server.key'); const serverKey = getFilePath('server.key');
@@ -398,7 +401,7 @@ export default class CertificateProvider {
}), }),
) )
.then(([path, subject]) => { .then(([path, subject]) => {
return new Promise(function(resolve, reject) { return new Promise<string>(function(resolve, reject) {
fs.unlink(path, err => { fs.unlink(path, err => {
if (err) { if (err) {
reject(err); reject(err);
@@ -408,7 +411,7 @@ export default class CertificateProvider {
}); });
}); });
}) })
.then((subject: string) => { .then(subject => {
const matches = subject.trim().match(x509SubjectCNRegex); const matches = subject.trim().match(x509SubjectCNRegex);
if (!matches || matches.length < 2) { if (!matches || matches.length < 2) {
throw new Error(`Cannot extract CN from ${subject}`); throw new Error(`Cannot extract CN from ${subject}`);
@@ -441,14 +444,14 @@ export default class CertificateProvider {
if (!fs.existsSync(caKey)) { if (!fs.existsSync(caKey)) {
return this.generateCertificateAuthority(); return this.generateCertificateAuthority();
} }
return this.checkCertIsValid(caCert).catch(e => return this.checkCertIsValid(caCert).catch(() =>
this.generateCertificateAuthority(), this.generateCertificateAuthority(),
); );
} }
checkCertIsValid(filename: string): Promise<void> { checkCertIsValid(filename: string): Promise<void> {
if (!fs.existsSync(filename)) { if (!fs.existsSync(filename)) {
return Promise.reject(); return Promise.reject(new Error(`${filename} does not exist`));
} }
// openssl checkend is a nice feature but it only checks for certificates // openssl checkend is a nice feature but it only checks for certificates
// expiring in the future, not those that have already expired. // expiring in the future, not those that have already expired.
@@ -459,7 +462,7 @@ export default class CertificateProvider {
checkend: minCertExpiryWindowSeconds, checkend: minCertExpiryWindowSeconds,
in: filename, in: filename,
}) })
.then(output => undefined) .then(() => undefined)
.catch(e => { .catch(e => {
console.warn(`Certificate will expire soon: ${filename}`, logTag); console.warn(`Certificate will expire soon: ${filename}`, logTag);
throw e; throw e;
@@ -492,7 +495,9 @@ export default class CertificateProvider {
} }
verifyServerCertWasIssuedByCA() { verifyServerCertWasIssuedByCA() {
const options = {CAfile: caCert}; const options: {
[key: string]: any;
} = {CAfile: caCert};
options[serverCert] = false; options[serverCert] = false;
return openssl('verify', options).then(output => { return openssl('verify', options).then(output => {
const verified = output.match(/[^:]+: OK/); const verified = output.match(/[^:]+: OK/);
@@ -534,8 +539,8 @@ export default class CertificateProvider {
} }
return this.checkCertIsValid(serverCert) return this.checkCertIsValid(serverCert)
.then(_ => this.verifyServerCertWasIssuedByCA()) .then(() => this.verifyServerCertWasIssuedByCA())
.catch(e => this.generateServerCertificate()); .catch(() => this.generateServerCertificate());
} }
generateServerCertificate(): Promise<void> { generateServerCertificate(): Promise<void> {
@@ -567,7 +572,7 @@ export default class CertificateProvider {
} }
writeToTempFile(content: string): Promise<string> { writeToTempFile(content: string): Promise<string> {
return tmpFile().then((path, fd, cleanupCallback) => return tmpFile().then(path =>
promisify(fs.writeFile)(path, content).then(_ => path), promisify(fs.writeFile)(path, content).then(_ => path),
); );
} }

View File

@@ -10,12 +10,16 @@ import {promisify} from 'util';
import {crashReporter, remote} from 'electron'; import {crashReporter, remote} from 'electron';
import isProduction from '../utils/isProduction'; import isProduction from '../utils/isProduction';
import constants from '../fb-stubs/constants'; import constants from '../fb-stubs/constants';
import {tmpName} from 'tmp'; import {tmpName as tmpNameCallback, TmpNameOptions} from 'tmp';
import {resolve} from 'path'; import {resolve} from 'path';
const tmpName = promisify(tmpNameCallback) as (
options?: TmpNameOptions,
) => Promise<string>;
// Cross platform way to find the /tmp directory or equivalent. // Cross platform way to find the /tmp directory or equivalent.
// The tempPath set should be persistent across app restarts. // The tempPath set should be persistent across app restarts.
const tempPathPromise: Promise<string> = promisify(tmpName)({ const tempPathPromise: Promise<string> = tmpName({
template: '/tmp/tmp-XXXXXX', template: '/tmp/tmp-XXXXXX',
}).then(name => resolve(name, '..', 'flipper')); }).then(name => resolve(name, '..', 'flipper'));

View File

@@ -5,16 +5,17 @@
* @format * @format
*/ */
import {exec as opensslWithCallback} from 'openssl-wrapper'; import {exec as opensslWithCallback, Action} from 'openssl-wrapper';
import child_process from 'child_process'; import child_process from 'child_process';
export function openssl(action: string, options: {}): Promise<string> { export function openssl(action: Action, options: {}): Promise<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
opensslWithCallback(action, options, (err, buffer) => { opensslWithCallback(action, options, (err, buffer) => {
if (err) { if (err) {
reject(err); reject(err);
} else if (buffer) {
resolve(buffer.toString());
} }
resolve(buffer.toString());
}); });
}); });
} }

View File

@@ -0,0 +1,27 @@
/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
declare module 'openssl-wrapper' {
export type Action =
| 'cms.verify'
| 'genrsa'
| 'pkcs12'
| 'req'
| 'req.new'
| 'req.verify'
| 'verify'
| 'rsa'
| 'smime.verify'
| 'x509.req'
| 'x509';
export function exec(
action: Action,
options: {[key: string]: string},
cb: (error: Error | undefined, buffer: Buffer | undefined) => any,
): void;
}

View File

@@ -1279,6 +1279,11 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
"@types/tmp@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.1.0.tgz#19cf73a7bcf641965485119726397a096f0049bd"
integrity sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA==
"@types/uuid@^3.4.5": "@types/uuid@^3.4.5":
version "3.4.5" version "3.4.5"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.5.tgz#d4dc10785b497a1474eae0ba7f0cb09c0ddfd6eb" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.5.tgz#d4dc10785b497a1474eae0ba7f0cb09c0ddfd6eb"