diff options
| author | Markus Pettersson <markus.pettersson@mullvad.net> | 2024-04-12 14:57:18 +0200 |
|---|---|---|
| committer | Markus Pettersson <markus.pettersson@mullvad.net> | 2024-04-12 14:57:18 +0200 |
| commit | f36bd2e90024501f46a9dabfb032bbc9ab2b6627 (patch) | |
| tree | d8888348de504beac26bd55971bce903b162324b | |
| parent | be0a46a83ea131caad8c0a972ae337a86871b3a5 (diff) | |
| parent | eb3c0562b17f3e4928a98c13ac29b3a582a6977c (diff) | |
| download | mullvadvpn-f36bd2e90024501f46a9dabfb032bbc9ab2b6627.tar.xz mullvadvpn-f36bd2e90024501f46a9dabfb032bbc9ab2b6627.zip | |
Merge branch 'e2e-tests-cleanup'
| -rw-r--r-- | mullvad-daemon/src/access_method.rs | 11 | ||||
| -rw-r--r-- | mullvad-daemon/src/custom_list.rs | 113 | ||||
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 19 | ||||
| -rw-r--r-- | mullvad-daemon/src/management_interface.rs | 20 | ||||
| -rw-r--r-- | mullvad-management-interface/proto/management_interface.proto | 2 | ||||
| -rw-r--r-- | mullvad-management-interface/src/client.rs | 18 | ||||
| -rw-r--r-- | mullvad-types/src/access_method.rs | 6 | ||||
| -rw-r--r-- | mullvad-types/src/custom_list.rs | 5 | ||||
| -rw-r--r-- | test/test-manager/src/tests/mod.rs | 73 |
9 files changed, 218 insertions, 49 deletions
diff --git a/mullvad-daemon/src/access_method.rs b/mullvad-daemon/src/access_method.rs index bc843f529e..edae229ae0 100644 --- a/mullvad-daemon/src/access_method.rs +++ b/mullvad-daemon/src/access_method.rs @@ -128,6 +128,17 @@ where Ok(()) } + /// Remove all custom [`AccessMethodSetting`]. + pub async fn clear_custom_api_access_methods(&mut self) -> Result<(), Error> { + self.settings + .update(|settings: &mut Settings| { + settings.api_access_methods.clear_custom(); + }) + .await?; + + Ok(()) + } + /// Return the [`AccessMethodSetting`] which is currently used to access the /// Mullvad API. pub async fn get_current_access_method(&self) -> Result<AccessMethodSetting, Error> { diff --git a/mullvad-daemon/src/custom_list.rs b/mullvad-daemon/src/custom_list.rs index c15fd14a70..df9f30a519 100644 --- a/mullvad-daemon/src/custom_list.rs +++ b/mullvad-daemon/src/custom_list.rs @@ -10,6 +10,9 @@ impl<L> Daemon<L> where L: EventListener + Clone + Send + 'static, { + /// Create a new custom list. + /// + /// Returns an error if the name is not unique. pub async fn create_custom_list(&mut self, name: String) -> Result<Id, crate::Error> { if self .settings @@ -33,6 +36,9 @@ where Ok(id) } + /// Update a custom list. + /// + /// Returns an error if the list doesn't exist. pub async fn delete_custom_list(&mut self, id: Id) -> Result<(), Error> { let Some(list_index) = self .settings @@ -56,7 +62,7 @@ where self.relay_selector .set_config(new_selector_config(&self.settings)); - if self.change_should_cause_reconnect(id) { + if self.change_should_cause_reconnect(Some(id)) { log::info!("Initiating tunnel restart because a selected custom list was deleted"); self.reconnect_tunnel(); } @@ -66,6 +72,11 @@ where Ok(()) } + /// Update a custom list. + /// + /// Returns an error if... + /// - there is no existing list with the same ID, + /// - or the existing list has a different name. pub async fn update_custom_list(&mut self, new_list: CustomList) -> Result<(), Error> { let Some((list_index, old_list)) = self .settings @@ -100,7 +111,7 @@ where self.relay_selector .set_config(new_selector_config(&self.settings)); - if self.change_should_cause_reconnect(id) { + if self.change_should_cause_reconnect(Some(id)) { log::info!("Initiating tunnel restart because a selected custom list changed"); self.reconnect_tunnel(); } @@ -110,48 +121,78 @@ where Ok(()) } - fn change_should_cause_reconnect(&self, custom_list_id: Id) -> bool { + /// Remove all custom lists. + pub async fn clear_custom_lists(&mut self) -> Result<(), Error> { + let settings_changed = self + .settings + .update(|settings| { + settings.custom_lists.clear(); + }) + .await + .map_err(Error::SettingsError); + + if let Ok(true) = settings_changed { + self.relay_selector + .set_config(new_selector_config(&self.settings)); + + if self.change_should_cause_reconnect(None) { + log::info!("Initiating tunnel restart because a selected custom list was deleted"); + self.reconnect_tunnel(); + } + } + + settings_changed?; + Ok(()) + } + + /// Check whether we need to reconnect after changing custom lists. + /// + /// If `custom_list_id` is `Some`, only changes to that custom list will trigger a reconnect. + fn change_should_cause_reconnect(&self, custom_list_id: Option<Id>) -> bool { use mullvad_types::states::TunnelState; let mut need_to_reconnect = false; - if let RelaySettings::Normal(relay_settings) = &self.settings.relay_settings { - if let Constraint::Only(LocationConstraint::CustomList { list_id }) = - &relay_settings.location - { - need_to_reconnect |= list_id == &custom_list_id; - } + let RelaySettings::Normal(relay_settings) = &self.settings.relay_settings else { + return false; + }; - if let TunnelState::Connecting { - endpoint, - location: _, - } - | TunnelState::Connected { - endpoint, - location: _, - } = &self.tunnel_state - { - match endpoint.tunnel_type { - TunnelType::Wireguard => { - if relay_settings.wireguard_constraints.multihop() { - if let Constraint::Only(LocationConstraint::CustomList { list_id }) = - &relay_settings.wireguard_constraints.entry_location - { - need_to_reconnect |= list_id == &custom_list_id; - } + if let Constraint::Only(LocationConstraint::CustomList { list_id }) = + &relay_settings.location + { + need_to_reconnect |= custom_list_id.map(|id| &id == list_id).unwrap_or(true); + } + + if let TunnelState::Connecting { + endpoint, + location: _, + } + | TunnelState::Connected { + endpoint, + location: _, + } = &self.tunnel_state + { + match endpoint.tunnel_type { + TunnelType::Wireguard => { + if relay_settings.wireguard_constraints.multihop() { + if let Constraint::Only(LocationConstraint::CustomList { list_id }) = + &relay_settings.wireguard_constraints.entry_location + { + need_to_reconnect |= + custom_list_id.map(|id| &id == list_id).unwrap_or(true); } } + } - TunnelType::OpenVpn => { - if !matches!(self.settings.bridge_state, BridgeState::Off) { - if let Ok(ResolvedBridgeSettings::Normal(bridge_settings)) = - self.settings.bridge_settings.resolve() + TunnelType::OpenVpn => { + if !matches!(self.settings.bridge_state, BridgeState::Off) { + if let Ok(ResolvedBridgeSettings::Normal(bridge_settings)) = + self.settings.bridge_settings.resolve() + { + if let Constraint::Only(LocationConstraint::CustomList { list_id }) = + &bridge_settings.location { - if let Constraint::Only(LocationConstraint::CustomList { - list_id, - }) = &bridge_settings.location - { - need_to_reconnect |= list_id == &custom_list_id; - } + need_to_reconnect |= + custom_list_id.map(|id| &id == list_id).unwrap_or(true); } } } diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index c3c64ebacf..365e82efeb 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -279,6 +279,8 @@ pub enum DaemonCommand { DeleteCustomList(ResponseTx<(), Error>, mullvad_types::custom_list::Id), /// Update a custom list with a given id UpdateCustomList(ResponseTx<(), Error>, CustomList), + /// Remove all custom lists + ClearCustomLists(ResponseTx<(), Error>), /// Add API access methods AddApiAccessMethod( ResponseTx<mullvad_types::access_method::Id, Error>, @@ -292,6 +294,8 @@ pub enum DaemonCommand { SetApiAccessMethod(ResponseTx<(), Error>, mullvad_types::access_method::Id), /// Edit an API access method UpdateApiAccessMethod(ResponseTx<(), Error>, AccessMethodSetting), + /// Remove all custom API access methods + ClearCustomApiAccessMethods(ResponseTx<(), Error>), /// Get the currently used API access method GetCurrentAccessMethod(ResponseTx<AccessMethodSetting, Error>), /// Test an API access method @@ -1253,6 +1257,7 @@ where CreateCustomList(tx, name) => self.on_create_custom_list(tx, name).await, DeleteCustomList(tx, id) => self.on_delete_custom_list(tx, id).await, UpdateCustomList(tx, update) => self.on_update_custom_list(tx, update).await, + ClearCustomLists(tx) => self.on_clear_custom_lists(tx).await, GetVersionInfo(tx) => self.on_get_version_info(tx), AddApiAccessMethod(tx, name, enabled, access_method) => { self.on_add_access_method(tx, name, enabled, access_method) @@ -1260,6 +1265,7 @@ where } RemoveApiAccessMethod(tx, method) => self.on_remove_api_access_method(tx, method).await, UpdateApiAccessMethod(tx, method) => self.on_update_api_access_method(tx, method).await, + ClearCustomApiAccessMethods(tx) => self.on_clear_custom_api_access_methods(tx).await, GetCurrentAccessMethod(tx) => self.on_get_current_api_access_method(tx), SetApiAccessMethod(tx, method) => self.on_set_api_access_method(tx, method).await, TestApiAccessMethodById(tx, method) => self.on_test_api_access_method(tx, method).await, @@ -2432,6 +2438,11 @@ where Self::oneshot_send(tx, result, "update_custom_list response"); } + async fn on_clear_custom_lists(&mut self, tx: ResponseTx<(), Error>) { + let result = self.clear_custom_lists().await; + Self::oneshot_send(tx, result, "clear_custom_lists response"); + } + async fn on_add_access_method( &mut self, tx: ResponseTx<mullvad_types::access_method::Id, Error>, @@ -2482,6 +2493,14 @@ where Self::oneshot_send(tx, result, "update_api_access_method response"); } + async fn on_clear_custom_api_access_methods(&mut self, tx: ResponseTx<(), Error>) { + let result = self + .clear_custom_api_access_methods() + .await + .map_err(Error::AccessMethodError); + Self::oneshot_send(tx, result, "clear_custom_api_access_methods response"); + } + fn on_get_current_api_access_method(&mut self, tx: ResponseTx<AccessMethodSetting, Error>) { let handle = self.access_mode_handler.clone(); tokio::spawn(async move { diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index ee0fadaa0e..55573f87a7 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -598,6 +598,16 @@ impl ManagementService for ManagementServiceImpl { .map_err(map_daemon_error) } + async fn clear_custom_lists(&self, _: Request<()>) -> ServiceResult<()> { + log::debug!("clear_custom_lists"); + let (tx, rx) = oneshot::channel(); + self.send_command_to_daemon(DaemonCommand::ClearCustomLists(tx))?; + self.wait_for_result(rx) + .await? + .map(Response::new) + .map_err(map_daemon_error) + } + // Access Methods async fn add_api_access_method( @@ -663,6 +673,16 @@ impl ManagementService for ManagementServiceImpl { .map_err(map_daemon_error) } + async fn clear_custom_api_access_methods(&self, _: Request<()>) -> ServiceResult<()> { + log::debug!("clear_custom_api_access_methods"); + let (tx, rx) = oneshot::channel(); + self.send_command_to_daemon(DaemonCommand::ClearCustomApiAccessMethods(tx))?; + self.wait_for_result(rx) + .await? + .map(Response::new) + .map_err(map_daemon_error) + } + /// Return the [`types::AccessMethodSetting`] which the daemon is using to /// connect to the Mullvad API. async fn get_current_api_access_method( diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto index 7fbdb6eba6..8af34aa8af 100644 --- a/mullvad-management-interface/proto/management_interface.proto +++ b/mullvad-management-interface/proto/management_interface.proto @@ -73,12 +73,14 @@ service ManagementService { rpc CreateCustomList(google.protobuf.StringValue) returns (google.protobuf.StringValue) {} rpc DeleteCustomList(google.protobuf.StringValue) returns (google.protobuf.Empty) {} rpc UpdateCustomList(CustomList) returns (google.protobuf.Empty) {} + rpc ClearCustomLists(google.protobuf.Empty) returns (google.protobuf.Empty) {} // Access methods rpc AddApiAccessMethod(NewAccessMethodSetting) returns (UUID) {} rpc RemoveApiAccessMethod(UUID) returns (google.protobuf.Empty) {} rpc SetApiAccessMethod(UUID) returns (google.protobuf.Empty) {} rpc UpdateApiAccessMethod(AccessMethodSetting) returns (google.protobuf.Empty) {} + rpc ClearCustomApiAccessMethods(google.protobuf.Empty) returns (google.protobuf.Empty) {} rpc GetCurrentApiAccessMethod(google.protobuf.Empty) returns (AccessMethodSetting) {} rpc TestCustomApiAccessMethod(CustomProxy) returns (google.protobuf.BoolValue) {} rpc TestApiAccessMethodById(UUID) returns (google.protobuf.BoolValue) {} diff --git a/mullvad-management-interface/src/client.rs b/mullvad-management-interface/src/client.rs index fd6c56e19f..8cf3ac495d 100644 --- a/mullvad-management-interface/src/client.rs +++ b/mullvad-management-interface/src/client.rs @@ -535,6 +535,15 @@ impl MullvadProxyClient { Ok(()) } + /// Remove all custom lists. + pub async fn clear_custom_lists(&mut self) -> Result<()> { + self.0 + .clear_custom_lists(()) + .await + .map_err(map_custom_list_error)?; + Ok(()) + } + pub async fn add_access_method( &mut self, name: String, @@ -575,6 +584,15 @@ impl MullvadProxyClient { .map(drop) } + /// Remove all custom API access methods. + pub async fn clear_custom_access_methods(&mut self) -> Result<()> { + self.0 + .clear_custom_api_access_methods(()) + .await + .map_err(Error::Rpc) + .map(drop) + } + /// Set the [`AccessMethod`] which [`ApiConnectionModeProvider`] should /// pick. /// diff --git a/mullvad-types/src/access_method.rs b/mullvad-types/src/access_method.rs index c5f0b41859..c42b099bae 100644 --- a/mullvad-types/src/access_method.rs +++ b/mullvad-types/src/access_method.rs @@ -74,6 +74,12 @@ impl Settings { updated } + /// Remove all custom access methods. + pub fn clear_custom(&mut self) { + self.custom.clear(); + self.ensure_consistent_state(); + } + /// Check that `self` contains atleast one enabled access methods. If not, /// the `Direct` access method is re-enabled. fn ensure_consistent_state(&mut self) { diff --git a/mullvad-types/src/custom_list.rs b/mullvad-types/src/custom_list.rs index b92f128a3b..89febe81ab 100644 --- a/mullvad-types/src/custom_list.rs +++ b/mullvad-types/src/custom_list.rs @@ -98,6 +98,11 @@ impl CustomListsSettings { pub fn remove(&mut self, index: usize) { self.custom_lists.remove(index); } + + /// Remove all custom lists + pub fn clear(&mut self) { + self.custom_lists.clear(); + } } impl IntoIterator for CustomListsSettings { diff --git a/test/test-manager/src/tests/mod.rs b/test/test-manager/src/tests/mod.rs index 32a32cb44a..f4c4563bde 100644 --- a/test/test-manager/src/tests/mod.rs +++ b/test/test-manager/src/tests/mod.rs @@ -77,58 +77,105 @@ pub async fn cleanup_after_test(mullvad_client: &mut MullvadProxyClient) -> anyh helpers::disconnect_and_wait(mullvad_client).await?; - let default_settings = mullvad_types::settings::Settings::default(); + // Bring all the settings into scope so we remember to reset them. + let mullvad_types::settings::Settings { + relay_settings, + bridge_settings, + obfuscation_settings, + bridge_state, + custom_lists, + api_access_methods, + allow_lan, + block_when_disconnected, + auto_connect, + tunnel_options, + relay_overrides, + show_beta_releases, + settings_version: _, // N/A + } = Default::default(); mullvad_client - .set_relay_settings(default_settings.relay_settings) + .clear_custom_access_methods() + .await + .context("Could not clear custom api access methods")?; + for access_method in api_access_methods.iter() { + mullvad_client + .update_access_method(access_method.clone()) + .await + .context("Could not reset default access method")?; + } + + mullvad_client + .set_relay_settings(relay_settings) .await .context("Could not set relay settings")?; + + let _ = relay_overrides; + mullvad_client + .clear_all_relay_overrides() + .await + .context("Could not set relay overrides")?; + mullvad_client - .set_auto_connect(default_settings.auto_connect) + .set_auto_connect(auto_connect) .await .context("Could not set auto connect in cleanup")?; + mullvad_client - .set_allow_lan(default_settings.allow_lan) + .set_allow_lan(allow_lan) .await .context("Could not set allow lan in cleanup")?; + mullvad_client - .set_show_beta_releases(default_settings.show_beta_releases) + .set_show_beta_releases(show_beta_releases) .await .context("Could not set show beta releases in cleanup")?; + mullvad_client - .set_bridge_state(default_settings.bridge_state) + .set_bridge_state(bridge_state) .await .context("Could not set bridge state in cleanup")?; + mullvad_client - .set_bridge_settings(default_settings.bridge_settings.clone()) + .set_bridge_settings(bridge_settings.clone()) .await .context("Could not set bridge settings in cleanup")?; + mullvad_client - .set_obfuscation_settings(default_settings.obfuscation_settings.clone()) + .set_obfuscation_settings(obfuscation_settings.clone()) .await .context("Could set obfuscation settings in cleanup")?; + mullvad_client - .set_block_when_disconnected(default_settings.block_when_disconnected) + .set_block_when_disconnected(block_when_disconnected) .await .context("Could not set block when disconnected setting in cleanup")?; - #[cfg(target_os = "windows")] + mullvad_client .clear_split_tunnel_apps() .await .context("Could not clear split tunnel apps in cleanup")?; - #[cfg(target_os = "linux")] + mullvad_client .clear_split_tunnel_processes() .await .context("Could not clear split tunnel processes in cleanup")?; + mullvad_client - .set_dns_options(default_settings.tunnel_options.dns_options.clone()) + .set_dns_options(tunnel_options.dns_options.clone()) .await .context("Could not clear dns options in cleanup")?; + mullvad_client - .set_quantum_resistant_tunnel(default_settings.tunnel_options.wireguard.quantum_resistant) + .set_quantum_resistant_tunnel(tunnel_options.wireguard.quantum_resistant) .await .context("Could not clear PQ options in cleanup")?; + let _ = custom_lists; + mullvad_client + .clear_custom_lists() + .await + .context("Could not remove custom list")?; + Ok(()) } |
