Skip to content

Commit

Permalink
Use CLI for old management interface to simplify dependency tree
Browse files Browse the repository at this point in the history
  • Loading branch information
dlon committed Sep 24, 2023
1 parent 2912759 commit c60bb86
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 400 deletions.
311 changes: 61 additions & 250 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion test/test-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ tower = { workspace = true }
colored = "2.0.0"

mullvad-management-interface = { path = "../../mullvad-management-interface" }
old-mullvad-management-interface = { git = "https://github.com/mullvad/mullvadvpn-app", rev = "2023.3", package = "mullvad-management-interface" }
talpid-types = { path = "../../talpid-types" }
mullvad-types = { path = "../../mullvad-types" }
# FIXME: does this always enable override?
Expand Down
34 changes: 34 additions & 0 deletions test/test-manager/api-addrs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
45.83.223.193
185.217.116.1
185.217.116.129
45.83.223.196
146.70.141.154
37.120.218.170
217.138.213.18
198.44.140.226
193.32.127.117
91.193.4.210
217.138.199.106
185.213.155.117
193.138.7.132
193.32.126.117
141.98.252.66
89.238.134.58
103.125.233.210
185.242.4.34
185.65.134.116
91.90.44.10
194.127.199.245
5.253.206.194
185.213.154.117
193.138.218.71
146.70.192.34
66.115.180.241
68.235.44.130
174.127.113.18
62.133.44.202
146.70.183.34
212.103.48.226
38.132.121.146
198.54.130.178
69.4.234.146
9 changes: 9 additions & 0 deletions test/test-manager/generate-api-endpoints.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

# Output known API IPs and bridge relay IPs

dig +short api.mullvad.net
dig +short api.devmole.eu
dig +short api.stagemole.eu
echo "45.83.223.196" # old prod
curl -s https://api.mullvad.net/app/v1/relays | jq -r '.bridge.relays[] | .ipv4_addr_in'
2 changes: 1 addition & 1 deletion test/test-manager/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ enum Commands {
///
/// # Note
///
/// The gRPC interface must be compatible with the version specified for `old-mullvad-management-interface` in Cargo.toml.
/// The CLI interface must be compatible with the upgrade test.
#[arg(long, short)]
previous_app: String,

Expand Down
16 changes: 0 additions & 16 deletions test/test-manager/src/mullvad_daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use test_rpc::{
};
use tokio::io::{AsyncReadExt, AsyncWriteExt, DuplexStream};
use tokio_util::codec::{Decoder, LengthDelimitedCodec};
use tonic::transport::Uri;
use tower::Service;

const GRPC_REQUEST_TIMEOUT: Duration = Duration::from_secs(10);
Expand Down Expand Up @@ -58,7 +57,6 @@ impl RpcClientProvider {
) -> Box<dyn std::any::Any + Send> {
match client_type {
MullvadClientVersion::New => Box::new(self.new_client().await),
MullvadClientVersion::Previous => Box::new(self.old_client().await),
MullvadClientVersion::None => Box::new(()),
}
}
Expand All @@ -76,20 +74,6 @@ impl RpcClientProvider {

ManagementServiceClient::new(channel)
}

async fn old_client(&self) -> old_mullvad_management_interface::ManagementServiceClient {
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
log::debug!("Mullvad daemon (old): connecting");
let channel = old_mullvad_management_interface::Channel::builder(Uri::from_static(
"serial://placeholder",
))
.timeout(GRPC_REQUEST_TIMEOUT)
.connect_with_connector(self.service.clone())
.await
.unwrap();

old_mullvad_management_interface::ManagementServiceClient::new(channel)
}
}

pub async fn new_rpc_client(
Expand Down
63 changes: 0 additions & 63 deletions test/test-manager/src/tests/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,69 +27,6 @@ macro_rules! assert_tunnel_state {
}};
}

