diff options
author | yonatan ben avraham <yonbav@gmail.com> | 2020-12-20 00:13:48 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-19 23:13:48 +0100 |
commit | afbd19ed9b9661a6648554e635ccdae5cbc0b0a3 (patch) | |
tree | b25a9cc9a6181e06bfb6f60dba54ef7d9cd199c7 | |
parent | 4ab1aa8877a70ef99ca4091fc65def0aefc9c360 (diff) |
feat(unstable): support in memory certificate data for Deno.createHttpClient (#8739)
-rw-r--r-- | cli/dts/lib.deno.unstable.d.ts | 4 | ||||
-rw-r--r-- | cli/tests/unit/fetch_test.ts | 41 | ||||
-rw-r--r-- | op_crates/fetch/lib.rs | 16 |
3 files changed, 57 insertions, 4 deletions
diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index f9ef1fb2f..e8d484ec3 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -1266,6 +1266,10 @@ declare namespace Deno { * Requires `allow-read` permission. */ caFile?: string; + + /** A certificate authority to use when validating TLS certificates. Certificate data must be PEM encoded. + */ + caData?: string; } /** **UNSTABLE**: New API, yet to be vetted. diff --git a/cli/tests/unit/fetch_test.ts b/cli/tests/unit/fetch_test.ts index 6a5cff164..6f90a1847 100644 --- a/cli/tests/unit/fetch_test.ts +++ b/cli/tests/unit/fetch_test.ts @@ -959,7 +959,7 @@ unitTest(function fetchResponseEmptyConstructor(): void { unitTest( { perms: { net: true, read: true } }, - async function fetchCustomHttpClientSuccess(): Promise< + async function fetchCustomHttpClientFileCertificateSuccess(): Promise< void > { const client = Deno.createHttpClient( @@ -974,3 +974,42 @@ unitTest( client.close(); }, ); + +unitTest( + { perms: { net: true } }, + async function fetchCustomHttpClientParamCertificateSuccess(): Promise< + void + > { + const client = Deno.createHttpClient( + { + caData: `-----BEGIN CERTIFICATE----- +MIIDIzCCAgugAwIBAgIJAMKPPW4tsOymMA0GCSqGSIb3DQEBCwUAMCcxCzAJBgNV +BAYTAlVTMRgwFgYDVQQDDA9FeGFtcGxlLVJvb3QtQ0EwIBcNMTkxMDIxMTYyODIy +WhgPMjExODA5MjcxNjI4MjJaMCcxCzAJBgNVBAYTAlVTMRgwFgYDVQQDDA9FeGFt +cGxlLVJvb3QtQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMH/IO +2qtHfyBKwANNPB4K0q5JVSg8XxZdRpTTlz0CwU0oRO3uHrI52raCCfVeiQutyZop +eFZTDWeXGudGAFA2B5m3orWt0s+touPi8MzjsG2TQ+WSI66QgbXTNDitDDBtTVcV +5G3Ic+3SppQAYiHSekLISnYWgXLl+k5CnEfTowg6cjqjVr0KjL03cTN3H7b+6+0S +ws4rYbW1j4ExR7K6BFNH6572yq5qR20E6GqlY+EcOZpw4CbCk9lS8/CWuXze/vMs +OfDcc6K+B625d27wyEGZHedBomT2vAD7sBjvO8hn/DP1Qb46a8uCHR6NSfnJ7bXO +G1igaIbgY1zXirNdAgMBAAGjUDBOMB0GA1UdDgQWBBTzut+pwwDfqmMYcI9KNWRD +hxcIpTAfBgNVHSMEGDAWgBTzut+pwwDfqmMYcI9KNWRDhxcIpTAMBgNVHRMEBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB9AqSbZ+hEglAgSHxAMCqRFdhVu7MvaQM0 +P090mhGlOCt3yB7kdGfsIrUW6nQcTz7PPQFRaJMrFHPvFvPootkBUpTYR4hTkdce +H6RCRu2Jxl4Y9bY/uezd9YhGCYfUtfjA6/TH9FcuZfttmOOlxOt01XfNvVMIR6RM +z/AYhd+DeOXjr35F/VHeVpnk+55L0PYJsm1CdEbOs5Hy1ecR7ACuDkXnbM4fpz9I +kyIWJwk2zJReKcJMgi1aIinDM9ao/dca1G99PHOw8dnr4oyoTiv8ao6PWiSRHHMi +MNf4EgWfK+tZMnuqfpfO9740KzfcVoMNo4QJD4yn5YxroUOO/Azi +-----END CERTIFICATE----- +`, + }, + ); + const response = await fetch( + "https://localhost:5545/cli/tests/fixture.json", + { client }, + ); + const json = await response.json(); + assertEquals(json.name, "deno"); + client.close(); + }, +); diff --git a/op_crates/fetch/lib.rs b/op_crates/fetch/lib.rs index c2c08d2cf..4bc37b998 100644 --- a/op_crates/fetch/lib.rs +++ b/op_crates/fetch/lib.rs @@ -260,6 +260,7 @@ where #[serde(default)] struct CreateHttpClientOptions { ca_file: Option<String>, + ca_data: Option<String>, } let args: CreateHttpClientOptions = serde_json::from_value(args)?; @@ -269,7 +270,9 @@ where permissions.check_read(&PathBuf::from(ca_file))?; } - let client = create_http_client(args.ca_file.as_deref()).unwrap(); + let client = + create_http_client(args.ca_file.as_deref(), args.ca_data.as_deref()) + .unwrap(); let rid = state.resource_table.add(HttpClientResource::new(client)); Ok(json!(rid)) @@ -277,9 +280,16 @@ where /// Create new instance of async reqwest::Client. This client supports /// proxies and doesn't follow redirects. -fn create_http_client(ca_file: Option<&str>) -> Result<Client, AnyError> { +fn create_http_client( + ca_file: Option<&str>, + ca_data: Option<&str>, +) -> Result<Client, AnyError> { let mut builder = Client::builder().redirect(Policy::none()).use_rustls_tls(); - if let Some(ca_file) = ca_file { + if let Some(ca_data) = ca_data { + let ca_data_vec = ca_data.as_bytes().to_vec(); + let cert = reqwest::Certificate::from_pem(&ca_data_vec)?; + builder = builder.add_root_certificate(cert); + } else if let Some(ca_file) = ca_file { let mut buf = Vec::new(); File::open(ca_file)?.read_to_end(&mut buf)?; let cert = reqwest::Certificate::from_pem(&buf)?; |