summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2024-04-12 14:57:18 +0200
committerMarkus Pettersson <markus.pettersson@mullvad.net>2024-04-12 14:57:18 +0200
commitf36bd2e90024501f46a9dabfb032bbc9ab2b6627 (patch)
treed8888348de504beac26bd55971bce903b162324b
parentbe0a46a83ea131caad8c0a972ae337a86871b3a5 (diff)
parenteb3c0562b17f3e4928a98c13ac29b3a582a6977c (diff)
downloadmullvadvpn-f36bd2e90024501f46a9dabfb032bbc9ab2b6627.tar.xz
mullvadvpn-f36bd2e90024501f46a9dabfb032bbc9ab2b6627.zip
Merge branch 'e2e-tests-cleanup'
-rw-r--r--mullvad-daemon/src/access_method.rs11
-rw-r--r--mullvad-daemon/src/custom_list.rs113
-rw-r--r--mullvad-daemon/src/lib.rs19
-rw-r--r--mullvad-daemon/src/management_interface.rs20
-rw-r--r--mullvad-management-interface/proto/management_interface.proto2
-rw-r--r--mullvad-management-interface/src/client.rs18
-rw-r--r--mullvad-types/src/access_method.rs6
-rw-r--r--mullvad-types/src/custom_list.rs5
-rw-r--r--test/test-manager/src/tests/mod.rs73
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(())
}