/// Return all possible API endpoints. Note that this includes all bridge IPs. Ideally,
/// we'd keep track of the current API IP, not exonerate all bridges from being considered
/// leaky.
#[macro_export]
macro_rules! get_possible_api_endpoints {
($mullvad_client:expr) => {{
use std::net::ToSocketAddrs;

let mut api_endpoints = vec![
"api.devmole.eu:0"
.to_socket_addrs()
.expect("failed to resolve api.devmole.eu")
.next()
.unwrap()
.ip(),
"api.stagemole.eu:0"
.to_socket_addrs()
.expect("failed to resolve api.stagemole.eu")
.next()
.unwrap()
.ip(),
"api.mullvad.net:0"
.to_socket_addrs()
.expect("failed to resolve api.mullvad.net")
.next()
.unwrap()
.ip(),
IpAddr::V4(Ipv4Addr::new(45, 83, 223, 196)),
];

let relay_list = $mullvad_client
.get_relay_locations(())
.await
.map_err(|error| Error::DaemonError(format!("Failed to obtain relay list: {}", error)))?
.into_inner();

api_endpoints.extend(
relay_list
.countries
.into_iter()
.flat_map(|country| country.cities)
.filter_map(|mut city| {
city.relays.retain(|relay| {
relay.active
&& relay.endpoint_type == (types::relay::RelayType::Bridge as i32)
});
if !city.relays.is_empty() {
Some(city)
} else {
None
}
})
.flat_map(|city| {
city.relays
.into_iter()
.map(|relay| IpAddr::V4(relay.ipv4_addr_in.parse().expect("invalid IP")))
}),
);

Ok::<Vec<IpAddr>, Error>(api_endpoints)
}};
}

