Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API access method tests #5798

Merged
merged 7 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/cargo-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ jobs:
# Ignored audit issues. This list should be kept short, and effort should be
# put into removing items from the list.
# RUSTSEC-2023-0057,RUSTSEC-2023-0058 - Unsoundness in `inventory`.
ignore: RUSTSEC-2023-0057,RUSTSEC-2023-0058
# RUSTSEC-2023-0079 - KyberSlash in `pqc_kyber`.
ignore: RUSTSEC-2023-0057,RUSTSEC-2023-0058,RUSTSEC-2023-0079
15 changes: 13 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 9 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,32 @@ members = [
"android/translations-converter",
"ios/MullvadREST/Transport/Shadowsocks/shadowsocks-proxy",
"ios/TunnelObfuscation/tunnel-obfuscator-proxy",
"mullvad-daemon",
"mullvad-api",
"mullvad-cli",
"mullvad-daemon",
"mullvad-exclude",
"mullvad-fs",
"mullvad-setup",
"mullvad-problem-report",
"mullvad-jni",
"mullvad-management-interface",
"mullvad-nsis",
"mullvad-paths",
"mullvad-problem-report",
"mullvad-relay-selector",
"mullvad-setup",
"mullvad-types",
"mullvad-api",
"mullvad-exclude",
"mullvad-version",
"mullvad-nsis",
"talpid-openvpn-plugin",
"talpid-core",
"talpid-dbus",
"talpid-future",
"talpid-openvpn",
"talpid-openvpn-plugin",
"talpid-platform-metadata",
"talpid-routing",
"talpid-time",
"talpid-tunnel",
"talpid-tunnel-config-client",
"talpid-windows",
"talpid-wireguard",
"mullvad-management-interface",
"tunnel-obfuscation",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ test('App should edit access method', async () => {
await inputs.nth(3).fill(process.env.SHADOWSOCKS_SERVER_PASSWORD!);

await page.getByTestId('ciphers').click();
await page.getByRole('option', { name: process.env.SHADOWSOCKS_SERVER_CIPHER! }).click();
await page.getByRole('option', { name: process.env.SHADOWSOCKS_SERVER_CIPHER!, exact: true }).click();

expect(
await util.waitForNavigation(async () => await saveButton.click())
Expand Down
69 changes: 47 additions & 22 deletions mullvad-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ impl<T> Deref for LazyManual<T> {
}
}

pub mod env {
pub const API_HOST_VAR: &str = "MULLVAD_API_HOST";
pub const API_ADDR_VAR: &str = "MULLVAD_API_ADDR";
pub const API_FORCE_DIRECT_VAR: &str = "MULLVAD_API_FORCE_DIRECT";
pub const DISABLE_TLS_VAR: &str = "MULLVAD_API_DISABLE_TLS";
}

/// A hostname and socketaddr to reach the Mullvad REST API over.
#[derive(Debug)]
pub struct ApiEndpoint {
Expand All @@ -128,17 +135,30 @@ pub struct ApiEndpoint {
pub disable_address_cache: bool,
#[cfg(feature = "api-override")]
pub disable_tls: bool,
#[cfg(feature = "api-override")]
/// Whether bridges/proxies can be used to access the API or not. This is
/// useful primarily for testing purposes.
///
/// * If `force_direct` is `true`, bridges and proxies will not be used to
/// reach the API.
/// * If `force_direct` is `false`, bridges and proxies can be used to reach the API.
///
/// # Note
///
/// By default, `force_direct` will be `true` if the `api-override` feature
/// is enabled. This is supposedely less error prone, as common targets such
/// as Devmole might be unreachable from behind a bridge server.
///
/// To disable `force_direct`, set the environment variable
/// `MULLVAD_API_FORCE_DIRECT=0` before starting the daemon.
pub force_direct: bool,
}

impl ApiEndpoint {
const API_HOST_DEFAULT: &'static str = "api.mullvad.net";
const API_IP_DEFAULT: IpAddr = IpAddr::V4(Ipv4Addr::new(45, 83, 223, 196));
const API_PORT_DEFAULT: u16 = 443;

const API_HOST_VAR: &'static str = "MULLVAD_API_HOST";
const API_ADDR_VAR: &'static str = "MULLVAD_API_ADDR";
const DISABLE_TLS_VAR: &'static str = "MULLVAD_API_DISABLE_TLS";

/// Returns the endpoint to connect to the API over.
///
/// # Panics
Expand All @@ -147,15 +167,19 @@ impl ApiEndpoint {
/// `MULLVAD_API_DISABLE_TLS` has invalid contents.
#[cfg(feature = "api-override")]
pub fn from_env_vars() -> ApiEndpoint {
let host_var = Self::read_var(ApiEndpoint::API_HOST_VAR);
let address_var = Self::read_var(ApiEndpoint::API_ADDR_VAR);
let disable_tls_var = Self::read_var(ApiEndpoint::DISABLE_TLS_VAR);
let host_var = Self::read_var(env::API_HOST_VAR);
let address_var = Self::read_var(env::API_ADDR_VAR);
let disable_tls_var = Self::read_var(env::DISABLE_TLS_VAR);
let force_direct = Self::read_var(env::API_FORCE_DIRECT_VAR);

let mut api = ApiEndpoint {
host: None,
address: None,
disable_address_cache: true,
disable_tls: false,
force_direct: force_direct
.map(|force_direct_env| force_direct_env.to_lowercase() != "0")
.unwrap_or(true),
};

match (host_var, address_var) {
Expand All @@ -164,8 +188,8 @@ impl ApiEndpoint {
use std::net::ToSocketAddrs;
log::debug!(
"{api_addr} not found. Resolving API IP address from {api_host}={host}",
api_addr = ApiEndpoint::API_ADDR_VAR,
api_host = ApiEndpoint::API_HOST_VAR
api_addr = env::API_ADDR_VAR,
api_host = env::API_HOST_VAR
);
api.address = format!("{}:{}", host, ApiEndpoint::API_PORT_DEFAULT)
.to_socket_addrs()
Expand All @@ -181,7 +205,7 @@ impl ApiEndpoint {
let addr = address.parse().unwrap_or_else(|_| {
panic!(
"{api_addr}={address} is not a valid socketaddr",
api_addr = ApiEndpoint::API_ADDR_VAR,
api_addr = env::API_ADDR_VAR,
)
});
api.address = Some(addr);
Expand All @@ -193,9 +217,9 @@ impl ApiEndpoint {
if disable_tls_var.is_some() {
log::warn!(
"{disable_tls} is ignored since {api_host} and {api_addr} are not set",
disable_tls = ApiEndpoint::DISABLE_TLS_VAR,
api_host = ApiEndpoint::API_HOST_VAR,
api_addr = ApiEndpoint::API_ADDR_VAR,
disable_tls = env::DISABLE_TLS_VAR,
api_host = env::API_HOST_VAR,
api_addr = env::API_ADDR_VAR,
);
}
} else {
Expand Down Expand Up @@ -226,16 +250,17 @@ impl ApiEndpoint {
/// `MULLVAD_API_DISABLE_TLS` has invalid contents.
#[cfg(not(feature = "api-override"))]
pub fn from_env_vars() -> ApiEndpoint {
let host_var = Self::read_var(ApiEndpoint::API_HOST_VAR);
let address_var = Self::read_var(ApiEndpoint::API_ADDR_VAR);
let disable_tls_var = Self::read_var(ApiEndpoint::DISABLE_TLS_VAR);

if host_var.is_some() || address_var.is_some() || disable_tls_var.is_some() {
let env_vars = [
env::API_HOST_VAR,
env::API_ADDR_VAR,
env::DISABLE_TLS_VAR,
env::API_FORCE_DIRECT_VAR,
];

if env_vars.map(Self::read_var).iter().any(Option::is_some) {
log::warn!(
"These variables are ignored in production builds: {api_host}, {api_addr}, {disable_tls}",
api_host = ApiEndpoint::API_HOST_VAR,
api_addr = ApiEndpoint::API_ADDR_VAR,
disable_tls = ApiEndpoint::DISABLE_TLS_VAR
"These variables are ignored in production builds: {env_vars_pretty}",
env_vars_pretty = env_vars.join(", ")
);
}

Expand Down
3 changes: 2 additions & 1 deletion mullvad-daemon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ mullvad-api = { path = "../mullvad-api" }
mullvad-fs = { path = "../mullvad-fs" }
mullvad-version = { path = "../mullvad-version" }
talpid-core = { path = "../talpid-core" }
talpid-types = { path = "../talpid-types" }
talpid-future = { path = "../talpid-future" }
talpid-platform-metadata = { path = "../talpid-platform-metadata" }
talpid-time = { path = "../talpid-time" }
talpid-types = { path = "../talpid-types" }

[target.'cfg(not(target_os="android"))'.dependencies]
clap = { workspace = true }
Expand Down
9 changes: 3 additions & 6 deletions mullvad-daemon/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,7 @@ impl AccessModeSelector {
#[cfg(feature = "api-override")]
{
use mullvad_api::API;
// If the API address has been explicitly overridden, it should
// always be used. This implies that a direct API connection mode is
// used.
if API.address.is_some() {
if API.force_direct {
log::debug!("API proxies are disabled");
let endpoint = resolve_allowed_endpoint(
&ApiConnectionMode::Direct,
Expand All @@ -350,8 +347,8 @@ impl AccessModeSelector {
}

log::debug!(
"The `api-override` feature is enabled, but the API address \
was not overridden. Selecting API access methods as normal"
"The `api-override` feature is enabled, but a direct connection \
is not enforced. Selecting API access methods as normal"
);
}

Expand Down
2 changes: 1 addition & 1 deletion mullvad-daemon/src/device/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use mullvad_api::{
rest::{self, MullvadRestHandle},
AccountsProxy, DevicesProxy,
};
use talpid_core::future_retry::{retry_future, ConstantInterval, ExponentialBackoff, Jittered};
use talpid_future::retry::{retry_future, ConstantInterval, ExponentialBackoff, Jittered};
/// Retry strategy used for user-initiated actions that require immediate feedback
const RETRY_ACTION_STRATEGY: ConstantInterval = ConstantInterval::new(Duration::ZERO, Some(3));
/// Retry strategy used for background tasks
Expand Down
6 changes: 2 additions & 4 deletions mullvad-daemon/src/geoip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ use mullvad_api::{
};
use mullvad_types::location::{AmIMullvad, GeoIpLocation, LocationEventData};
use once_cell::sync::Lazy;
use talpid_core::{
future_retry::{retry_future, ExponentialBackoff, Jittered},
mpsc::Sender,
};
use talpid_core::mpsc::Sender;
use talpid_future::retry::{retry_future, ExponentialBackoff, Jittered};
use talpid_types::ErrorExt;

use crate::{DaemonEventSender, InternalDaemonEvent};
Expand Down
7 changes: 4 additions & 3 deletions mullvad-daemon/src/version_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use std::{
str::FromStr,
time::Duration,
};
use talpid_core::{future_retry::ConstantInterval, mpsc::Sender};
use talpid_core::mpsc::Sender;
use talpid_future::retry::{retry_future, ConstantInterval};
use talpid_types::ErrorExt;
use tokio::fs::{self, File};

Expand Down Expand Up @@ -193,7 +194,7 @@ impl VersionUpdater {
.map_err(Error::Download)
};

Box::pin(talpid_core::future_retry::retry_future(
Box::pin(retry_future(
download_future_factory,
move |result| Self::should_retry_immediate(result, &api_handle),
IMMEDIATE_RETRY_STRATEGY,
Expand Down Expand Up @@ -233,7 +234,7 @@ impl VersionUpdater {
}
};

Box::pin(talpid_core::future_retry::retry_future(
Box::pin(retry_future(
download_future_factory,
|result| result.is_err(),
std::iter::repeat(UPDATE_INTERVAL_ERROR),
Expand Down
2 changes: 1 addition & 1 deletion mullvad-relay-selector/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ rand = "0.8.5"
serde_json = "1.0"
tokio = { workspace = true, features = ["fs", "io-util", "time"] }

talpid-core = { path = "../talpid-core" }
talpid-future = { path = "../talpid-future" }
talpid-types = { path = "../talpid-types" }
mullvad-api = { path = "../mullvad-api" }
mullvad-types = { path = "../mullvad-types" }
Expand Down
2 changes: 1 addition & 1 deletion mullvad-relay-selector/src/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::{
sync::Arc,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use talpid_core::future_retry::{retry_future, ExponentialBackoff, Jittered};
use talpid_future::retry::{retry_future, ExponentialBackoff, Jittered};
use talpid_types::ErrorExt;
use tokio::fs::File;

Expand Down
1 change: 1 addition & 0 deletions mullvad-setup/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ mullvad-api = { path = "../mullvad-api" }
mullvad-types = { path = "../mullvad-types" }
mullvad-version = { path = "../mullvad-version" }
talpid-core = { path = "../talpid-core" }
talpid-future = { path = "../talpid-future" }
talpid-types = { path = "../talpid-types" }
11 changes: 5 additions & 6 deletions mullvad-setup/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use clap::Parser;
use once_cell::sync::Lazy;
use std::{path::PathBuf, process, str::FromStr, time::Duration};

use mullvad_api::{self, proxy::ApiConnectionMode, DEVICE_NOT_FOUND};
use mullvad_management_interface::MullvadProxyClient;
use mullvad_types::version::ParsedAppVersion;
use once_cell::sync::Lazy;
use std::{path::PathBuf, process, str::FromStr, time::Duration};
use talpid_core::{
firewall::{self, Firewall},
future_retry::{retry_future, ConstantInterval},
};
use talpid_core::firewall::{self, Firewall};
use talpid_future::retry::{retry_future, ConstantInterval};
use talpid_types::ErrorExt;

static APP_VERSION: Lazy<ParsedAppVersion> =
Expand Down
Loading
Loading