feat: stabilize Deno.startTls (#12581)

This commit stabilizes `Deno.startTls` and removes `certFile` from the
`StartTlsOptions`.
This commit is contained in:
Luca Casonato 2021-10-29 17:13:31 +02:00 committed by GitHub
parent 8e0fd1dca1
commit b7341438f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 71 deletions

View file

@ -1093,45 +1093,6 @@ declare namespace Deno {
*/
export function connectTls(options: ConnectTlsOptions): Promise<TlsConn>;
export interface StartTlsOptions {
/** A literal IP address or host name that can be resolved to an IP address.
* If not specified, defaults to `127.0.0.1`. */
hostname?: string;
/**
* @deprecated This option is deprecated and will be removed in a future
* release.
*
* Server certificate file.
*/
certFile?: string;
/** A list of root certificates that will be used in addition to the
* default root certificates to verify the peer's certificate.
*
* Must be in PEM format. */
caCerts?: string[];
}
/** **UNSTABLE**: new API, yet to be vetted.
*
* Start TLS handshake from an existing connection using
* an optional cert file, hostname (default is "127.0.0.1"). Specifying CA
* certs is optional. By default the configured root certificates are used.
* Using this function requires that the other end of the connection is
* prepared for TLS handshake.
*
* ```ts
* const conn = await Deno.connect({ port: 80, hostname: "127.0.0.1" });
* const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem");
* const tlsConn = await Deno.startTls(conn, { caCerts: [caCert], hostname: "localhost" });
* ```
*
* Requires `allow-net` permission.
*/
export function startTls(
conn: Conn,
options?: StartTlsOptions,
): Promise<TlsConn>;
export interface ListenTlsOptions {
/** **UNSTABLE**: new API, yet to be vetted.
*

View file

@ -1105,23 +1105,6 @@ unitTest(
},
);
unitTest(
{ permissions: { read: true, net: true } },
async function startTLSCertFile() {
const plainConn = await Deno.connect({
hostname: "localhost",
port: 4557,
});
const conn = await Deno.startTls(plainConn, {
hostname: "localhost",
certFile: "cli/tests/testdata/tls/RootCA.pem",
});
const result = decoder.decode(await readAll(conn));
assertEquals(result, "PASS");
conn.close();
},
);
unitTest(
{ permissions: { read: true, net: true } },
async function tlsHandshakeSuccess() {
@ -1235,7 +1218,7 @@ unitTest(
const tcpConn = await Deno.connect({ hostname, port });
const tlsConn = await Deno.startTls(tcpConn, {
hostname: "foo.land",
certFile: "cli/tests/testdata/tls/RootCA.crt",
caCerts: [Deno.readTextFileSync("cli/tests/testdata/tls/RootCA.pem")],
});
// Handshake fails because hostname doesn't match the certificate.
await assertRejects(

View file

@ -166,6 +166,36 @@ declare namespace Deno {
*/
export function connectTls(options: ConnectTlsOptions): Promise<TlsConn>;
export interface StartTlsOptions {
/** A literal IP address or host name that can be resolved to an IP address.
* If not specified, defaults to `127.0.0.1`. */
hostname?: string;
/** A list of root certificates that will be used in addition to the
* default root certificates to verify the peer's certificate.
*
* Must be in PEM format. */
caCerts?: string[];
}
/** Start TLS handshake from an existing connection using an optional list of
* CA certificates, and hostname (default is "127.0.0.1"). Specifying CA certs
* is optional. By default the configured root certificates are used. Using
* this function requires that the other end of the connection is prepared for
* a TLS handshake.
*
* ```ts
* const conn = await Deno.connect({ port: 80, hostname: "127.0.0.1" });
* const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem");
* const tlsConn = await Deno.startTls(conn, { caCerts: [caCert], hostname: "localhost" });
* ```
*
* Requires `allow-net` permission.
*/
export function startTls(
conn: Conn,
options?: StartTlsOptions,
): Promise<TlsConn>;
/** Shutdown socket send operations.
*
* Matches behavior of POSIX shutdown(3).

View file

@ -776,7 +776,6 @@ pub struct ConnectTlsArgs {
#[serde(rename_all = "camelCase")]
struct StartTlsArgs {
rid: ResourceId,
cert_file: Option<String>,
ca_certs: Vec<String>,
hostname: String,
}
@ -794,29 +793,19 @@ where
"" => "localhost",
n => n,
};
let cert_file = args.cert_file.as_deref();
{
super::check_unstable2(&state, "Deno.startTls");
let mut s = state.borrow_mut();
let permissions = s.borrow_mut::<NP>();
permissions.check_net(&(hostname, Some(0)))?;
if let Some(path) = cert_file {
permissions.check_read(Path::new(path))?;
}
}
let mut ca_certs = args
let ca_certs = args
.ca_certs
.into_iter()
.map(|s| s.into_bytes())
.collect::<Vec<_>>();
if let Some(path) = cert_file {
let mut buf = Vec::new();
File::open(path)?.read_to_end(&mut buf)?;
ca_certs.push(buf);
};
let hostname_dns = DNSNameRef::try_from_ascii_str(hostname)
.map_err(|_| invalid_hostname(hostname))?;

View file

@ -88,6 +88,7 @@
listen: __bootstrap.net.listen,
connectTls: __bootstrap.tls.connectTls,
listenTls: __bootstrap.tls.listenTls,
startTls: __bootstrap.tls.startTls,
shutdown: __bootstrap.net.shutdown,
fstatSync: __bootstrap.fs.fstatSync,
fstat: __bootstrap.fs.fstat,
@ -125,7 +126,6 @@
listen: __bootstrap.netUnstable.listen,
connect: __bootstrap.netUnstable.connect,
listenDatagram: __bootstrap.netUnstable.listenDatagram,
startTls: __bootstrap.tls.startTls,
umask: __bootstrap.fs.umask,
futime: __bootstrap.fs.futime,
futimeSync: __bootstrap.fs.futimeSync,