diff options
author | Kitson Kelly <me@kitsonkelly.com> | 2022-01-24 11:27:52 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-24 11:27:52 +1100 |
commit | 3ec248cff8fff1a41c2b2ad5301e7aa3db00c6a8 (patch) | |
tree | 549b791b6d9718a51d3f7c8258e076beafab64df /cli/lsp | |
parent | 3959d9f2d285bd45beb34074cf61090e2c4976dc (diff) |
fix(lsp): respect DENO_CERT and other options related to TLS certs (#13467)
Fixes #13437
Diffstat (limited to 'cli/lsp')
-rw-r--r-- | cli/lsp/cache.rs | 6 | ||||
-rw-r--r-- | cli/lsp/config.rs | 16 | ||||
-rw-r--r-- | cli/lsp/language_server.rs | 62 | ||||
-rw-r--r-- | cli/lsp/registries.rs | 54 | ||||
-rw-r--r-- | cli/lsp/repl.rs | 3 |
5 files changed, 107 insertions, 34 deletions
diff --git a/cli/lsp/cache.rs b/cli/lsp/cache.rs index 562ad78b0..e21bcff2d 100644 --- a/cli/lsp/cache.rs +++ b/cli/lsp/cache.rs @@ -33,6 +33,9 @@ impl CacheServer { maybe_cache_path: Option<PathBuf>, maybe_import_map: Option<Arc<ImportMap>>, maybe_config_file: Option<ConfigFile>, + maybe_ca_stores: Option<Vec<String>>, + maybe_ca_file: Option<String>, + unsafely_ignore_certificate_errors: Option<Vec<String>>, ) -> Self { let (tx, mut rx) = mpsc::unbounded_channel::<Request>(); let _join_handle = thread::spawn(move || { @@ -40,6 +43,9 @@ impl CacheServer { runtime.block_on(async { let ps = ProcState::build(Flags { cache_path: maybe_cache_path, + ca_stores: maybe_ca_stores, + ca_file: maybe_ca_file, + unsafely_ignore_certificate_errors, ..Default::default() }) .await diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index 89924a22a..37558e1b7 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -154,6 +154,10 @@ pub struct WorkspaceSettings { /// cache/DENO_DIR for the language server. pub cache: Option<String>, + /// Override the default stores used to validate certificates. This overrides + /// the environment variable `DENO_TLS_CA_STORE` if present. + pub certificate_stores: Option<Vec<String>>, + /// An option that points to a path string of the config file to apply to /// code within the workspace. pub config: Option<String>, @@ -179,6 +183,15 @@ pub struct WorkspaceSettings { #[serde(default)] pub suggest: CompletionSettings, + /// An option which sets the cert file to use when attempting to fetch remote + /// resources. This overrides `DENO_CERT` if present. + pub tls_certificate: Option<String>, + + /// An option, if set, will unsafely ignore certificate errors when fetching + /// remote resources. + #[serde(default)] + pub unsafely_ignore_certificate_errors: Option<Vec<String>>, + #[serde(default)] pub unstable: bool, } @@ -485,6 +498,7 @@ mod tests { WorkspaceSettings { enable: false, cache: None, + certificate_stores: None, config: None, import_map: None, code_lens: CodeLensSettings { @@ -505,6 +519,8 @@ mod tests { hosts: HashMap::new(), } }, + tls_certificate: None, + unsafely_ignore_certificate_errors: None, unstable: false, } ); diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index e33ffc93a..5ad0c17a6 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -48,7 +48,8 @@ use super::lsp_custom; use super::parent_process_checker; use super::performance::Performance; use super::refactor; -use super::registries; +use super::registries::ModuleRegistry; +use super::registries::ModuleRegistryOptions; use super::text; use super::tsc; use super::tsc::AssetDocument; @@ -96,7 +97,7 @@ pub(crate) struct Inner { /// on disk or "open" within the client. pub(crate) documents: Documents, /// Handles module registries, which allow discovery of modules - module_registries: registries::ModuleRegistry, + module_registries: ModuleRegistry, /// The path to the module registries cache module_registries_location: PathBuf, /// An optional path to the DENO_DIR which has been specified in the client @@ -139,8 +140,11 @@ impl Inner { let dir = deno_dir::DenoDir::new(maybe_custom_root) .expect("could not access DENO_DIR"); let module_registries_location = dir.root.join(REGISTRIES_PATH); - let module_registries = - registries::ModuleRegistry::new(&module_registries_location); + let module_registries = ModuleRegistry::new( + &module_registries_location, + ModuleRegistryOptions::default(), + ) + .expect("could not create module registries"); let location = dir.root.join(CACHE_PATH); let documents = Documents::new(&location); let performance = Arc::new(Performance::default()); @@ -425,11 +429,23 @@ impl Inner { let maybe_custom_root = maybe_cache_path .clone() .or_else(|| env::var("DENO_DIR").map(String::into).ok()); - let dir = deno_dir::DenoDir::new(maybe_custom_root) - .expect("could not access DENO_DIR"); + let dir = deno_dir::DenoDir::new(maybe_custom_root)?; let module_registries_location = dir.root.join(REGISTRIES_PATH); - self.module_registries = - registries::ModuleRegistry::new(&module_registries_location); + let workspace_settings = self.config.get_workspace_settings(); + let maybe_root_path = self + .root_uri + .as_ref() + .and_then(|uri| fs_util::specifier_to_file_path(uri).ok()); + self.module_registries = ModuleRegistry::new( + &module_registries_location, + ModuleRegistryOptions { + maybe_root_path, + maybe_ca_stores: workspace_settings.certificate_stores.clone(), + maybe_ca_file: workspace_settings.tls_certificate.clone(), + unsafely_ignore_certificate_errors: workspace_settings + .unsafely_ignore_certificate_errors, + }, + )?; self.module_registries_location = module_registries_location; self.documents.set_location(dir.root.join(CACHE_PATH)); self.maybe_cache_path = maybe_cache_path; @@ -496,14 +512,23 @@ impl Inner { async fn update_registries(&mut self) -> Result<(), AnyError> { let mark = self.performance.mark("update_registries", None::<()>); - for (registry, enabled) in self - .config - .get_workspace_settings() - .suggest - .imports - .hosts - .iter() - { + let workspace_settings = self.config.get_workspace_settings(); + let maybe_root_path = self + .root_uri + .as_ref() + .and_then(|uri| fs_util::specifier_to_file_path(uri).ok()); + self.module_registries = ModuleRegistry::new( + &self.module_registries_location, + ModuleRegistryOptions { + maybe_root_path, + maybe_ca_stores: workspace_settings.certificate_stores.clone(), + maybe_ca_file: workspace_settings.tls_certificate.clone(), + unsafely_ignore_certificate_errors: workspace_settings + .unsafely_ignore_certificate_errors + .clone(), + }, + )?; + for (registry, enabled) in workspace_settings.suggest.imports.hosts.iter() { if *enabled { lsp_log!("Enabling import suggestions for: {}", registry); self.module_registries.enable(registry).await?; @@ -2583,6 +2608,9 @@ impl Inner { self.maybe_cache_path.clone(), self.maybe_import_map.clone(), self.maybe_config_file.clone(), + None, + None, + None, ) .await, ); @@ -2616,8 +2644,6 @@ impl Inner { error!("Unable to remove registries cache: {}", err); LspError::internal_error() })?; - self.module_registries = - registries::ModuleRegistry::new(&self.module_registries_location); self.update_registries().await.map_err(|err| { error!("Unable to update registries: {}", err); LspError::internal_error() diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs index 418c19fe3..0b8a4240b 100644 --- a/cli/lsp/registries.rs +++ b/cli/lsp/registries.rs @@ -12,6 +12,7 @@ use super::path_to_regex::StringOrVec; use super::path_to_regex::Token; use crate::deno_dir; +use crate::file_fetcher::get_root_cert_store; use crate::file_fetcher::CacheSetting; use crate::file_fetcher::FileFetcher; use crate::http_cache::HttpCache; @@ -37,6 +38,7 @@ use once_cell::sync::Lazy; use regex::Regex; use std::collections::HashMap; use std::path::Path; +use std::path::PathBuf; const CONFIG_PATH: &str = "/.well-known/deno-import-intellisense.json"; const COMPONENT: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS @@ -406,11 +408,19 @@ enum VariableItems { List(VariableItemsList), } +#[derive(Debug, Default)] +pub(crate) struct ModuleRegistryOptions { + pub maybe_root_path: Option<PathBuf>, + pub maybe_ca_stores: Option<Vec<String>>, + pub maybe_ca_file: Option<String>, + pub unsafely_ignore_certificate_errors: Option<Vec<String>>, +} + /// A structure which holds the information about currently configured module /// registries and can provide completion information for URLs that match /// one of the enabled registries. #[derive(Debug, Clone)] -pub struct ModuleRegistry { +pub(crate) struct ModuleRegistry { origins: HashMap<String, Vec<RegistryConfiguration>>, file_fetcher: FileFetcher, } @@ -422,29 +432,35 @@ impl Default for ModuleRegistry { // custom root. let dir = deno_dir::DenoDir::new(None).unwrap(); let location = dir.root.join("registries"); - Self::new(&location) + Self::new(&location, ModuleRegistryOptions::default()).unwrap() } } impl ModuleRegistry { - pub fn new(location: &Path) -> Self { + pub fn new( + location: &Path, + options: ModuleRegistryOptions, + ) -> Result<Self, AnyError> { let http_cache = HttpCache::new(location); + let root_cert_store = Some(get_root_cert_store( + options.maybe_root_path, + options.maybe_ca_stores, + options.maybe_ca_file, + )?); let mut file_fetcher = FileFetcher::new( http_cache, CacheSetting::RespectHeaders, true, - None, + root_cert_store, BlobStore::default(), - None, - ) - .context("Error creating file fetcher in module registry.") - .unwrap(); + options.unsafely_ignore_certificate_errors, + )?; file_fetcher.set_download_log_level(super::logging::lsp_log_level()); - Self { + Ok(Self { origins: HashMap::new(), file_fetcher, - } + }) } fn complete_literal( @@ -1200,7 +1216,8 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new().expect("could not create tmp"); let location = temp_dir.path().join("registries"); - let mut module_registry = ModuleRegistry::new(&location); + let mut module_registry = + ModuleRegistry::new(&location, ModuleRegistryOptions::default()).unwrap(); module_registry .enable("http://localhost:4545/") .await @@ -1260,7 +1277,8 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new().expect("could not create tmp"); let location = temp_dir.path().join("registries"); - let mut module_registry = ModuleRegistry::new(&location); + let mut module_registry = + ModuleRegistry::new(&location, ModuleRegistryOptions::default()).unwrap(); module_registry .enable("http://localhost:4545/") .await @@ -1482,7 +1500,8 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new().expect("could not create tmp"); let location = temp_dir.path().join("registries"); - let mut module_registry = ModuleRegistry::new(&location); + let mut module_registry = + ModuleRegistry::new(&location, ModuleRegistryOptions::default()).unwrap(); module_registry .enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-key-first.json") .await @@ -1551,7 +1570,8 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new().expect("could not create tmp"); let location = temp_dir.path().join("registries"); - let mut module_registry = ModuleRegistry::new(&location); + let mut module_registry = + ModuleRegistry::new(&location, ModuleRegistryOptions::default()).unwrap(); module_registry .enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-complex.json") .await @@ -1601,7 +1621,8 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new().expect("could not create tmp"); let location = temp_dir.path().join("registries"); - let module_registry = ModuleRegistry::new(&location); + let module_registry = + ModuleRegistry::new(&location, ModuleRegistryOptions::default()).unwrap(); let result = module_registry.check_origin("http://localhost:4545").await; assert!(result.is_ok()); } @@ -1611,7 +1632,8 @@ mod tests { let _g = test_util::http_server(); let temp_dir = TempDir::new().expect("could not create tmp"); let location = temp_dir.path().join("registries"); - let module_registry = ModuleRegistry::new(&location); + let module_registry = + ModuleRegistry::new(&location, ModuleRegistryOptions::default()).unwrap(); let result = module_registry.check_origin("https://deno.com").await; assert!(result.is_err()); let err = result.unwrap_err().to_string(); diff --git a/cli/lsp/repl.rs b/cli/lsp/repl.rs index b4bc1daf7..0a2603298 100644 --- a/cli/lsp/repl.rs +++ b/cli/lsp/repl.rs @@ -277,11 +277,14 @@ pub fn get_repl_workspace_settings() -> WorkspaceSettings { WorkspaceSettings { enable: true, config: None, + certificate_stores: None, cache: None, import_map: None, code_lens: Default::default(), internal_debug: false, lint: false, + tls_certificate: None, + unsafely_ignore_certificate_errors: None, unstable: false, suggest: CompletionSettings { complete_function_calls: false, |