mirror of
https://github.com/denoland/deno.git
synced 2025-02-07 23:06:50 -05:00
feat(ext/net): extract TLS key and certificate from interfaces (#23327)
Relands #23325
This commit is contained in:
parent
5e2a747685
commit
6a09a16d71
7 changed files with 277 additions and 127 deletions
33
cli/tsc/dts/lib.deno.ns.d.ts
vendored
33
cli/tsc/dts/lib.deno.ns.d.ts
vendored
|
@ -6277,11 +6277,23 @@ declare namespace Deno {
|
||||||
* @category HTTP Server
|
* @category HTTP Server
|
||||||
*/
|
*/
|
||||||
export interface ServeTlsOptions extends ServeOptions {
|
export interface ServeTlsOptions extends ServeOptions {
|
||||||
/** Server private key in PEM format */
|
/**
|
||||||
cert: string;
|
* Server private key in PEM format. Use {@linkcode TlsCertifiedKeyOptions} instead.
|
||||||
|
*
|
||||||
|
* @deprecated This will be removed in Deno 2.0. See the
|
||||||
|
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||||
|
* for migration instructions.
|
||||||
|
*/
|
||||||
|
cert?: string;
|
||||||
|
|
||||||
/** Cert chain in PEM format */
|
/**
|
||||||
key: string;
|
* Cert chain in PEM format. Use {@linkcode TlsCertifiedKeyOptions} instead.
|
||||||
|
*
|
||||||
|
* @deprecated This will be removed in Deno 2.0. See the
|
||||||
|
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||||
|
* for migration instructions.
|
||||||
|
*/
|
||||||
|
key?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6490,7 +6502,10 @@ declare namespace Deno {
|
||||||
* @category HTTP Server
|
* @category HTTP Server
|
||||||
*/
|
*/
|
||||||
export function serve(
|
export function serve(
|
||||||
options: ServeOptions | ServeTlsOptions,
|
options:
|
||||||
|
| ServeOptions
|
||||||
|
| ServeTlsOptions
|
||||||
|
| (ServeTlsOptions & TlsCertifiedKeyOptions),
|
||||||
handler: ServeHandler,
|
handler: ServeHandler,
|
||||||
): HttpServer;
|
): HttpServer;
|
||||||
/** Serves HTTP requests with the given option bag.
|
/** Serves HTTP requests with the given option bag.
|
||||||
|
@ -6546,6 +6561,12 @@ declare namespace Deno {
|
||||||
* @category HTTP Server
|
* @category HTTP Server
|
||||||
*/
|
*/
|
||||||
export function serve(
|
export function serve(
|
||||||
options: ServeInit & (ServeOptions | ServeTlsOptions),
|
options:
|
||||||
|
& ServeInit
|
||||||
|
& (
|
||||||
|
| ServeOptions
|
||||||
|
| ServeTlsOptions
|
||||||
|
| (ServeTlsOptions & TlsCertifiedKeyOptions)
|
||||||
|
),
|
||||||
): HttpServer;
|
): HttpServer;
|
||||||
}
|
}
|
||||||
|
|
25
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
25
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
|
@ -882,10 +882,6 @@ declare namespace Deno {
|
||||||
caCerts?: string[];
|
caCerts?: string[];
|
||||||
/** A HTTP proxy to use for new connections. */
|
/** A HTTP proxy to use for new connections. */
|
||||||
proxy?: Proxy;
|
proxy?: Proxy;
|
||||||
/** Cert chain in PEM format. */
|
|
||||||
cert?: string;
|
|
||||||
/** Server private key in PEM format. */
|
|
||||||
key?: string;
|
|
||||||
/** Sets the maximum numer of idle connections per host allowed in the pool. */
|
/** Sets the maximum numer of idle connections per host allowed in the pool. */
|
||||||
poolMaxIdlePerHost?: number;
|
poolMaxIdlePerHost?: number;
|
||||||
/** Set an optional timeout for idle sockets being kept-alive.
|
/** Set an optional timeout for idle sockets being kept-alive.
|
||||||
|
@ -962,6 +958,27 @@ declare namespace Deno {
|
||||||
options: CreateHttpClientOptions,
|
options: CreateHttpClientOptions,
|
||||||
): HttpClient;
|
): HttpClient;
|
||||||
|
|
||||||
|
/** **UNSTABLE**: New API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* Create a custom HttpClient to use with {@linkcode fetch}. This is an
|
||||||
|
* extension of the web platform Fetch API which allows Deno to use custom
|
||||||
|
* TLS certificates and connect via a proxy while using `fetch()`.
|
||||||
|
*
|
||||||
|
* @example ```ts
|
||||||
|
* const caCert = await Deno.readTextFile("./ca.pem");
|
||||||
|
* // Load a client key and certificate that we'll use to connect
|
||||||
|
* const key = await Deno.readTextFile("./key.key");
|
||||||
|
* const cert = await Deno.readTextFile("./cert.crt");
|
||||||
|
* const client = Deno.createHttpClient({ caCerts: [ caCert ], key, cert });
|
||||||
|
* const response = await fetch("https://myserver.com", { client });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @category Fetch API
|
||||||
|
*/
|
||||||
|
export function createHttpClient(
|
||||||
|
options: CreateHttpClientOptions & TlsCertifiedKeyOptions,
|
||||||
|
): HttpClient;
|
||||||
|
|
||||||
/** **UNSTABLE**: New API, yet to be vetted.
|
/** **UNSTABLE**: New API, yet to be vetted.
|
||||||
*
|
*
|
||||||
* Represents membership of a IPv4 multicast group.
|
* Represents membership of a IPv4 multicast group.
|
||||||
|
|
|
@ -25,12 +25,7 @@ const { ObjectDefineProperty } = primordials;
|
||||||
*/
|
*/
|
||||||
function createHttpClient(options) {
|
function createHttpClient(options) {
|
||||||
options.caCerts ??= [];
|
options.caCerts ??= [];
|
||||||
const keyPair = loadTlsKeyPair(
|
const keyPair = loadTlsKeyPair("Deno.createHttpClient", options);
|
||||||
options.cert,
|
|
||||||
undefined,
|
|
||||||
options.key,
|
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
return new HttpClient(
|
return new HttpClient(
|
||||||
op_fetch_custom_client(
|
op_fetch_custom_client(
|
||||||
options,
|
options,
|
||||||
|
|
|
@ -51,54 +51,46 @@ async function connectTls({
|
||||||
port,
|
port,
|
||||||
hostname = "127.0.0.1",
|
hostname = "127.0.0.1",
|
||||||
transport = "tcp",
|
transport = "tcp",
|
||||||
certFile = undefined,
|
|
||||||
caCerts = [],
|
caCerts = [],
|
||||||
certChain = undefined,
|
|
||||||
privateKey = undefined,
|
|
||||||
cert = undefined,
|
|
||||||
key = undefined,
|
|
||||||
alpnProtocols = undefined,
|
alpnProtocols = undefined,
|
||||||
|
keyFormat = undefined,
|
||||||
|
cert = undefined,
|
||||||
|
certFile = undefined,
|
||||||
|
certChain = undefined,
|
||||||
|
key = undefined,
|
||||||
|
keyFile = undefined,
|
||||||
|
privateKey = undefined,
|
||||||
}) {
|
}) {
|
||||||
if (certFile !== undefined) {
|
|
||||||
internals.warnOnDeprecatedApi(
|
|
||||||
"Deno.ConnectTlsOptions.certFile",
|
|
||||||
new Error().stack,
|
|
||||||
"Pass the cert file contents to the `Deno.ConnectTlsOptions.cert` option instead.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (certChain !== undefined) {
|
|
||||||
internals.warnOnDeprecatedApi(
|
|
||||||
"Deno.ConnectTlsOptions.certChain",
|
|
||||||
new Error().stack,
|
|
||||||
"Use the `Deno.ConnectTlsOptions.cert` option instead.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (privateKey !== undefined) {
|
|
||||||
internals.warnOnDeprecatedApi(
|
|
||||||
"Deno.ConnectTlsOptions.privateKey",
|
|
||||||
new Error().stack,
|
|
||||||
"Use the `Deno.ConnectTlsOptions.key` option instead.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (transport !== "tcp") {
|
if (transport !== "tcp") {
|
||||||
throw new TypeError(`Unsupported transport: '${transport}'`);
|
throw new TypeError(`Unsupported transport: '${transport}'`);
|
||||||
}
|
}
|
||||||
if (certChain !== undefined && cert !== undefined) {
|
let deprecatedCertFile = undefined;
|
||||||
throw new TypeError(
|
|
||||||
"Cannot specify both `certChain` and `cert`",
|
// Deno.connectTls has an irregular option where you can just pass `certFile` and
|
||||||
|
// not `keyFile`. In this case it's used for `caCerts` rather than the client key.
|
||||||
|
if (certFile !== undefined && keyFile === undefined) {
|
||||||
|
internals.warnOnDeprecatedApi(
|
||||||
|
"Deno.ConnectTlsOptions.certFile",
|
||||||
|
new Error().stack,
|
||||||
|
"Pass the cert file's contents to the `Deno.ConnectTlsOptions.caCerts` option instead.",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
deprecatedCertFile = certFile;
|
||||||
|
certFile = undefined;
|
||||||
}
|
}
|
||||||
if (privateKey !== undefined && key !== undefined) {
|
|
||||||
throw new TypeError(
|
const keyPair = loadTlsKeyPair("Deno.connectTls", {
|
||||||
"Cannot specify both `privateKey` and `key`",
|
keyFormat,
|
||||||
);
|
cert,
|
||||||
}
|
certFile,
|
||||||
cert ??= certChain;
|
certChain,
|
||||||
key ??= privateKey;
|
key,
|
||||||
const keyPair = loadTlsKeyPair(cert, undefined, key, undefined);
|
keyFile,
|
||||||
|
privateKey,
|
||||||
|
});
|
||||||
const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_connect_tls(
|
const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_connect_tls(
|
||||||
{ hostname, port },
|
{ hostname, port },
|
||||||
{ certFile, caCerts, cert, key, alpnProtocols },
|
{ certFile: deprecatedCertFile, caCerts, alpnProtocols },
|
||||||
keyPair,
|
keyPair,
|
||||||
);
|
);
|
||||||
localAddr.transport = "tcp";
|
localAddr.transport = "tcp";
|
||||||
|
@ -137,29 +129,96 @@ class TlsListener extends Listener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this object has the shape of one of the certified key material
|
||||||
|
* interfaces.
|
||||||
|
*/
|
||||||
function hasTlsKeyPairOptions(options) {
|
function hasTlsKeyPairOptions(options) {
|
||||||
return (ReflectHas(options, "cert") || ReflectHas(options, "key") ||
|
return (ReflectHas(options, "cert") || ReflectHas(options, "key") ||
|
||||||
ReflectHas(options, "certFile") ||
|
ReflectHas(options, "certFile") ||
|
||||||
ReflectHas(options, "keyFile"));
|
ReflectHas(options, "keyFile") || ReflectHas(options, "privateKey") ||
|
||||||
|
ReflectHas(options, "certChain"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadTlsKeyPair(
|
/**
|
||||||
|
* Loads a TLS keypair from one of the various options. If no key material is provided,
|
||||||
|
* returns a special Null keypair.
|
||||||
|
*/
|
||||||
|
function loadTlsKeyPair(api, {
|
||||||
|
keyFormat,
|
||||||
cert,
|
cert,
|
||||||
certFile,
|
certFile,
|
||||||
|
certChain,
|
||||||
key,
|
key,
|
||||||
keyFile,
|
keyFile,
|
||||||
) {
|
privateKey,
|
||||||
if ((certFile !== undefined) ^ (keyFile !== undefined)) {
|
}) {
|
||||||
throw new TypeError(
|
// Check for "pem" format
|
||||||
"If certFile is specified, keyFile must also be specified",
|
if (keyFormat !== undefined && keyFormat !== "pem") {
|
||||||
);
|
throw new TypeError('If `keyFormat` is specified, it must be "pem"');
|
||||||
}
|
|
||||||
if ((cert !== undefined) ^ (key !== undefined)) {
|
|
||||||
throw new TypeError("If cert is specified, key must also be specified");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function exclusive(a1, a1v, a2, a2v) {
|
||||||
|
if (a1v !== undefined && a2v !== undefined) {
|
||||||
|
throw new TypeError(
|
||||||
|
`Cannot specify both \`${a1}\` and \`${a2}\` for \`${api}\`.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that only one pair is valid
|
||||||
|
exclusive("certChain", certChain, "cert", cert);
|
||||||
|
exclusive("certChain", certChain, "certFile", certFile);
|
||||||
|
exclusive("key", key, "keyFile", keyFile);
|
||||||
|
exclusive("key", key, "privateKey", privateKey);
|
||||||
|
|
||||||
|
function both(a1, a1v, a2, a2v) {
|
||||||
|
if (a1v !== undefined && a2v === undefined) {
|
||||||
|
throw new TypeError(
|
||||||
|
`If \`${a1}\` is specified, \`${a2}\` must be specified as well for \`${api}\`.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (a1v === undefined && a2v !== undefined) {
|
||||||
|
throw new TypeError(
|
||||||
|
`If \`${a2}\` is specified, \`${a1}\` must be specified as well for \`${api}\`.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick one pair of cert/key, certFile/keyFile or certChain/privateKey
|
||||||
|
both("cert", cert, "key", key);
|
||||||
|
both("certFile", certFile, "keyFile", keyFile);
|
||||||
|
both("certChain", certChain, "privateKey", privateKey);
|
||||||
|
|
||||||
if (certFile !== undefined) {
|
if (certFile !== undefined) {
|
||||||
return op_tls_key_static_from_file("Deno.listenTls", certFile, keyFile);
|
internals.warnOnDeprecatedApi(
|
||||||
|
"Deno.TlsCertifiedKeyOptions.keyFile",
|
||||||
|
new Error().stack,
|
||||||
|
"Pass the key file's contents to the `Deno.TlsCertifiedKeyPem.key` option instead.",
|
||||||
|
);
|
||||||
|
internals.warnOnDeprecatedApi(
|
||||||
|
"Deno.TlsCertifiedKeyOptions.certFile",
|
||||||
|
new Error().stack,
|
||||||
|
"Pass the cert file's contents to the `Deno.TlsCertifiedKeyPem.cert` option instead.",
|
||||||
|
);
|
||||||
|
return op_tls_key_static_from_file(api, certFile, keyFile);
|
||||||
|
} else if (certChain !== undefined) {
|
||||||
|
if (api !== "Deno.connectTls") {
|
||||||
|
throw new TypeError(
|
||||||
|
`Invalid options 'certChain' and 'privateKey' for ${api}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
internals.warnOnDeprecatedApi(
|
||||||
|
"Deno.TlsCertifiedKeyOptions.privateKey",
|
||||||
|
new Error().stack,
|
||||||
|
"Use the `Deno.TlsCertifiedKeyPem.key` option instead.",
|
||||||
|
);
|
||||||
|
internals.warnOnDeprecatedApi(
|
||||||
|
"Deno.TlsCertifiedKeyOptions.certChain",
|
||||||
|
new Error().stack,
|
||||||
|
"Use the `Deno.TlsCertifiedKeyPem.cert` option instead.",
|
||||||
|
);
|
||||||
|
return op_tls_key_static(certChain, privateKey);
|
||||||
} else if (cert !== undefined) {
|
} else if (cert !== undefined) {
|
||||||
return op_tls_key_static(cert, key);
|
return op_tls_key_static(cert, key);
|
||||||
} else {
|
} else {
|
||||||
|
@ -169,10 +228,6 @@ function loadTlsKeyPair(
|
||||||
|
|
||||||
function listenTls({
|
function listenTls({
|
||||||
port,
|
port,
|
||||||
cert,
|
|
||||||
certFile,
|
|
||||||
key,
|
|
||||||
keyFile,
|
|
||||||
hostname = "0.0.0.0",
|
hostname = "0.0.0.0",
|
||||||
transport = "tcp",
|
transport = "tcp",
|
||||||
alpnProtocols = undefined,
|
alpnProtocols = undefined,
|
||||||
|
@ -181,22 +236,13 @@ function listenTls({
|
||||||
if (transport !== "tcp") {
|
if (transport !== "tcp") {
|
||||||
throw new TypeError(`Unsupported transport: '${transport}'`);
|
throw new TypeError(`Unsupported transport: '${transport}'`);
|
||||||
}
|
}
|
||||||
if (keyFile !== undefined) {
|
|
||||||
internals.warnOnDeprecatedApi(
|
|
||||||
"Deno.ListenTlsOptions.keyFile",
|
|
||||||
new Error().stack,
|
|
||||||
"Pass the key file contents to the `Deno.ListenTlsOptions.key` option instead.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (certFile !== undefined) {
|
|
||||||
internals.warnOnDeprecatedApi(
|
|
||||||
"Deno.ListenTlsOptions.certFile",
|
|
||||||
new Error().stack,
|
|
||||||
"Pass the cert file contents to the `Deno.ListenTlsOptions.cert` option instead.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const keyPair = loadTlsKeyPair(cert, certFile, key, keyFile);
|
if (!hasTlsKeyPairOptions(arguments[0])) {
|
||||||
|
throw new TypeError(
|
||||||
|
"A key and certificate are required for `Deno.listenTls`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const keyPair = loadTlsKeyPair("Deno.listenTls", arguments[0]);
|
||||||
const { 0: rid, 1: localAddr } = op_net_listen_tls(
|
const { 0: rid, 1: localAddr } = op_net_listen_tls(
|
||||||
{ hostname, port: Number(port) },
|
{ hostname, port: Number(port) },
|
||||||
{ alpnProtocols, reusePort },
|
{ alpnProtocols, reusePort },
|
||||||
|
|
139
ext/net/lib.deno_net.d.ts
vendored
139
ext/net/lib.deno_net.d.ts
vendored
|
@ -197,12 +197,50 @@ declare namespace Deno {
|
||||||
options: UnixListenOptions & { transport: "unix" },
|
options: UnixListenOptions & { transport: "unix" },
|
||||||
): UnixListener;
|
): UnixListener;
|
||||||
|
|
||||||
/** @category Network */
|
/** Provides TLS certified keys, ie: a key that has been certified by a trusted certificate authority.
|
||||||
export interface ListenTlsOptions extends TcpListenOptions {
|
* A certified key generally consists of a private key and certificate part.
|
||||||
/** Server private key in PEM format */
|
*
|
||||||
key?: string;
|
* @category Network
|
||||||
/** Cert chain in PEM format */
|
*/
|
||||||
cert?: string;
|
export type TlsCertifiedKeyOptions =
|
||||||
|
| TlsCertifiedKeyPem
|
||||||
|
| TlsCertifiedKeyFromFile
|
||||||
|
| TlsCertifiedKeyConnectTls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides certified key material from strings. The key material is provided in
|
||||||
|
* `PEM`-format (Privacy Enhanced Mail, https://www.rfc-editor.org/rfc/rfc1422) which can be identified by having
|
||||||
|
* `-----BEGIN-----` and `-----END-----` markers at the beginning and end of the strings. This type of key is not compatible
|
||||||
|
* with `DER`-format keys which are binary.
|
||||||
|
*
|
||||||
|
* Deno supports RSA, EC, and PKCS8-format keys.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const key = {
|
||||||
|
* key: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
|
||||||
|
* cert: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n" }
|
||||||
|
* };
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @category Network
|
||||||
|
*/
|
||||||
|
export interface TlsCertifiedKeyPem {
|
||||||
|
/** The format of this key material, which must be PEM. */
|
||||||
|
keyFormat?: "pem";
|
||||||
|
/** Private key in `PEM` format. RSA, EC, and PKCS8-format keys are supported. */
|
||||||
|
key: string;
|
||||||
|
/** Certificate chain in `PEM` format. */
|
||||||
|
cert: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated This will be removed in Deno 2.0. See the
|
||||||
|
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||||
|
* for migration instructions.
|
||||||
|
*
|
||||||
|
* @category Network
|
||||||
|
*/
|
||||||
|
export interface TlsCertifiedKeyFromFile {
|
||||||
/** Path to a file containing a PEM formatted CA certificate. Requires
|
/** Path to a file containing a PEM formatted CA certificate. Requires
|
||||||
* `--allow-read`.
|
* `--allow-read`.
|
||||||
*
|
*
|
||||||
|
@ -211,16 +249,45 @@ declare namespace Deno {
|
||||||
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||||
* for migration instructions.
|
* for migration instructions.
|
||||||
*/
|
*/
|
||||||
certFile?: string;
|
certFile: string;
|
||||||
/** Server private key file. Requires `--allow-read`.
|
/** Path to a file containing a private key file. Requires `--allow-read`.
|
||||||
*
|
*
|
||||||
* @tags allow-read
|
* @tags allow-read
|
||||||
* @deprecated This will be removed in Deno 2.0. See the
|
* @deprecated This will be removed in Deno 2.0. See the
|
||||||
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||||
* for migration instructions.
|
* for migration instructions.
|
||||||
*/
|
*/
|
||||||
keyFile?: string;
|
keyFile: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated This will be removed in Deno 2.0. See the
|
||||||
|
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||||
|
* for migration instructions.
|
||||||
|
*
|
||||||
|
* @category Network
|
||||||
|
*/
|
||||||
|
export interface TlsCertifiedKeyConnectTls {
|
||||||
|
/**
|
||||||
|
* Certificate chain in `PEM` format.
|
||||||
|
*
|
||||||
|
* @deprecated This will be removed in Deno 2.0. See the
|
||||||
|
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||||
|
* for migration instructions.
|
||||||
|
*/
|
||||||
|
certChain: string;
|
||||||
|
/**
|
||||||
|
* Private key in `PEM` format. RSA, EC, and PKCS8-format keys are supported.
|
||||||
|
*
|
||||||
|
* @deprecated This will be removed in Deno 2.0. See the
|
||||||
|
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||||
|
* for migration instructions.
|
||||||
|
*/
|
||||||
|
privateKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @category Network */
|
||||||
|
export interface ListenTlsOptions extends TcpListenOptions {
|
||||||
transport?: "tcp";
|
transport?: "tcp";
|
||||||
|
|
||||||
/** Application-Layer Protocol Negotiation (ALPN) protocols to announce to
|
/** Application-Layer Protocol Negotiation (ALPN) protocols to announce to
|
||||||
|
@ -246,7 +313,9 @@ declare namespace Deno {
|
||||||
* @tags allow-net
|
* @tags allow-net
|
||||||
* @category Network
|
* @category Network
|
||||||
*/
|
*/
|
||||||
export function listenTls(options: ListenTlsOptions): TlsListener;
|
export function listenTls(
|
||||||
|
options: ListenTlsOptions & TlsCertifiedKeyOptions,
|
||||||
|
): TlsListener;
|
||||||
|
|
||||||
/** @category Network */
|
/** @category Network */
|
||||||
export interface ConnectOptions {
|
export interface ConnectOptions {
|
||||||
|
@ -343,9 +412,11 @@ declare namespace Deno {
|
||||||
*
|
*
|
||||||
* @default {"127.0.0.1"} */
|
* @default {"127.0.0.1"} */
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
/**
|
/** Path to a file containing a PEM formatted list of root certificates that will
|
||||||
* Server certificate file.
|
* be used in addition to the default root certificates to verify the peer's certificate. Requires
|
||||||
|
* `--allow-read`.
|
||||||
*
|
*
|
||||||
|
* @tags allow-read
|
||||||
* @deprecated This will be removed in Deno 2.0. See the
|
* @deprecated This will be removed in Deno 2.0. See the
|
||||||
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||||
* for migration instructions.
|
* for migration instructions.
|
||||||
|
@ -361,26 +432,6 @@ declare namespace Deno {
|
||||||
* TLS handshake.
|
* TLS handshake.
|
||||||
*/
|
*/
|
||||||
alpnProtocols?: string[];
|
alpnProtocols?: string[];
|
||||||
/**
|
|
||||||
* PEM formatted client certificate chain.
|
|
||||||
*
|
|
||||||
* @deprecated This will be removed in Deno 2.0. See the
|
|
||||||
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
|
||||||
* for migration instructions.
|
|
||||||
*/
|
|
||||||
certChain?: string;
|
|
||||||
/**
|
|
||||||
* PEM formatted (RSA or PKCS8) private key of client certificate.
|
|
||||||
*
|
|
||||||
* @deprecated This will be removed in Deno 2.0. See the
|
|
||||||
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
|
||||||
* for migration instructions.
|
|
||||||
*/
|
|
||||||
privateKey?: string;
|
|
||||||
/** Server private key in PEM format. */
|
|
||||||
key?: string;
|
|
||||||
/** Cert chain in PEM format. */
|
|
||||||
cert?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Establishes a secure connection over TLS (transport layer security) using
|
/** Establishes a secure connection over TLS (transport layer security) using
|
||||||
|
@ -403,6 +454,30 @@ declare namespace Deno {
|
||||||
*/
|
*/
|
||||||
export function connectTls(options: ConnectTlsOptions): Promise<TlsConn>;
|
export function connectTls(options: ConnectTlsOptions): Promise<TlsConn>;
|
||||||
|
|
||||||
|
/** Establishes a secure connection over TLS (transport layer security) using
|
||||||
|
* an optional cert file, client certificate, hostname (default is "127.0.0.1") and
|
||||||
|
* port. The cert file is optional and if not included Mozilla's root certificates will
|
||||||
|
* be used (see also https://github.com/ctz/webpki-roots for specifics)
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem");
|
||||||
|
* const key = "----BEGIN PRIVATE KEY----...";
|
||||||
|
* const cert = "----BEGIN CERTIFICATE----...";
|
||||||
|
* const conn1 = await Deno.connectTls({ port: 80, key, cert });
|
||||||
|
* const conn2 = await Deno.connectTls({ caCerts: [caCert], hostname: "192.0.2.1", port: 80, key, cert });
|
||||||
|
* const conn3 = await Deno.connectTls({ hostname: "[2001:db8::1]", port: 80, key, cert });
|
||||||
|
* const conn4 = await Deno.connectTls({ caCerts: [caCert], hostname: "golang.org", port: 80, key, cert });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Requires `allow-net` permission.
|
||||||
|
*
|
||||||
|
* @tags allow-net
|
||||||
|
* @category Network
|
||||||
|
*/
|
||||||
|
export function connectTls(
|
||||||
|
options: ConnectTlsOptions & TlsCertifiedKeyOptions,
|
||||||
|
): Promise<TlsConn>;
|
||||||
|
|
||||||
/** @category Network */
|
/** @category Network */
|
||||||
export interface StartTlsOptions {
|
export interface StartTlsOptions {
|
||||||
/** A literal IP address or host name that can be resolved to an IP address.
|
/** A literal IP address or host name that can be resolved to an IP address.
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::tcp::TcpListener;
|
||||||
use crate::DefaultTlsOptions;
|
use crate::DefaultTlsOptions;
|
||||||
use crate::NetPermissions;
|
use crate::NetPermissions;
|
||||||
use crate::UnsafelyIgnoreCertificateErrors;
|
use crate::UnsafelyIgnoreCertificateErrors;
|
||||||
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::error::bad_resource;
|
use deno_core::error::bad_resource;
|
||||||
use deno_core::error::custom_error;
|
use deno_core::error::custom_error;
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::generic_error;
|
||||||
|
@ -448,18 +449,13 @@ where
|
||||||
.with_no_client_auth();
|
.with_no_client_auth();
|
||||||
|
|
||||||
let mut tls_config = match keys {
|
let mut tls_config = match keys {
|
||||||
TlsKeys::Null => {
|
TlsKeys::Null => Err(anyhow!("Deno.listenTls requires a key")),
|
||||||
unreachable!()
|
TlsKeys::Static(TlsKey(cert, key)) => tls_config
|
||||||
}
|
.with_single_cert(cert.clone(), key.clone())
|
||||||
TlsKeys::Static(TlsKey(cert, key)) => {
|
.map_err(|e| anyhow!(e)),
|
||||||
tls_config.with_single_cert(cert.clone(), key.clone())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
custom_error(
|
custom_error("InvalidData", "Error creating TLS certificate").context(e)
|
||||||
"InvalidData",
|
|
||||||
format!("Error creating TLS certificate: {:?}", e),
|
|
||||||
)
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(alpn_protocols) = args.alpn_protocols {
|
if let Some(alpn_protocols) = args.alpn_protocols {
|
||||||
|
|
|
@ -1336,7 +1336,7 @@ Deno.test(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
TypeError,
|
TypeError,
|
||||||
"Cannot specify both `privateKey` and `key`",
|
"Cannot specify both `key` and `privateKey` for `Deno.connectTls`.",
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Reference in a new issue