mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
parent
3c7057d583
commit
9a43a2b495
4 changed files with 185 additions and 19 deletions
|
@ -51,21 +51,49 @@ async function connectTls({
|
||||||
caCerts = [],
|
caCerts = [],
|
||||||
certChain = undefined,
|
certChain = undefined,
|
||||||
privateKey = undefined,
|
privateKey = undefined,
|
||||||
|
cert = undefined,
|
||||||
|
key = undefined,
|
||||||
alpnProtocols = undefined,
|
alpnProtocols = undefined,
|
||||||
}) {
|
}) {
|
||||||
if (certFile !== undefined) {
|
if (certFile !== undefined) {
|
||||||
internals.warnOnDeprecatedApi(
|
internals.warnOnDeprecatedApi(
|
||||||
"Deno.ConnectTlsOptions.certFile",
|
"Deno.ConnectTlsOptions.certFile",
|
||||||
new Error().stack,
|
new Error().stack,
|
||||||
"Pass the cert file contents to the `Deno.ConnectTlsOptions.certChain` option instead.",
|
"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) {
|
||||||
|
throw new TypeError(
|
||||||
|
"Cannot specify both `certChain` and `cert`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (privateKey !== undefined && key !== undefined) {
|
||||||
|
throw new TypeError(
|
||||||
|
"Cannot specify both `privateKey` and `key`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
cert ??= certChain;
|
||||||
|
key ??= 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, certChain, privateKey, alpnProtocols },
|
{ certFile, caCerts, cert, key, alpnProtocols },
|
||||||
);
|
);
|
||||||
localAddr.transport = "tcp";
|
localAddr.transport = "tcp";
|
||||||
remoteAddr.transport = "tcp";
|
remoteAddr.transport = "tcp";
|
||||||
|
|
20
ext/net/lib.deno_net.d.ts
vendored
20
ext/net/lib.deno_net.d.ts
vendored
|
@ -348,10 +348,26 @@ declare namespace Deno {
|
||||||
* TLS handshake.
|
* TLS handshake.
|
||||||
*/
|
*/
|
||||||
alpnProtocols?: string[];
|
alpnProtocols?: string[];
|
||||||
/** PEM formatted client certificate chain. */
|
/**
|
||||||
|
* 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;
|
certChain?: string;
|
||||||
/** PEM formatted (RSA or PKCS8) private key of client certificate. */
|
/**
|
||||||
|
* 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;
|
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
|
||||||
|
|
|
@ -145,8 +145,8 @@ impl Resource for TlsStreamResource {
|
||||||
pub struct ConnectTlsArgs {
|
pub struct ConnectTlsArgs {
|
||||||
cert_file: Option<String>,
|
cert_file: Option<String>,
|
||||||
ca_certs: Vec<String>,
|
ca_certs: Vec<String>,
|
||||||
cert_chain: Option<String>,
|
cert: Option<String>,
|
||||||
private_key: Option<String>,
|
key: Option<String>,
|
||||||
alpn_protocols: Option<Vec<String>>,
|
alpn_protocols: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,24 +297,23 @@ where
|
||||||
let local_addr = tcp_stream.local_addr()?;
|
let local_addr = tcp_stream.local_addr()?;
|
||||||
let remote_addr = tcp_stream.peer_addr()?;
|
let remote_addr = tcp_stream.peer_addr()?;
|
||||||
|
|
||||||
let cert_chain_and_key =
|
let cert_and_key = if args.cert.is_some() || args.key.is_some() {
|
||||||
if args.cert_chain.is_some() || args.private_key.is_some() {
|
let cert = args
|
||||||
let cert_chain = args
|
.cert
|
||||||
.cert_chain
|
.ok_or_else(|| type_error("No certificate chain provided"))?;
|
||||||
.ok_or_else(|| type_error("No certificate chain provided"))?;
|
let key = args
|
||||||
let private_key = args
|
.key
|
||||||
.private_key
|
.ok_or_else(|| type_error("No private key provided"))?;
|
||||||
.ok_or_else(|| type_error("No private key provided"))?;
|
Some((cert, key))
|
||||||
Some((cert_chain, private_key))
|
} else {
|
||||||
} else {
|
None
|
||||||
None
|
};
|
||||||
};
|
|
||||||
|
|
||||||
let mut tls_config = create_client_config(
|
let mut tls_config = create_client_config(
|
||||||
root_cert_store,
|
root_cert_store,
|
||||||
ca_certs,
|
ca_certs,
|
||||||
unsafely_ignore_certificate_errors,
|
unsafely_ignore_certificate_errors,
|
||||||
cert_chain_and_key,
|
cert_and_key,
|
||||||
SocketUse::GeneralSsl,
|
SocketUse::GeneralSsl,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
|
@ -1174,6 +1174,22 @@ Deno.test(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Deno.test(
|
||||||
|
{ permissions: { read: true, net: true } },
|
||||||
|
async function connectTLSBadCertKey(): Promise<void> {
|
||||||
|
await assertRejects(async () => {
|
||||||
|
await Deno.connectTls({
|
||||||
|
hostname: "deno.land",
|
||||||
|
port: 443,
|
||||||
|
cert: "bad data",
|
||||||
|
key: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.key",
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}, Deno.errors.InvalidData);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { read: true, net: true } },
|
{ permissions: { read: true, net: true } },
|
||||||
async function connectTLSBadPrivateKey(): Promise<void> {
|
async function connectTLSBadPrivateKey(): Promise<void> {
|
||||||
|
@ -1190,6 +1206,22 @@ Deno.test(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Deno.test(
|
||||||
|
{ permissions: { read: true, net: true } },
|
||||||
|
async function connectTLSBadKey(): Promise<void> {
|
||||||
|
await assertRejects(async () => {
|
||||||
|
await Deno.connectTls({
|
||||||
|
hostname: "deno.land",
|
||||||
|
port: 443,
|
||||||
|
cert: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.crt",
|
||||||
|
),
|
||||||
|
key: "bad data",
|
||||||
|
});
|
||||||
|
}, Deno.errors.InvalidData);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { read: true, net: true } },
|
{ permissions: { read: true, net: true } },
|
||||||
async function connectTLSNotPrivateKey(): Promise<void> {
|
async function connectTLSNotPrivateKey(): Promise<void> {
|
||||||
|
@ -1206,6 +1238,22 @@ Deno.test(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Deno.test(
|
||||||
|
{ permissions: { read: true, net: true } },
|
||||||
|
async function connectTLSNotKey(): Promise<void> {
|
||||||
|
await assertRejects(async () => {
|
||||||
|
await Deno.connectTls({
|
||||||
|
hostname: "deno.land",
|
||||||
|
port: 443,
|
||||||
|
cert: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.crt",
|
||||||
|
),
|
||||||
|
key: "",
|
||||||
|
});
|
||||||
|
}, Deno.errors.InvalidData);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { read: true, net: true } },
|
{ permissions: { read: true, net: true } },
|
||||||
async function connectWithClientCert() {
|
async function connectWithClientCert() {
|
||||||
|
@ -1231,6 +1279,81 @@ Deno.test(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Deno.test(
|
||||||
|
{ permissions: { read: true, net: true } },
|
||||||
|
async function connectWithCert() {
|
||||||
|
// The test_server running on port 4552 responds with 'PASS' if client
|
||||||
|
// authentication was successful. Try it by running test_server and
|
||||||
|
// curl --key cli/tests/testdata/tls/localhost.key \
|
||||||
|
// --cert cli/tests/testdata/tls/localhost.crt \
|
||||||
|
// --cacert cli/tests/testdata/tls/RootCA.crt https://localhost:4552/
|
||||||
|
const conn = await Deno.connectTls({
|
||||||
|
hostname: "localhost",
|
||||||
|
port: 4552,
|
||||||
|
cert: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.crt",
|
||||||
|
),
|
||||||
|
key: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.key",
|
||||||
|
),
|
||||||
|
caCerts: [Deno.readTextFileSync("tests/testdata/tls/RootCA.pem")],
|
||||||
|
});
|
||||||
|
const result = decoder.decode(await readAll(conn));
|
||||||
|
assertEquals(result, "PASS");
|
||||||
|
conn.close();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Deno.test(
|
||||||
|
{ permissions: { read: true, net: true } },
|
||||||
|
async function connectTlsConflictingCertOptions(): Promise<void> {
|
||||||
|
await assertRejects(
|
||||||
|
async () => {
|
||||||
|
await Deno.connectTls({
|
||||||
|
hostname: "deno.land",
|
||||||
|
port: 443,
|
||||||
|
cert: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.crt",
|
||||||
|
),
|
||||||
|
certChain: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.crt",
|
||||||
|
),
|
||||||
|
key: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.key",
|
||||||
|
),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
TypeError,
|
||||||
|
"Cannot specify both `certChain` and `cert`",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Deno.test(
|
||||||
|
{ permissions: { read: true, net: true } },
|
||||||
|
async function connectTlsConflictingKeyOptions(): Promise<void> {
|
||||||
|
await assertRejects(
|
||||||
|
async () => {
|
||||||
|
await Deno.connectTls({
|
||||||
|
hostname: "deno.land",
|
||||||
|
port: 443,
|
||||||
|
cert: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.crt",
|
||||||
|
),
|
||||||
|
privateKey: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.crt",
|
||||||
|
),
|
||||||
|
key: await Deno.readTextFile(
|
||||||
|
"tests/testdata/tls/localhost.key",
|
||||||
|
),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
TypeError,
|
||||||
|
"Cannot specify both `privateKey` and `key`",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { read: true, net: true } },
|
{ permissions: { read: true, net: true } },
|
||||||
async function connectTLSCaCerts() {
|
async function connectTLSCaCerts() {
|
||||||
|
|
Loading…
Reference in a new issue