mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
test(rust/gui-client/auth): manual test for auto-sign-in with invalid token (#6792)
Synthetic replication for #6791. The diff for the fix will probably be short, so I wanted this diff for the test to be reviewed separately. In your normal terminal: `cargo build -p firezone-gui-client -p gui-smoke-test` With sudo / admin powers: `./target/debug/gui-smoke-test.exe --manual-tests` Some customers _must_ have hit this, it's so easy to trigger. I can't add it to the CI smoke test because there's no portal in CI during the smoke test, unless we use Staging.
This commit is contained in:
1
rust/Cargo.lock
generated
1
rust/Cargo.lock
generated
@@ -3184,6 +3184,7 @@ name = "gui-smoke-test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"subprocess",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
|
||||
@@ -169,17 +169,22 @@ impl Auth {
|
||||
);
|
||||
let token = SecretString::from(token);
|
||||
|
||||
self.save_session(&resp.actor_name, &token)?;
|
||||
self.state = State::SignedIn(Session {
|
||||
actor_name: resp.actor_name,
|
||||
});
|
||||
Ok(SecretString::from(token))
|
||||
}
|
||||
|
||||
fn save_session(&self, actor_name: &str, token: &SecretString) -> Result<(), Error> {
|
||||
// This MUST be the only place the GUI can call `set_password`, since
|
||||
// the actor name is also saved here.
|
||||
self.token_store.set_password(token.expose_secret())?;
|
||||
let path = actor_name_path()?;
|
||||
std::fs::create_dir_all(path.parent().ok_or(Error::ActorNamePathWrong)?)
|
||||
.map_err(Error::CreateDirAll)?;
|
||||
std::fs::write(path, resp.actor_name.as_bytes()).map_err(Error::WriteActorName)?;
|
||||
self.state = State::SignedIn(Session {
|
||||
actor_name: resp.actor_name,
|
||||
});
|
||||
Ok(SecretString::from(token))
|
||||
std::fs::write(path, actor_name.as_bytes()).map_err(Error::WriteActorName)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the token if we are signed in
|
||||
@@ -259,6 +264,16 @@ fn secure_equality(a: &SecretString, b: &SecretString) -> bool {
|
||||
a.ct_eq(b).into()
|
||||
}
|
||||
|
||||
pub fn replicate_6791() -> Result<()> {
|
||||
tracing::warn!("Debugging issue #6791, pretending to be signed in with a bad token");
|
||||
let this = Auth::new()?;
|
||||
this.save_session(
|
||||
"Jane Doe",
|
||||
&SecretString::from("obviously invalid token for testing #6791".to_string()),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -158,6 +158,10 @@ struct Cli {
|
||||
#[arg(long, hide = true)]
|
||||
panic: bool,
|
||||
|
||||
/// Quit gracefully after a given number of seconds
|
||||
#[arg(long, hide = true)]
|
||||
quit_after: Option<u64>,
|
||||
|
||||
/// If true, slow down I/O operations to test how the GUI handles slow I/O
|
||||
#[arg(long, hide = true)]
|
||||
inject_faults: bool,
|
||||
|
||||
@@ -5,6 +5,7 @@ use anyhow::Result;
|
||||
|
||||
#[derive(clap::Subcommand)]
|
||||
pub(crate) enum Cmd {
|
||||
Replicate6791,
|
||||
SetAutostart(SetAutostartArgs),
|
||||
}
|
||||
|
||||
@@ -26,6 +27,7 @@ pub(crate) struct StoreTokenArgs {
|
||||
|
||||
pub fn run(cmd: Cmd) -> Result<()> {
|
||||
match cmd {
|
||||
Cmd::Replicate6791 => firezone_gui_client_common::auth::replicate_6791(),
|
||||
Cmd::SetAutostart(SetAutostartArgs { enabled }) => set_autostart(enabled),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,16 +223,27 @@ pub(crate) fn run(
|
||||
let ctlr_tx = ctlr_tx.clone();
|
||||
tokio::spawn(async move {
|
||||
let delay = 5;
|
||||
tracing::info!(
|
||||
tracing::warn!(
|
||||
"Will crash / error / panic on purpose in {delay} seconds to test error handling."
|
||||
);
|
||||
tokio::time::sleep(Duration::from_secs(delay)).await;
|
||||
tracing::info!("Crashing / erroring / panicking on purpose");
|
||||
tracing::warn!("Crashing / erroring / panicking on purpose");
|
||||
ctlr_tx.send(ControllerRequest::Fail(failure)).await?;
|
||||
Ok::<_, anyhow::Error>(())
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(delay) = cli.quit_after {
|
||||
let ctlr_tx = ctlr_tx.clone();
|
||||
tokio::spawn(async move {
|
||||
tracing::warn!("Will quit gracefully in {delay} seconds.");
|
||||
tokio::time::sleep(Duration::from_secs(delay)).await;
|
||||
tracing::warn!("Quitting gracefully due to `--quit-after`");
|
||||
ctlr_tx.send(ControllerRequest::SystemTrayMenu(firezone_gui_client_common::system_tray::Event::Quit)).await?;
|
||||
Ok::<_, anyhow::Error>(())
|
||||
});
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
firezone_bin_shared::BUNDLE_ID,
|
||||
app.handle().config().tauri.bundle.identifier,
|
||||
|
||||
@@ -35,7 +35,7 @@ mod platform;
|
||||
use platform::default_token_path;
|
||||
|
||||
/// Command-line args for the headless Client
|
||||
#[derive(clap::Parser)]
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Cli {
|
||||
// Needed to preserve CLI arg compatibility
|
||||
|
||||
@@ -5,6 +5,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0" }
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
subprocess = "0.2.9"
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Starts up the IPC service and GUI app and lets them run for a bit
|
||||
|
||||
use anyhow::{bail, Context as _, Result};
|
||||
use clap::Parser;
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
path::{Path, PathBuf},
|
||||
@@ -21,8 +22,19 @@ const EXE_EXTENSION: &str = "";
|
||||
#[cfg(target_os = "windows")]
|
||||
const EXE_EXTENSION: &str = "exe";
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Cli {
|
||||
/// Run tests that can't run in CI, like tests that need access to the staging network.
|
||||
#[arg(long)]
|
||||
manual_tests: bool,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
tracing_subscriber::fmt::init();
|
||||
tracing::info!("Started logging");
|
||||
let cli = Cli::try_parse()?;
|
||||
|
||||
let app = App::new()?;
|
||||
|
||||
dump_syms()?;
|
||||
@@ -46,6 +58,26 @@ fn main() -> Result<()> {
|
||||
|
||||
app.check_crash_dump()?;
|
||||
|
||||
if cli.manual_tests {
|
||||
manual_tests(&app)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn manual_tests(app: &App) -> Result<()> {
|
||||
// Replicate #6791
|
||||
app.gui_command(&["debug", "replicate6791"])?
|
||||
.popen()?
|
||||
.wait()?;
|
||||
|
||||
let mut ipc_service = ipc_service_command().arg("run-smoke-test").popen()?;
|
||||
let mut gui = app.gui_command(&["--quit-after", "10"])?.popen()?;
|
||||
|
||||
// Expect exit codes of 0
|
||||
gui.wait()?.fz_exit_ok().context("GUI process")?;
|
||||
ipc_service.wait()?.fz_exit_ok().context("IPC service")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user