-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathio.ts
549 lines (507 loc) · 18 KB
/
io.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
/**
*
* A module containing a grab bag of support for core network I/O functionality, including sockets, TLS, DNS, logging,
* error handling, streams, and connection -> thread mapping.
*
* Categories include:
* - Network: socket configuration
* - TLS: tls configuration
* - Logging: logging controls and configuration
* - IO: everything else
*
* @packageDocumentation
* @module io
* @mergeTarget
*/
import crt_native from './binding';
import { NativeResource } from "./native_resource";
import { setLogLevel, LogLevel, TlsVersion, SocketType, SocketDomain } from '../common/io';
import { Readable } from 'stream';
// Do not re-export the logging functions in common; they are package-private
export { setLogLevel, LogLevel, TlsVersion, SocketType, SocketDomain } from '../common/io';
import { CrtError } from './error';
/**
* Convert a native error code into a human-readable string
* @param error_code - An error code returned from a native API call, or delivered
* via callback.
* @returns Long-form description of the error
* @see CrtError
*
* nodejs only.
*
* @category System
*/
export function error_code_to_string(error_code: number): string {
return crt_native.error_code_to_string(error_code);
}
/**
* Convert a native error code into a human-readable identifier
* @param error_code - An error code returned from a native API call, or delivered
* via callback.
* @return error name as a string
* @see CrtError
*
* nodejs only.
*
* @category System
*/
export function error_code_to_name(error_code: number): string {
return crt_native.error_code_to_name(error_code);
}
/**
* Enables logging of the native AWS CRT libraries.
* @param level - The logging level to filter to. It is not possible to log less than WARN.
*
* nodejs only.
* @category Logging
*/
export function enable_logging(level: LogLevel) {
crt_native.io_logging_enable(level);
setLogLevel(level);
}
/**
* Returns true if ALPN is available on this platform natively
* @return true if ALPN is supported natively, false otherwise
*
* nodejs only.
* @category TLS
*/
export function is_alpn_available(): boolean {
return crt_native.is_alpn_available();
}
/**
* Wraps a ```Readable``` for reading by native code, used to stream
* data into the AWS CRT libraries.
*
* nodejs only.
* @category IO
*/
export class InputStream extends NativeResource {
constructor(private source: Readable) {
super(crt_native.io_input_stream_new(16 * 1024));
this.source.on('data', (data) => {
data = Buffer.isBuffer(data) ? data : Buffer.from(data.toString());
crt_native.io_input_stream_append(this.native_handle(), data);
});
this.source.on('end', () => {
crt_native.io_input_stream_append(this.native_handle(), undefined);
})
}
}
/**
* Represents native resources required to bootstrap a client connection
* Things like a host resolver, event loop group, etc. There should only need
* to be 1 of these per application, in most cases.
*
* nodejs only.
* @category IO
*/
export class ClientBootstrap extends NativeResource {
constructor() {
super(crt_native.io_client_bootstrap_new());
}
}
/**
* Standard Berkeley socket style options.
*
* nodejs only.
* @category Network
*/
export class SocketOptions extends NativeResource {
constructor(
type = SocketType.STREAM,
domain = SocketDomain.IPV6,
connect_timeout_ms = 5000,
keepalive = false,
keep_alive_interval_sec = 0,
keep_alive_timeout_sec = 0,
keep_alive_max_failed_probes = 0) {
super(crt_native.io_socket_options_new(
type,
domain,
connect_timeout_ms,
keep_alive_interval_sec,
keep_alive_timeout_sec,
keep_alive_max_failed_probes,
keepalive
));
}
}
/**
* Interface used to hold the options for creating a PKCS#12 connection in the builder.
*
* Note: Only supported on MacOS devices.
*
* NodeJS only
* @category TLS
*/
export interface Pkcs12Options {
/** Path to the PKCS#12 file */
pkcs12_file: string;
/** The password for the PKCS#12 file */
pkcs12_password : string;
}
/**
* Options for creating a {@link ClientTlsContext} or {@link ServerTlsContext}.
*
* nodejs only.
* @category TLS
*/
export class TlsContextOptions {
/** Minimum version of TLS to support. Uses OS/system default if unspecified. */
public min_tls_version: TlsVersion = TlsVersion.Default;
/** Path to a single file with all trust anchors in it, in PEM format */
public ca_filepath?: string;
/** Path to directory containing trust anchors. Only used on Unix-style systems. */
public ca_dirpath?: string;
/** String with all trust anchors in it, in PEM format */
public certificate_authority?: string;
/** List of ALPN protocols to be used on platforms which support ALPN */
public alpn_list: string[] = [];
/** Path to certificate, in PEM format */
public certificate_filepath?: string;
/** Certificate, in PEM format */
public certificate?: string;
/** Path to private key, in PEM format */
public private_key_filepath?: string;
/** Private key, in PEM format */
public private_key?: string;
/** Path to certificate, in PKCS#12 format. Currently, only supported on OSX */
public pkcs12_filepath?: string;
/** Password for PKCS#12. Currently, only supported on OSX. */
public pkcs12_password?: string;
/** PKCS#11 options. Currently, only supported on Unix */
public pkcs11_options?: TlsContextOptions.Pkcs11Options;
/** Path to certificate in a Windows cert store. Windows only. */
public windows_cert_store_path?: string;
/**
* In client mode, this turns off x.509 validation. Don't do this unless you are testing.
* It is much better to just override the default trust store and pass the self-signed
* certificate as the ca_file argument.
*
* In server mode (ServerTlsContext), this defaults to false. If you want to enforce mutual TLS on the server,
* set this to true.
*/
public verify_peer: boolean = true;
/**
* Overrides the default system trust store.
* @param ca_dirpath - Only used on Unix-style systems where all trust anchors are
* stored in a directory (e.g. /etc/ssl/certs).
* @param ca_filepath - Single file containing all trust CAs, in PEM format
*/
override_default_trust_store_from_path(ca_dirpath?: string, ca_filepath?: string) {
this.ca_dirpath = ca_dirpath;
this.ca_filepath = ca_filepath;
}
/**
* Overrides the default system trust store.
* @param certificate_authority - String containing all trust CAs, in PEM format
*/
override_default_trust_store(certificate_authority: string) {
this.certificate_authority = certificate_authority;
}
/**
* Create options configured for mutual TLS in client mode,
* with client certificate and private key provided as in-memory strings.
* @param certificate - Client certificate file contents, in PEM format
* @param private_key - Client private key file contents, in PEM format
*
* @returns newly configured TlsContextOptions object
*/
static create_client_with_mtls(certificate: string, private_key: string): TlsContextOptions {
let opt = new TlsContextOptions();
opt.certificate = certificate;
opt.private_key = private_key;
opt.verify_peer = true;
return opt;
}
/**
* Create options configured for mutual TLS in client mode,
* with client certificate and private key provided via filepath.
* @param certificate_filepath - Path to client certificate, in PEM format
* @param private_key_filepath - Path to private key, in PEM format
*
* @returns newly configured TlsContextOptions object
*/
static create_client_with_mtls_from_path(certificate_filepath: string, private_key_filepath: string): TlsContextOptions {
let opt = new TlsContextOptions();
opt.certificate_filepath = certificate_filepath;
opt.private_key_filepath = private_key_filepath;
opt.verify_peer = true;
return opt;
}
/**
* Create options for mutual TLS in client mode,
* with client certificate and private key bundled in a single PKCS#12 file.
* @param pkcs12_filepath - Path to PKCS#12 file containing client certificate and private key.
* @param pkcs12_password - PKCS#12 password
*
* @returns newly configured TlsContextOptions object
*/
static create_client_with_mtls_pkcs12_from_path(pkcs12_filepath: string, pkcs12_password: string): TlsContextOptions {
let opt = new TlsContextOptions();
opt.pkcs12_filepath = pkcs12_filepath;
opt.pkcs12_password = pkcs12_password;
opt.verify_peer = true;
return opt;
}
/**
* @deprecated Renamed [[create_client_with_mtls_pkcs12_from_path]]
*/
static create_client_with_mtls_pkcs_from_path(pkcs12_filepath: string, pkcs12_password: string): TlsContextOptions {
return this.create_client_with_mtls_pkcs12_from_path(pkcs12_filepath, pkcs12_password);
}
/**
* Create options configured for mutual TLS in client mode,
* using a PKCS#11 library for private key operations.
*
* NOTE: This configuration only works on Unix devices.
*
* @param options - PKCS#11 options
*
* @returns newly configured TlsContextOptions object
*/
static create_client_with_mtls_pkcs11(options: TlsContextOptions.Pkcs11Options): TlsContextOptions {
let opt = new TlsContextOptions();
opt.pkcs11_options = options;
opt.verify_peer = true;
return opt;
}
/**
* Create options configured for mutual TLS in client mode,
* using a certificate in a Windows certificate store.
*
* NOTE: Windows only.
*
* @param certificate_path - Path to certificate in a Windows certificate store.
* The path must use backslashes and end with the certificate's thumbprint.
* Example: `CurrentUser\MY\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6`
*/
static create_client_with_mtls_windows_cert_store_path(certificate_path: string): TlsContextOptions {
let opt = new TlsContextOptions();
opt.windows_cert_store_path = certificate_path;
opt.verify_peer = true;
return opt;
}
/**
* Creates TLS context with peer verification disabled, along with a certificate and private key
* @param certificate_filepath - Path to certificate, in PEM format
* @param private_key_filepath - Path to private key, in PEM format
*
* @returns newly configured TlsContextOptions object
*/
static create_server_with_mtls_from_path(certificate_filepath: string, private_key_filepath: string): TlsContextOptions {
let opt = new TlsContextOptions();
opt.certificate_filepath = certificate_filepath;
opt.private_key_filepath = private_key_filepath;
opt.verify_peer = false;
return opt;
}
/**
* Creates TLS context with peer verification disabled, along with a certificate and private key
* in PKCS#12 format
* @param pkcs12_filepath - Path to certificate, in PKCS#12 format
* @param pkcs12_password - PKCS#12 Password
*
* @returns newly configured TlsContextOptions object
*/
static create_server_with_mtls_pkcs_from_path(pkcs12_filepath: string, pkcs12_password: string): TlsContextOptions {
let opt = new TlsContextOptions();
opt.pkcs12_filepath = pkcs12_filepath;
opt.pkcs12_password = pkcs12_password;
opt.verify_peer = false;
return opt;
}
}
export namespace TlsContextOptions {
/**
* Options for TLS using a PKCS#11 library for private key operations.
*
* Unix only. nodejs only.
*
* @see [[TlsContextOptions.create_client_with_mtls_pkcs11]]
*/
export type Pkcs11Options = {
/**
* Use this PKCS#11 library.
*/
pkcs11_lib: Pkcs11Lib,
/**
* Use this PIN to log the user into the PKCS#11 token. Pass `null`
* to log into a token with a "protected authentication path".
*/
user_pin: null | string,
/**
* Specify the slot ID containing a PKCS#11 token. If not specified, the token
* will be chosen based on other criteria (such as [[token_label]]).
*/
slot_id?: number,
/**
* Specify the label of the PKCS#11 token to use. If not specified, the token
* will be chosen based on other criteria (such as [[slot_id]]).
*/
token_label?: string,
/**
* Specify the label of the private key object on the PKCS#11 token. If not
* specified, the key will be chosen based on other criteria (such as being the
* only available private key on the token).
*/
private_key_object_label?: string,
/**
* Use this X.509 certificate (file on disk).
* The certificate must be PEM-formatted.
* The certificate may be specified by other means instead
* (ex: [[cert_file_contents]])
*/
cert_file_path?: string,
/**
* Use this X.509 certificate (contents in memory).
* The certificate must be PEM-formatted.
* The certificate may be specified by other means instead
* (ex: [[cert_file_path]])
*/
cert_file_contents?: string,
}
}
/**
* Abstract base TLS context used for client/server TLS communications over sockets.
*
* @see ClientTlsContext
* @see ServerTlsContext
*
* nodejs only.
* @category TLS
*/
export abstract class TlsContext extends NativeResource {
constructor(ctx_opt: TlsContextOptions) {
if (ctx_opt == null || ctx_opt == undefined) {
throw new CrtError("TlsContext constructor: ctx_opt not defined");
}
super(crt_native.io_tls_ctx_new(
ctx_opt.min_tls_version,
ctx_opt.ca_filepath,
ctx_opt.ca_dirpath,
ctx_opt.certificate_authority,
(ctx_opt.alpn_list && ctx_opt.alpn_list.length > 0) ? ctx_opt.alpn_list.join(';') : undefined,
ctx_opt.certificate_filepath,
ctx_opt.certificate,
ctx_opt.private_key_filepath,
ctx_opt.private_key,
ctx_opt.pkcs12_filepath,
ctx_opt.pkcs12_password,
ctx_opt.pkcs11_options,
ctx_opt.windows_cert_store_path,
ctx_opt.verify_peer));
}
}
/**
* TLS context used for client TLS communications over sockets. If no
* options are supplied, the context will default to enabling peer verification
* only.
*
* nodejs only.
* @category TLS
*/
export class ClientTlsContext extends TlsContext {
constructor(ctx_opt?: TlsContextOptions) {
if (!ctx_opt) {
ctx_opt = new TlsContextOptions()
ctx_opt.verify_peer = true;
}
super(ctx_opt);
}
}
/**
* TLS context used for server TLS communications over sockets. If no
* options are supplied, the context will default to disabling peer verification
* only.
*
* nodejs only.
* @category TLS
*/
export class ServerTlsContext extends TlsContext {
constructor(ctx_opt?: TlsContextOptions) {
if (!ctx_opt) {
ctx_opt = new TlsContextOptions();
ctx_opt.verify_peer = false;
}
super(ctx_opt);
}
}
/**
* TLS options that are unique to a given connection using a shared TlsContext.
*
* nodejs only.
* @category TLS
*/
export class TlsConnectionOptions extends NativeResource {
constructor(readonly tls_ctx: TlsContext, readonly server_name?: string, readonly alpn_list: string[] = []) {
if (tls_ctx == null || tls_ctx == undefined) {
throw new CrtError("TlsConnectionOptions constructor: tls_ctx not defined");
}
super(crt_native.io_tls_connection_options_new(
tls_ctx.native_handle(),
server_name,
(alpn_list && alpn_list.length > 0) ? alpn_list.join(';') : undefined
));
}
}
/**
* Handle to a loaded PKCS#11 library.
*
* For most use cases, a single instance of Pkcs11Lib should be used
* for the lifetime of your application.
*
* nodejs only.
* @category TLS
*/
export class Pkcs11Lib extends NativeResource {
/**
* @param path - Path to PKCS#11 library.
* @param behavior - Specifies how `C_Initialize()` and `C_Finalize()`
* will be called on the PKCS#11 library.
*/
constructor(path: string, behavior: Pkcs11Lib.InitializeFinalizeBehavior = Pkcs11Lib.InitializeFinalizeBehavior.DEFAULT) {
super(crt_native.io_pkcs11_lib_new(path, behavior));
}
/**
* Release the PKCS#11 library immediately, without waiting for the GC.
*/
close() {
crt_native.io_pkcs11_lib_close(this.native_handle());
}
}
export namespace Pkcs11Lib {
/**
* Controls `C_Initialize()` and `C_Finalize()` are called on the PKCS#11 library.
*/
export enum InitializeFinalizeBehavior {
/**
* Default behavior that accommodates most use cases.
*
* `C_Initialize()` is called on creation, and "already-initialized"
* errors are ignored. `C_Finalize()` is never called, just in case
* another part of your application is still using the PKCS#11 library.
*/
DEFAULT = 0,
/**
* Skip calling `C_Initialize()` and `C_Finalize()`.
*
* Use this if your application has already initialized the PKCS#11 library,
* and you do not want `C_Initialize()` called again.
*/
OMIT = 1,
/**
* `C_Initialize()` is called on creation and `C_Finalize()` is called on cleanup.
*
* If `C_Initialize()` reports that's it's already initialized, this is
* treated as an error. Use this if you need perfect cleanup (ex: running
* valgrind with --leak-check).
*/
STRICT = 2,
}
}