use assert_cmd::Command;
use predicates::str::contains;
use tempfile::tempdir;
fn tsafe() -> Command {
Command::cargo_bin("tsafe").unwrap()
}
fn test_profile(name: &str) -> String {
format!("rotate-key-{name}-{}", std::process::id())
}
#[test]
fn rotate_key_changes_password_and_unlocks_with_new() {
let dir = tempdir().unwrap();
let profile = test_profile("changes-password");
tsafe()
.args(["--profile", profile.as_str(), "init"])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "old-master-pw")
.assert()
.success();
tsafe()
.args([
"--profile",
profile.as_str(),
"set",
"REKEY_SECRET",
"rekey-value",
])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "old-master-pw")
.assert()
.success();
tsafe()
.args(["--profile", profile.as_str(), "rotate-key"])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "old-master-pw")
.env("TSAFE_NEW_MASTER_PASSWORD", "new-master-pw")
.assert()
.success()
.stdout(contains("re-encrypted successfully"));
tsafe()
.args(["--profile", profile.as_str(), "get", "REKEY_SECRET"])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "old-master-pw")
.assert()
.failure()
.stderr(contains("wrong password"));
tsafe()
.args(["--profile", profile.as_str(), "get", "REKEY_SECRET"])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "new-master-pw")
.assert()
.success()
.stdout("rekey-value");
}
#[test]
fn rotate_key_rejects_empty_new_password() {
let dir = tempdir().unwrap();
let profile = test_profile("empty-new-password");
tsafe()
.args(["--profile", profile.as_str(), "init"])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "pw")
.assert()
.success();
tsafe()
.args(["--profile", profile.as_str(), "rotate-key"])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "pw")
.env("TSAFE_NEW_MASTER_PASSWORD", "")
.assert()
.failure()
.stderr(contains("empty"));
}
#[test]
fn rotate_key_preserves_all_secrets() {
let dir = tempdir().unwrap();
let profile = test_profile("preserves-secrets");
tsafe()
.args(["--profile", profile.as_str(), "init"])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "before")
.assert()
.success();
for (k, v) in [("ALPHA", "a"), ("BETA", "b"), ("GAMMA", "c")] {
tsafe()
.args(["--profile", profile.as_str(), "set", k, v])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "before")
.assert()
.success();
}
tsafe()
.args(["--profile", profile.as_str(), "rotate-key"])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "before")
.env("TSAFE_NEW_MASTER_PASSWORD", "after")
.assert()
.success();
for (k, v) in [("ALPHA", "a"), ("BETA", "b"), ("GAMMA", "c")] {
let out = tsafe()
.args(["--profile", profile.as_str(), "get", k])
.env("TSAFE_VAULT_DIR", dir.path())
.env("TSAFE_PASSWORD", "after")
.assert()
.success()
.get_output()
.stdout
.clone();
assert_eq!(
String::from_utf8(out).unwrap().trim(),
v,
"key {k} should survive rotate-key"
);
}
}