use std::path::PathBuf;
use cosmian_logger::log_init;
use tempfile::TempDir;
use test_kms_server::start_default_test_kms_server;
use crate::{
actions::kms::{
cover_crypt::{
access_structure::{
AddQualifiedAttributeAction, DisableAttributeAction, RemoveAttributeAction,
RenameAttributeAction, ViewAction,
},
decrypt::DecryptAction,
encrypt::EncryptAction,
keys::{
create_key_pair::CreateMasterKeyPairAction, create_user_key::CreateUserKeyAction,
},
},
shared::ExportSecretDataOrKeyAction,
},
error::result::KmsCliResult,
};
#[tokio::test]
async fn test_view_access_structure() -> KmsCliResult<()> {
log_init(option_env!("RUST_LOG"));
let ctx = start_default_test_kms_server().await;
let (_master_secret_key_id, master_public_key_id) = Box::pin(
CreateMasterKeyPairAction {
specification: PathBuf::from("../../test_data/access_structure_specifications.json"),
tags: vec![],
sensitive: false,
wrapping_key_id: None,
}
.run(ctx.get_owner_client()),
)
.await?;
let tmp_dir = TempDir::new()?;
let tmp_path = tmp_dir.path();
let public_key_path = tmp_path.join("public_key.json");
ExportSecretDataOrKeyAction {
key_id: Some(master_public_key_id.to_string()),
key_file: format!("{}", public_key_path.display()).into(),
..Default::default()
}
.run(ctx.get_owner_client())
.await?;
let view_access_structure = ViewAction {
key_id: None,
key_file: Some(format!("{}", public_key_path.display()).into()),
}
.run(ctx.get_owner_client())
.await?;
let output = format!("{view_access_structure:?}");
assert!(output.contains("Security Level"));
assert!(output.contains("Top Secret"));
assert!(output.contains("RnD"));
assert!(output.contains(
"Attribute { id: 6, security_mode: Classic, encryption_status: EncryptDecrypt }"
));
Ok(())
}
#[tokio::test]
async fn test_edit_access_structure() -> KmsCliResult<()> {
log_init(None);
let ctx = start_default_test_kms_server().await;
let tmp_dir = TempDir::new()?;
let tmp_path = tmp_dir.path();
let input_file = PathBuf::from("../../test_data/plain.txt");
let cipher_file = tmp_path.join("cipher.enc");
let new_cipher_file = tmp_path.join("cipher.new.enc");
let recovered_file = tmp_path.join("plain.txt");
let (master_secret_key_id, master_public_key_id) = Box::pin(
CreateMasterKeyPairAction {
specification: PathBuf::from("../../test_data/access_structure_specifications.json"),
tags: vec![],
sensitive: false,
wrapping_key_id: None,
}
.run(ctx.get_owner_client()),
)
.await?;
let user_decryption_key = CreateUserKeyAction {
master_secret_key_id: master_secret_key_id.to_string(),
access_policy: "(Department::MKG || Department::FIN) && Security Level::Top Secret"
.to_owned(),
tags: vec![],
sensitive: false,
wrapping_key_id: None,
}
.run(ctx.get_owner_client())
.await?;
EncryptAction {
input_files: vec![input_file.clone()],
encryption_policy: "Department::MKG && Security Level::Confidential".to_owned(),
key_id: Some(master_public_key_id.to_string()),
tags: None,
output_file: Some(cipher_file.clone()),
authentication_data: Some("myid".to_owned()),
}
.run(ctx.get_owner_client())
.await?;
DecryptAction {
input_files: vec![cipher_file.clone()],
key_id: Some(user_decryption_key.to_string()),
tags: None,
output_file: Some(recovered_file.clone()),
authentication_data: Some("myid".to_owned()),
}
.run(ctx.get_owner_client())
.await?;
RenameAttributeAction {
attribute: "Department::MKG".to_owned(),
new_name: "Marketing".to_owned(),
master_secret_key_id: Some(master_secret_key_id.to_string()),
tags: None,
}
.run(ctx.get_owner_client())
.await?;
DecryptAction {
input_files: vec![cipher_file.clone()],
key_id: Some(user_decryption_key.to_string()),
tags: None,
output_file: Some(recovered_file.clone()),
authentication_data: Some("myid".to_owned()),
}
.run(ctx.get_owner_client())
.await?;
AddQualifiedAttributeAction {
attribute: "Department::Sales".to_owned(),
hybridized: false,
secret_key_id: Some(master_secret_key_id.to_string()),
tags: None,
}
.run(ctx.get_owner_client())
.await?;
EncryptAction {
input_files: vec![input_file.clone()],
encryption_policy: "Department::Sales && Security Level::Confidential".to_owned(),
key_id: Some(master_public_key_id.to_string()),
tags: None,
output_file: Some(new_cipher_file.clone()),
authentication_data: Some("myid".to_owned()),
}
.run(ctx.get_owner_client())
.await?;
let sales_mkg_user_decryption_key = CreateUserKeyAction {
master_secret_key_id: master_secret_key_id.to_string(),
access_policy: "(Department::Sales || Department::Marketing) && Security \
Level::Confidential"
.to_owned(),
tags: vec![],
sensitive: false,
wrapping_key_id: None,
}
.run(ctx.get_owner_client())
.await?;
DecryptAction {
input_files: vec![new_cipher_file.clone()],
key_id: Some(user_decryption_key.to_string()),
tags: None,
output_file: Some(recovered_file.clone()),
authentication_data: Some("myid".to_owned()),
}
.run(ctx.get_owner_client())
.await
.unwrap_err();
DecryptAction {
input_files: vec![new_cipher_file.clone()],
key_id: Some(sales_mkg_user_decryption_key.to_string()),
tags: None,
output_file: Some(recovered_file.clone()),
authentication_data: Some("myid".to_owned()),
}
.run(ctx.get_owner_client())
.await?;
DisableAttributeAction {
attribute: "Department::Sales".to_owned(),
master_secret_key_id: Some(master_secret_key_id.to_string()),
tags: None,
}
.run(ctx.get_owner_client())
.await?;
EncryptAction {
input_files: vec![input_file],
encryption_policy: "Department::Sales && Security Level::Confidential".to_owned(),
key_id: Some(master_public_key_id.to_string()),
tags: None,
output_file: None,
authentication_data: None,
}
.run(ctx.get_owner_client())
.await
.unwrap_err();
DecryptAction {
input_files: vec![new_cipher_file.clone()],
key_id: Some(sales_mkg_user_decryption_key.to_string()),
tags: None,
output_file: Some(recovered_file.clone()),
authentication_data: Some("myid".to_owned()),
}
.run(ctx.get_owner_client())
.await?;
RemoveAttributeAction {
attribute: "Department::Sales".to_owned(),
master_secret_key_id: Some(master_secret_key_id.to_string()),
tags: None,
}
.run(ctx.get_owner_client())
.await?;
DecryptAction {
input_files: vec![new_cipher_file],
key_id: Some(sales_mkg_user_decryption_key.to_string()),
tags: None,
output_file: Some(recovered_file.clone()),
authentication_data: Some("myid".to_owned()),
}
.run(ctx.get_owner_client())
.await
.unwrap_err();
Ok(())
}