Introduce ServerAdapter
Summary: Introduce ServerAdapter which should be used as a base class for different server implementations e.g. RSocket, WebSocket. The type is not used elsewhere at this point but this is a good chance to look at the API and suggest changes and/or improvements. Reviewed By: passy Differential Revision: D29958434 fbshipit-source-id: 50ba46332d40e836b0a87bcf354d3237bf8fe7c5
This commit is contained in:
committed by
Facebook GitHub Bot
parent
06d45247b4
commit
b0e47bf75e
173
desktop/app/src/comms/ServerAdapter.tsx
Normal file
173
desktop/app/src/comms/ServerAdapter.tsx
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
CertificateExchangeMedium,
|
||||||
|
SecureServerConfig,
|
||||||
|
} from '../utils/CertificateProvider';
|
||||||
|
import Client, {ClientQuery} from '../Client';
|
||||||
|
import {ClientConnection} from './ClientConnection';
|
||||||
|
import {transformCertificateExchangeMediumToType} from './Utilities';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClientCsrQuery defines a client query with CSR
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
export type ClientCsrQuery = {
|
||||||
|
csr?: string | undefined;
|
||||||
|
csr_path?: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SecureClientQuery combines a ClientQuery with
|
||||||
|
* ClientCsrQuery. It also adds medium information.
|
||||||
|
*/
|
||||||
|
export type SecureClientQuery = ClientQuery &
|
||||||
|
ClientCsrQuery & {medium: number | undefined};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines an interface for events triggered by a running server interacting
|
||||||
|
* with a client.
|
||||||
|
*/
|
||||||
|
export interface ServerEventsListener {
|
||||||
|
/**
|
||||||
|
* Server started and listening at the specified port.
|
||||||
|
* @param port The port in which the server is listening to.
|
||||||
|
*/
|
||||||
|
onListening(port: number): void;
|
||||||
|
/**
|
||||||
|
* An insecure connection attempt has been made by a client. At this
|
||||||
|
* point, a connection should be already be available but needs to be
|
||||||
|
* validated by the server.
|
||||||
|
* @param clientQuery A ClientQuery instance containing metadata about
|
||||||
|
* the client e.g. OS, device, app, etc.
|
||||||
|
*/
|
||||||
|
onConnectionAttempt(clientQuery: ClientQuery): void;
|
||||||
|
/**
|
||||||
|
* A TLS connection attempt has been made by a client. At this
|
||||||
|
* point, a connection should be already be available but needs to be
|
||||||
|
* validated by the server.
|
||||||
|
* @param clientQuery A SecureClientQuery instance containing metadata about
|
||||||
|
* the client and CSR information as exchanged on the previously
|
||||||
|
* established insecure connection.
|
||||||
|
*/
|
||||||
|
onSecureConnectionAttempt(clientQuery: SecureClientQuery): void;
|
||||||
|
/**
|
||||||
|
* CSR received by the server and needs to be processed. If successfully
|
||||||
|
* processed, it should return a generated device identifier.
|
||||||
|
* @param unsanitizedCSR CSR as sent by the client, will need to be sanitized
|
||||||
|
* before usage.
|
||||||
|
* @param clientQuery A ClientQuery instance containing metadata about
|
||||||
|
* the client e.g. OS, device, app, etc.
|
||||||
|
* @param appDirectory App directory in which to deploy the CA and client
|
||||||
|
* certificates.
|
||||||
|
* @param medium Certificate exchange medium type e.g. FS_ACCESS, WWW.
|
||||||
|
*/
|
||||||
|
onProcessCSR(
|
||||||
|
unsanitizedCSR: string,
|
||||||
|
clientQuery: ClientQuery,
|
||||||
|
appDirectory: string,
|
||||||
|
medium: CertificateExchangeMedium,
|
||||||
|
): Promise<{deviceId: string}>;
|
||||||
|
/**
|
||||||
|
* A secure connection has been established with a validated client.
|
||||||
|
* A promise to a Client instance needs to be returned.
|
||||||
|
* @param clientQuery A SecureClientQuery instance containing metadata about
|
||||||
|
* the client and CSR information as exchanged on the previously
|
||||||
|
* established insecure connection.
|
||||||
|
* @param clientConnection A valid client connection.
|
||||||
|
*/
|
||||||
|
onConnectionCreated(
|
||||||
|
clientQuery: SecureClientQuery,
|
||||||
|
clientConnection: ClientConnection,
|
||||||
|
): Promise<Client>;
|
||||||
|
/**
|
||||||
|
* A connection with a client has been closed.
|
||||||
|
* @param id The client identifier.
|
||||||
|
*/
|
||||||
|
onConnectionClosed(id: string): void;
|
||||||
|
/**
|
||||||
|
* An error has occurred.
|
||||||
|
* @param error An Error instance.
|
||||||
|
*/
|
||||||
|
onError(error: Error): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the base class to be used by any server implementation e.g.
|
||||||
|
* RSocket, WebSocket, etc.
|
||||||
|
*/
|
||||||
|
abstract class ServerAdapter {
|
||||||
|
listener: ServerEventsListener;
|
||||||
|
|
||||||
|
constructor(listener: ServerEventsListener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start and bind server to the specified port.
|
||||||
|
* @param port A port number.
|
||||||
|
* @param sslConfig An optional SSL configuration to be used for
|
||||||
|
* TLS servers.
|
||||||
|
*/
|
||||||
|
abstract start(
|
||||||
|
port: number,
|
||||||
|
sslConfig?: SecureServerConfig,
|
||||||
|
): Promise<boolean>;
|
||||||
|
/**
|
||||||
|
* Stop the server.
|
||||||
|
*/
|
||||||
|
abstract stop(): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a message received over an insecure connection. The only
|
||||||
|
* supported message is to sign certificates.
|
||||||
|
* @param clientQuery A ClientQuery instance containing metadata about
|
||||||
|
* the client e.g. OS, device, app, etc.
|
||||||
|
* @param rawData Raw data as sent by the client.
|
||||||
|
* @returns The response to be sent back to the client. If the received
|
||||||
|
* request is to sign a certificate and no errors were found, the response
|
||||||
|
* should contain the device identifier to use by the client.
|
||||||
|
*/
|
||||||
|
async _onHandleUntrustedMessage(
|
||||||
|
clientQuery: ClientQuery,
|
||||||
|
rawData: any,
|
||||||
|
): Promise<any> {
|
||||||
|
// OSS's older Client SDK might not send medium information.
|
||||||
|
// This is not an issue for internal FB users, as Flipper release
|
||||||
|
// is insync with client SDK through launcher.
|
||||||
|
const message: {
|
||||||
|
method: 'signCertificate';
|
||||||
|
csr: string;
|
||||||
|
destination: string;
|
||||||
|
medium: number | undefined;
|
||||||
|
} = rawData;
|
||||||
|
|
||||||
|
if (message.method === 'signCertificate') {
|
||||||
|
console.debug('CSR received from device', 'server');
|
||||||
|
|
||||||
|
const {csr, destination, medium} = message;
|
||||||
|
|
||||||
|
const result = await this.listener.onProcessCSR(
|
||||||
|
csr,
|
||||||
|
clientQuery,
|
||||||
|
destination,
|
||||||
|
transformCertificateExchangeMediumToType(medium),
|
||||||
|
);
|
||||||
|
const response = JSON.stringify({
|
||||||
|
deviceId: result.deviceId,
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServerAdapter;
|
||||||
Reference in New Issue
Block a user