Skip to content

Commit

Permalink
Add integration tests that require a live YubiKey slot
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Feb 11, 2023
1 parent 3408998 commit 355ce1c
Showing 1 changed file with 93 additions and 0 deletions.
93 changes: 93 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,36 @@ use std::process::{Command, Stdio};

const PLUGIN_BIN: &str = env!("CARGO_BIN_EXE_age-plugin-yubikey");

#[test_with::env(YUBIKEY_SERIAL, YUBIKEY_SLOT)]
#[cfg_attr(all(unix, not(target_os = "macos")), test_with::executable(pcscd))]
#[test]
fn recipient_and_identity_match() {
let recipient = Command::new(PLUGIN_BIN)
.arg("--list")
.arg("--serial")
.arg(env::var("YUBIKEY_SERIAL").unwrap())
.arg("--slot")
.arg(env::var("YUBIKEY_SLOT").unwrap())
.output()
.unwrap();
assert_eq!(recipient.status.code(), Some(0));

let identity = Command::new(PLUGIN_BIN)
.arg("--identity")
.arg("--serial")
.arg(env::var("YUBIKEY_SERIAL").unwrap())
.arg("--slot")
.arg(env::var("YUBIKEY_SLOT").unwrap())
.output()
.unwrap();
assert_eq!(identity.status.code(), Some(0));

let recipient_file = String::from_utf8_lossy(&recipient.stdout);
let recipient = recipient_file.lines().last().unwrap();
let identity = String::from_utf8_lossy(&identity.stdout);
assert!(identity.contains(recipient));
}

#[test_with::executable(rage)]
#[test]
fn plugin_encrypt() {
Expand All @@ -30,3 +60,66 @@ fn plugin_encrypt() {
let status = process.wait().unwrap();
assert_eq!(status.code(), Some(0));
}

#[test_with::env(YUBIKEY_SERIAL, YUBIKEY_SLOT)]
#[test_with::executable(rage)]
#[cfg_attr(all(unix, not(target_os = "macos")), test_with::executable(pcscd))]
#[test]
fn plugin_decrypt() {
let mut identity_file = tempfile::NamedTempFile::new_in(env!("CARGO_TARGET_TMPDIR")).unwrap();
let enc_file = tempfile::NamedTempFile::new_in(env!("CARGO_TARGET_TMPDIR")).unwrap();
let plaintext = "Testing YubiKey encryption";

// Write an identity file corresponding to this YubiKey slot.
let identity = Command::new(PLUGIN_BIN)
.arg("--identity")
.arg("--serial")
.arg(env::var("YUBIKEY_SERIAL").unwrap())
.arg("--slot")
.arg(env::var("YUBIKEY_SLOT").unwrap())
.output()
.unwrap();
assert_eq!(identity.status.code(), Some(0));
identity_file.write_all(&identity.stdout).unwrap();
identity_file.flush().unwrap();

// Encrypt to the YubiKey slot.
let mut enc_process = Command::new(which::which("rage").unwrap())
.arg("-e")
.arg("-i")
.arg(identity_file.path())
.arg("-o")
.arg(enc_file.path())
.stdin(Stdio::piped())
.env("PATH", Path::new(PLUGIN_BIN).parent().unwrap())
.spawn()
.unwrap();

// Scope to ensure stdin is closed.
{
let mut stdin = enc_process.stdin.take().unwrap();
stdin.write_all(plaintext.as_bytes()).unwrap();
stdin.flush().unwrap();
}

let enc_status = enc_process.wait().unwrap();
assert_eq!(enc_status.code(), Some(0));

// Decrypt with the YubiKey.
let dec_process = Command::new(which::which("rage").unwrap())
.arg("-d")
.arg("-i")
.arg(identity_file.path())
.arg(enc_file.path())
.stdin(Stdio::piped())
.env("PATH", Path::new(PLUGIN_BIN).parent().unwrap())
.output()
.unwrap();

let stderr = String::from_utf8_lossy(&dec_process.stderr);
if !stderr.is_empty() {
assert!(stderr.contains("age-plugin-yubikey"));
assert!(stderr.ends_with("...\n"));
}
assert_eq!(String::from_utf8_lossy(&dec_process.stdout), plaintext);
}

0 comments on commit 355ce1c

Please sign in to comment.