Skip to content

Commit

Permalink
BREAKING(net): remove `Deno.ConnectTlsOptions.{certChain,certFile,pri…
Browse files Browse the repository at this point in the history
…vateKey}` and `Deno.ListenTlsOptions.certChain,certFile,keyFile}` (#25525)

Towards #22079
  • Loading branch information
iuioiua authored Sep 10, 2024
1 parent be0ba6d commit ace1202
Show file tree
Hide file tree
Showing 11 changed files with 28 additions and 515 deletions.
4 changes: 2 additions & 2 deletions cli/tsc/dts/lib.deno.ns.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5356,7 +5356,7 @@ declare namespace Deno {
export function serve(
options:
| ServeTcpOptions
| (ServeTcpOptions & TlsCertifiedKeyOptions),
| (ServeTcpOptions & TlsCertifiedKeyPem),
handler: ServeHandler<Deno.NetAddr>,
): HttpServer<Deno.NetAddr>;
/** Serves HTTP requests with the given option bag.
Expand Down Expand Up @@ -5413,7 +5413,7 @@ declare namespace Deno {
*/
export function serve(
options:
& (ServeTcpOptions | (ServeTcpOptions & TlsCertifiedKeyOptions))
& (ServeTcpOptions | (ServeTcpOptions & TlsCertifiedKeyPem))
& ServeInit<Deno.NetAddr>,
): HttpServer<Deno.NetAddr>;

Expand Down
2 changes: 1 addition & 1 deletion cli/tsc/dts/lib.deno.unstable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ declare namespace Deno {
* @experimental
*/
export function createHttpClient(
options: CreateHttpClientOptions & TlsCertifiedKeyOptions,
options: CreateHttpClientOptions & TlsCertifiedKeyPem,
): HttpClient;

/** **UNSTABLE**: New API, yet to be vetted.
Expand Down
109 changes: 11 additions & 98 deletions ext/net/02_tls.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
op_tls_handshake,
op_tls_key_null,
op_tls_key_static,
op_tls_key_static_from_file,
op_tls_start,
} from "ext:core/ops";
const {
Expand Down Expand Up @@ -50,45 +49,23 @@ async function connectTls({
alpnProtocols = undefined,
keyFormat = undefined,
cert = undefined,
certFile = undefined,
certChain = undefined,
key = undefined,
keyFile = undefined,
privateKey = undefined,
}) {
if (transport !== "tcp") {
throw new TypeError(`Unsupported transport: '${transport}'`);
}
let deprecatedCertFile = undefined;

// 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;
}

const keyPair = loadTlsKeyPair("Deno.connectTls", {
keyFormat,
cert,
certFile,
certChain,
key,
keyFile,
privateKey,
});
// TODO(mmastrac): We only expose this feature via symbol for now. This should actually be a feature
// in Deno.connectTls, however.
const serverName = arguments[0][serverNameSymbol] ?? null;
const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_connect_tls(
{ hostname, port },
{ certFile: deprecatedCertFile, caCerts, alpnProtocols, serverName },
{ caCerts, alpnProtocols, serverName },
keyPair,
);
localAddr.transport = "tcp";
Expand Down Expand Up @@ -137,10 +114,7 @@ function hasTlsKeyPairOptions(options) {
if (options[resolverSymbol] !== undefined) {
return true;
}
return (options.cert !== undefined || options.key !== undefined ||
options.certFile !== undefined ||
options.keyFile !== undefined || options.privateKey !== undefined ||
options.certChain !== undefined);
return (options.cert !== undefined || options.key !== undefined);
}

/**
Expand All @@ -150,19 +124,8 @@ function hasTlsKeyPairOptions(options) {
function loadTlsKeyPair(api, {
keyFormat,
cert,
certFile,
certChain,
key,
keyFile,
privateKey,
}) {
if (internals.future) {
certFile = undefined;
certChain = undefined;
keyFile = undefined;
privateKey = undefined;
}

// TODO(mmastrac): remove this temporary symbol when the API lands
if (arguments[1][resolverSymbol] !== undefined) {
return createTlsKeyResolver(arguments[1][resolverSymbol]);
Expand All @@ -173,68 +136,18 @@ function loadTlsKeyPair(api, {
throw new TypeError('If `keyFormat` is specified, it must be "pem"');
}

function exclusive(a1, a1v, a2, a2v) {
if (a1v !== undefined && a2v !== undefined) {
throw new TypeError(
`Cannot specify both \`${a1}\` and \`${a2}\` for \`${api}\`.`,
);
}
if (cert !== undefined && key === undefined) {
throw new TypeError(
`If \`cert\` is specified, \`key\` must be specified as well 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}\`.`,
);
}
if (cert === undefined && key !== undefined) {
throw new TypeError(
`If \`key\` is specified, \`cert\` 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) {
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) {
if (cert !== undefined) {
return op_tls_key_static(cert, key);
} else {
return op_tls_key_null();
Expand Down
77 changes: 2 additions & 75 deletions ext/net/lib.deno_net.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,16 +232,6 @@ declare namespace Deno {
options: UnixListenOptions & { transport: "unix" },
): UnixListener;

/** Provides TLS certified keys, ie: a key that has been certified by a trusted certificate authority.
* A certified key generally consists of a private key and certificate part.
*
* @category Network
*/
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
Expand All @@ -268,59 +258,6 @@ declare namespace Deno {
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
* `--allow-read`.
*
* @tags allow-read
* @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.
*/
certFile: string;
/** Path to a file containing a private key file. Requires `--allow-read`.
*
* @tags allow-read
* @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.
*/
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";
Expand Down Expand Up @@ -349,7 +286,7 @@ declare namespace Deno {
* @category Network
*/
export function listenTls(
options: ListenTlsOptions & TlsCertifiedKeyOptions,
options: ListenTlsOptions & TlsCertifiedKeyPem,
): TlsListener;

/** @category Network */
Expand Down Expand Up @@ -430,16 +367,6 @@ declare namespace Deno {
*
* @default {"127.0.0.1"} */
hostname?: string;
/** Path to a file containing a PEM formatted list of root certificates that will
* 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
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
* for migration instructions.
*/
certFile?: string;
/** A list of root certificates that will be used in addition to the
* default root certificates to verify the peer's certificate.
*
Expand Down Expand Up @@ -493,7 +420,7 @@ declare namespace Deno {
* @category Network
*/
export function connectTls(
options: ConnectTlsOptions & TlsCertifiedKeyOptions,
options: ConnectTlsOptions & TlsCertifiedKeyPem,
): Promise<TlsConn>;

/** @category Network */
Expand Down
1 change: 0 additions & 1 deletion ext/net/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ deno_core::extension!(deno_net,

ops_tls::op_tls_key_null,
ops_tls::op_tls_key_static,
ops_tls::op_tls_key_static_from_file<P>,
ops_tls::op_tls_cert_resolver_create,
ops_tls::op_tls_cert_resolver_poll,
ops_tls::op_tls_cert_resolver_resolve,
Expand Down
43 changes: 0 additions & 43 deletions ext/net/ops_tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ use deno_tls::new_resolver;
use deno_tls::rustls::pki_types::ServerName;
use deno_tls::rustls::ClientConnection;
use deno_tls::rustls::ServerConfig;
use deno_tls::webpki::types::CertificateDer;
use deno_tls::webpki::types::PrivateKeyDer;
use deno_tls::ServerConfigProvider;
use deno_tls::SocketUse;
use deno_tls::TlsKey;
Expand Down Expand Up @@ -213,32 +211,6 @@ pub fn op_tls_key_static(
Ok(TlsKeysHolder::from(TlsKeys::Static(TlsKey(cert, key))))
}

/// Legacy op -- will be removed in Deno 2.0.
#[op2]
#[cppgc]
pub fn op_tls_key_static_from_file<NP>(
state: &mut OpState,
#[string] api: String,
#[string] cert_file: String,
#[string] key_file: String,
) -> Result<TlsKeysHolder, AnyError>
where
NP: NetPermissions + 'static,
{
{
let permissions = state.borrow_mut::<NP>();
permissions.check_read(Path::new(&cert_file), &api)?;
permissions.check_read(Path::new(&key_file), &api)?;
}

let cert = load_certs_from_file(&cert_file)?;
let key = load_private_keys_from_file(&key_file)?
.into_iter()
.next()
.unwrap();
Ok(TlsKeysHolder::from(TlsKeys::Static(TlsKey(cert, key))))
}

#[op2]
pub fn op_tls_cert_resolver_create<'s>(
scope: &mut v8::HandleScope<'s>,
Expand Down Expand Up @@ -455,21 +427,6 @@ where
Ok((rid, IpAddr::from(local_addr), IpAddr::from(remote_addr)))
}

fn load_certs_from_file(
path: &str,
) -> Result<Vec<CertificateDer<'static>>, AnyError> {
let cert_file = File::open(path)?;
let reader = &mut BufReader::new(cert_file);
load_certs(reader)
}

fn load_private_keys_from_file(
path: &str,
) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> {
let key_bytes = std::fs::read(path)?;
load_private_keys(&key_bytes)
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListenTlsArgs {
Expand Down
Loading

0 comments on commit ace1202

Please sign in to comment.