mod common;
use assert_fs::prelude::*;
use predicates::prelude::predicate::str::*;
use pretty_assertions::assert_eq;
use serde_yaml as sy;
use std::{fs::OpenOptions, io::Write};
use yage::EncryptionStatus;
use crate::common::*;
const YAML_CONTENT_ENCRYPTED_PATTERN: &str = r"foo: yage\[[0-9a-zA-Z/=\-+]+\|r:[a-z0-9,]+\]
titi:
toto: yage\[[0-9a-zA-Z/=\-+]+\|r:[a-z0-9,]+\]
array:
- yage\[[0-9a-zA-Z/=\-+]+\|r:[a-z0-9,]+\]
- yage\[[0-9a-zA-Z/=\-+]+\|r:[a-z0-9,]+\]
- yage\[[0-9a-zA-Z/=\-+]+\|r:[a-z0-9,]+\]
empty_map: \{\}
empty_array: \[\]
empty_string: yage\[[0-9a-zA-Z/=\-+]+\|r:[a-z0-9,]+\]
empty: null
";
#[test]
fn encrypt_to_stdout() {
let tmp = temp_dir();
let (key_path, pub_path) = create_key(&tmp);
let yaml_path = tmp.child("file.yaml");
write(&yaml_path, YAML_CONTENT);
let output = yage!("encrypt", "-R", &pub_path, &yaml_path)
.stdout(is_match(YAML_CONTENT_ENCRYPTED_PATTERN).unwrap())
.stderr(is_empty())
.get_output()
.clone();
let data: sy::Value = sy::from_str(YAML_CONTENT).unwrap();
let identities = yage::load_identities(&[], &[key_path]).unwrap();
let encrypted_data: sy::Value =
sy::from_str(&String::from_utf8(output.stdout).unwrap()).unwrap();
let decrypted_data = yage::decrypt_yaml(&encrypted_data, &identities).unwrap();
assert_eq!(data, decrypted_data);
}
#[test]
fn encrypt_to_file() {
let tmp = temp_dir();
let (key_path, pub_path) = create_key(&tmp);
let yaml_path = tmp.child("file.yaml");
write(&yaml_path, YAML_CONTENT);
let encrypted_path = tmp.child("file.enc.yaml");
yage!("encrypt", "-R", &pub_path, &yaml_path, "-o", &encrypted_path)
.stdout(is_empty())
.stderr(is_empty());
let data: sy::Value = sy::from_str(YAML_CONTENT).unwrap();
let identities = yage::load_identities(&[], &[key_path]).unwrap();
let encrypted_data: sy::Value = sy::from_str(&read(&encrypted_path)).unwrap();
let decrypted_data = yage::decrypt_yaml(&encrypted_data, &identities).unwrap();
assert_eq!(data, decrypted_data);
}
#[test]
fn encrypt_no_recipient() {
let tmp = temp_dir();
let yaml_path = tmp.child("file.yaml");
write(&yaml_path, YAML_CONTENT);
yage_cmd!("encrypt", &yaml_path)
.assert()
.failure()
.stdout(is_empty())
.stderr(contains("error: no recipients provided"));
}
#[test]
fn encrypt_multiple_recipients() {
let tmp = temp_dir();
let (key_path1, pub_path1) = create_key(&tmp);
let (key_path2, pub_path2) = create_key(&tmp);
let (key_path3, pub_path3) = create_key(&tmp);
let (key_path4, pub_path4) = create_key(&tmp);
let (key_path5, pub_path5) = create_key(&tmp);
let (key_path6, _) = create_key(&tmp);
let (key_path7, _) = create_key(&tmp);
let yaml_path = tmp.child("file.yaml");
write(&yaml_path, YAML_CONTENT);
let encrypted_path = tmp.child("file.enc.yaml");
yage_cmd!(
"encrypt",
"--recipient",
read(&pub_path1).trim(),
"--recipient-file",
&pub_path2,
"-r",
read(&pub_path3).trim(),
"-R",
"-",
&yaml_path,
"--output",
&encrypted_path
)
.env("YAGE_RECIPIENT", read(&key_path6).trim())
.env("YAGE_RECIPIENT_FILE", &key_path7)
.write_stdin(format!("{}{}", read(&pub_path4), read(&pub_path5)))
.assert()
.success()
.stdout(is_empty())
.stderr(is_empty());
let data: sy::Value = sy::from_str(YAML_CONTENT).unwrap();
let encrypted_data: sy::Value = sy::from_str(&read(&encrypted_path)).unwrap();
for key_path in [key_path1, key_path2, key_path3, key_path4, key_path5] {
let identities = yage::load_identities(&[], &[key_path]).unwrap();
let decrypted_data = yage::decrypt_yaml(&encrypted_data, &identities).unwrap();
assert_eq!(data, decrypted_data);
}
let identities = yage::load_identities(&[], &[key_path6]).unwrap();
assert!(yage::decrypt_yaml(&encrypted_data, &identities).is_err());
let identities = yage::load_identities(&[], &[key_path7]).unwrap();
assert!(yage::decrypt_yaml(&encrypted_data, &identities).is_err());
}
#[test]
fn encrypt_recipients_from_env() {
let tmp = temp_dir();
let (key_path1, pub_path1) = create_key(&tmp);
let (key_path2, pub_path2) = create_key(&tmp);
let (key_path3, pub_path3) = create_key(&tmp);
let (key_path4, pub_path4) = create_key(&tmp);
let yaml_path = tmp.child("file.yaml");
write(&yaml_path, YAML_CONTENT);
let encrypted_path = tmp.child("file.enc.yaml");
yage_cmd!("encrypt", &yaml_path, "--output", &encrypted_path)
.env("YAGE_RECIPIENT", format!("{},{}", read(&pub_path1).trim(), read(&pub_path2).trim()))
.env("YAGE_RECIPIENT_FILE", std::env::join_paths(vec![&pub_path3, &pub_path4]).unwrap())
.assert()
.success()
.stdout(is_empty())
.stderr(is_empty());
let data: sy::Value = sy::from_str(YAML_CONTENT).unwrap();
let encrypted_data: sy::Value = sy::from_str(&read(&encrypted_path)).unwrap();
for key_path in [key_path1, key_path2, key_path3, key_path4] {
let identities = yage::load_identities(&[], &[key_path]).unwrap();
let decrypted_data = yage::decrypt_yaml(&encrypted_data, &identities).unwrap();
assert_eq!(data, decrypted_data);
}
}
#[test]
fn encrypt_from_stdin() {
let tmp = temp_dir();
let (key_path, pub_path) = create_key(&tmp);
let encrypted_path = tmp.child("file.enc.yaml");
yage_cmd!("encrypt", "-R", &pub_path, "-", "--output", &encrypted_path)
.write_stdin(YAML_CONTENT)
.assert()
.success()
.stdout(is_empty())
.stderr(is_empty());
let data: sy::Value = sy::from_str(YAML_CONTENT).unwrap();
let identities = yage::load_identities(&[], &[key_path]).unwrap();
let encrypted_data: sy::Value = sy::from_str(&read(&encrypted_path)).unwrap();
let decrypted_data = yage::decrypt_yaml(&encrypted_data, &identities).unwrap();
assert_eq!(data, decrypted_data);
}
#[test]
fn encrypt_in_place() {
let tmp = temp_dir();
let (key_path, pub_path) = create_key(&tmp);
let yaml_path = tmp.child("file.yaml");
let other_path = tmp.child("other.yaml");
write(&yaml_path, YAML_CONTENT);
write(&other_path, YAML_CONTENT);
yage!("encrypt", "-R", &pub_path, "-i", &yaml_path, &other_path)
.stdout(is_empty())
.stderr(is_empty());
let data: sy::Value = sy::from_str(YAML_CONTENT).unwrap();
let identities = yage::load_identities(&[], &[key_path]).unwrap();
for path in [&yaml_path, &other_path] {
let encrypted_data: sy::Value = sy::from_str(&read(path)).unwrap();
let decrypted_data = yage::decrypt_yaml(&encrypted_data, &identities).unwrap();
assert_eq!(data, decrypted_data);
}
}
#[test]
fn encrypt_stdin_in_place() {
yage_cmd!("encrypt", "--in-place", "-")
.assert()
.failure()
.stdout(is_empty())
.stderr(contains("error: stdin can't be modified in place"));
}
#[test]
fn encrypt_multiple_files_no_in_place() {
yage_cmd!("encrypt", "foo.yaml", "bar.yaml")
.assert()
.failure()
.stdout(is_empty())
.stderr(contains("error: invalid number of input files"));
}
#[test]
fn encrypt_partially_encrypted() {
let tmp = temp_dir();
let (key_path, pub_path) = create_key(&tmp);
let yaml_path = tmp.child("file.yaml");
write(&yaml_path, YAML_CONTENT);
let encrypted_path = tmp.child("file.enc.yaml");
yage!("encrypt", "-R", &pub_path, &yaml_path, "-o", &encrypted_path)
.stdout(is_empty())
.stderr(is_empty());
let raw_encrypted_data = read(&encrypted_path);
let encrypted_data: sy::Value = sy::from_str(&raw_encrypted_data).unwrap();
assert_eq!(yage::check_encrypted(&encrypted_data), EncryptionStatus::Encrypted);
OpenOptions::new()
.append(true)
.open(&encrypted_path)
.unwrap()
.write_all(b"auie: tsrn\n")
.unwrap();
assert_eq!(
yage::check_encrypted(&sy::from_str(&read(&encrypted_path)).unwrap()),
EncryptionStatus::Mixed
);
let encrypted_path2 = tmp.child("file2.enc.yaml");
yage!("encrypt", "-R", &pub_path, &encrypted_path, "-o", &encrypted_path2)
.stdout(is_empty())
.stderr(is_empty());
assert!(read(&encrypted_path2).starts_with(&raw_encrypted_data));
let raw_encrypted_data2 = read(&encrypted_path2);
let encrypted_data2: sy::Value = sy::from_str(&raw_encrypted_data2).unwrap();
assert_eq!(yage::check_encrypted(&encrypted_data2), EncryptionStatus::Encrypted);
let identities = yage::load_identities(&[], &[key_path]).unwrap();
assert!(yage::decrypt_yaml(&encrypted_data2, &identities).is_ok());
}
#[test]
fn encrypt_partially_encrypted_other_recipient() {
let tmp = temp_dir();
let (_, pub_path1) = create_key(&tmp);
let yaml_path = tmp.child("file.yaml");
write(&yaml_path, YAML_CONTENT);
let encrypted_path = tmp.child("file.enc.yaml");
yage!("encrypt", "-R", &pub_path1, &yaml_path, "-o", &encrypted_path)
.stdout(is_empty())
.stderr(is_empty());
let raw_encrypted_data = read(&encrypted_path);
let encrypted_data: sy::Value = sy::from_str(&raw_encrypted_data).unwrap();
assert_eq!(yage::check_encrypted(&encrypted_data), EncryptionStatus::Encrypted);
OpenOptions::new()
.append(true)
.open(&encrypted_path)
.unwrap()
.write_all(b"auie: tsrn\n")
.unwrap();
assert_eq!(
yage::check_encrypted(&sy::from_str(&read(&encrypted_path)).unwrap()),
EncryptionStatus::Mixed
);
let (_, pub_path2) = create_key(&tmp);
yage_cmd!("encrypt", "-R", &pub_path2, &encrypted_path)
.assert()
.failure()
.stdout(is_empty())
.stderr(contains(
"error: the recipients form the command line don't match the recipients from the file",
));
}