pub fn get_package_desc(name: &str) -> Result<Package, Error> {
Ok(Package {
path: Path::new(&TEST_CONFIG.artifacts_dir).join(name),
Expand Down
61 changes: 15 additions & 46 deletions test/test-manager/src/tests/install.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use super::helpers::{get_package_desc, ping_with_timeout, AbortOnDrop};
use super::{Error, TestContext};
use crate::get_possible_api_endpoints;

use super::config::TEST_CONFIG;
use crate::network_monitor::{start_packet_monitor, MonitorOptions};
use mullvad_management_interface::types;
use once_cell::sync::Lazy;
use std::collections::HashMap;
use std::net::ToSocketAddrs;
use std::{
net::{IpAddr, Ipv4Addr, SocketAddr},
net::{IpAddr, SocketAddr},
time::Duration,
};
use test_macro::test_function;
Expand Down Expand Up @@ -53,8 +53,13 @@ pub async fn test_install_previous_app(_: TestContext, rpc: ServiceClient) -> Re
pub async fn test_upgrade_app(
ctx: TestContext,
rpc: ServiceClient,
mut mullvad_client: old_mullvad_management_interface::ManagementServiceClient,
) -> Result<(), Error> {
// Parse api-addrs.txt
const API_ADDRS: Lazy<Vec<IpAddr>> = Lazy::new(|| {
const API_ADDRS: &str = std::include_str!("../../api-addrs.txt");
API_ADDRS.split('\n').map(|addr| addr.parse().unwrap()).collect()
});

let inet_destination: SocketAddr = "1.1.1.1:1337".parse().unwrap();
let bind_addr: SocketAddr = "0.0.0.0:0".parse().unwrap();

Expand All @@ -79,48 +84,15 @@ pub async fn test_upgrade_app(
//
log::debug!("Entering blocking error state");

mullvad_client
.update_relay_settings(
old_mullvad_management_interface::types::RelaySettingsUpdate {
r#type: Some(
old_mullvad_management_interface::types::relay_settings_update::Type::Normal(
old_mullvad_management_interface::types::NormalRelaySettingsUpdate {
location: Some(
old_mullvad_management_interface::types::RelayLocation {
country: "xx".to_string(),
city: "".to_string(),
hostname: "".to_string(),
},
),
..Default::default()
},
),
),
},
)
.await
.map_err(|error| Error::DaemonError(format!("Failed to set relay settings: {}", error)))?;
rpc.exec("mullvad", ["relay", "set", "location", "xx"]).await.expect("Failed to set relay location");
rpc.exec("mullvad", ["connect"]).await.expect("Failed to begin connecting");

// cannot use the event listener due since the proto file is incompatible
mullvad_client
.connect_tunnel(())
.await
.expect("failed to begin connecting");
tokio::time::timeout(super::WAIT_FOR_TUNNEL_STATE_TIMEOUT, async {
// use polling for sake of simplicity
loop {
// use polling for sake of simplicity
if matches!(
mullvad_client
.get_tunnel_state(())
.await
.expect("RPC error")
.into_inner(),
old_mullvad_management_interface::types::TunnelState {
state: Some(
old_mullvad_management_interface::types::tunnel_state::State::Error { .. }
),
}
) {
const FIND_SLICE: &[u8] = b"Blocked:";
let result = rpc.exec("mullvad", ["status"]).await.expect("Failed to poll tunnel status");
if result.stdout.windows(FIND_SLICE.len()).any(|subslice| subslice == FIND_SLICE) {
break;
}
tokio::time::sleep(Duration::from_secs(1)).await;
Expand All @@ -139,13 +111,11 @@ pub async fn test_upgrade_app(
.expect("failed to obtain tunnel IP");
log::debug!("Guest IP: {guest_ip}");

let api_endpoints = get_possible_api_endpoints!(&mut mullvad_client)?;

log::debug!("Monitoring outgoing traffic");

let monitor = start_packet_monitor(
move |packet| {
packet.source.ip() == guest_ip && !api_endpoints.contains(&packet.destination.ip())
packet.source.ip() == guest_ip && !API_ADDRS.contains(&packet.destination.ip())
},
MonitorOptions::default(),
)
Expand Down Expand Up @@ -185,7 +155,6 @@ pub async fn test_upgrade_app(
"observed unexpected packets from {guest_ip}"
);

drop(mullvad_client);
let mut mullvad_client = ctx.rpc_provider.new_client().await;

// check if settings were (partially) preserved
Expand Down
20 changes: 0 additions & 20 deletions test/test-manager/test_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
//! rpc: ServiceClient,
//! mut mullvad_client: mullvad_management_interface::ManagementServiceClient,
//! ) -> Result<(), Error> {
//! The `mullvad_client` argument can be removed or replaced with the `old_mullvad_management_interface` version.
//! The `test_function` macro takes 4 optional arguments
//! #[test_function(priority = -1337, cleanup = false, must_succeed = true, always_run = true)]
//!
Expand Down Expand Up @@ -118,10 +117,6 @@ fn create_test(test_function: TestFunction) -> proc_macro2::TokenStream {
MullvadClient::New {
mullvad_client_type,
..
}
| MullvadClient::Old {
mullvad_client_type,
..
} => {
let mullvad_client_type = *mullvad_client_type;
quote! {
Expand Down Expand Up @@ -185,10 +180,6 @@ enum MullvadClient {
mullvad_client_type: Box<syn::Type>,
mullvad_client_version: proc_macro2::TokenStream,
},
Old {
mullvad_client_type: Box<syn::Type>,
mullvad_client_version: proc_macro2::TokenStream,
},
}

impl MullvadClient {
Expand All @@ -201,10 +192,6 @@ impl MullvadClient {
mullvad_client_version,
..
} => mullvad_client_version.clone(),
MullvadClient::Old {
mullvad_client_version,
..
} => mullvad_client_version.clone(),
}
}
}
Expand All @@ -230,13 +217,6 @@ fn get_test_function_parameters(
mullvad_client_version,
}
}
"old_mullvad_management_interface" => {
let mullvad_client_version = quote! { test_rpc::mullvad_daemon::MullvadClientVersion::Previous };
MullvadClient::Old {
mullvad_client_type: pat_type.ty,
mullvad_client_version,
}
}
_ => panic!("cannot infer mullvad client type"),
}
}
Expand Down
4 changes: 2 additions & 2 deletions test/test-rpc/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl ServiceClient {

/// Execute a program.
pub async fn exec_env<
I: Iterator<Item = T>,
I: IntoIterator<Item = T>,
M: IntoIterator<Item = (K, T)>,
T: AsRef<str>,
K: AsRef<str>,
Expand All @@ -80,7 +80,7 @@ impl ServiceClient {
}

/// Execute a program.
pub async fn exec<I: Iterator<Item = T>, T: AsRef<str>>(
pub async fn exec<I: IntoIterator<Item = T>, T: AsRef<str>>(
&self,
path: T,
args: I,
Expand Down
1 change: 0 additions & 1 deletion test/test-rpc/src/mullvad_daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,4 @@ pub enum Verbosity {
pub enum MullvadClientVersion {
None,
New,
Previous,
}

0 comments on commit c60bb86

Please sign in to comment.