use ed25519_dalek::pkcs8::EncodePrivateKey;
use nethsm::NamespaceId;
use nethsm::PrivateKeyImport;
use nethsm::UserId;
use nethsm::test::ADMIN_USER_ID;
use nethsm::test::DEFAULT_AES_BITS;
use nethsm::test::DEFAULT_OPERATOR_USER_ID;
use nethsm::test::DEFAULT_RSA_BITS;
use nethsm::test::NAMESPACE1;
use nethsm::test::NAMESPACE1_ADMIN_USER_ID;
use nethsm::test::NAMESPACE1_OPERATOR_USER_ID;
use nethsm::test::NAMESPACE2_ADMIN_USER_ID;
use nethsm::test::NAMESPACE2_OPERATOR_USER_ID;
use nethsm::test::NetHsmImage;
use nethsm::test::nethsm_with_users;
use nethsm::{KeyMechanism, KeyType, NetHsm};
use rstest::{fixture, rstest};
use rustainers::Container;
use testresult::TestResult;
#[rstest]
#[case(KeyType::Curve25519, vec![KeyMechanism::EdDsaSignature], None)]
#[case(KeyType::EcP256, vec![KeyMechanism::EcdsaSignature], None)]
#[case(KeyType::EcP384, vec![KeyMechanism::EcdsaSignature], None)]
#[case(KeyType::EcP521, vec![KeyMechanism::EcdsaSignature], None)]
#[case(KeyType::Generic, vec![KeyMechanism::AesDecryptionCbc, KeyMechanism::AesEncryptionCbc], Some(DEFAULT_AES_BITS))]
#[case(KeyType::Rsa, vec![KeyMechanism::RsaSignaturePssSha512], Some(DEFAULT_RSA_BITS))]
#[tokio::test]
async fn generate_keys(
#[case] key_type: KeyType,
#[case] mechanisms: Vec<KeyMechanism>,
#[case] length: Option<u32>,
#[future] nethsm_with_users: TestResult<(NetHsm, Container<NetHsmImage>)>,
) -> TestResult {
let (nethsm, _container) = nethsm_with_users.await?;
let sw_tag = "sw".to_string();
let ns1_tag = "ns1".to_string();
let ns2_tag = "ns2".to_string();
let admin_user_id: UserId = ADMIN_USER_ID.parse()?;
let default_operator_user_id: UserId = DEFAULT_OPERATOR_USER_ID.parse()?;
let namespace1: NamespaceId = NAMESPACE1.parse()?;
let namespace1_admin_user_id: UserId = NAMESPACE1_ADMIN_USER_ID.parse()?;
let namespace1_operator_user_id: UserId = NAMESPACE1_OPERATOR_USER_ID.parse()?;
let namespace2_admin_user_id: UserId = NAMESPACE2_ADMIN_USER_ID.parse()?;
let namespace2_operator_user_id: UserId = NAMESPACE2_OPERATOR_USER_ID.parse()?;
let _free_key = nethsm.generate_key(key_type, mechanisms.clone(), length, None, None)?;
let sw_key = nethsm.generate_key(
key_type,
mechanisms.clone(),
length,
None,
Some(vec![sw_tag.clone()]),
)?;
println!("Created system-wide key: {}", &sw_key);
nethsm.add_user_tag(&default_operator_user_id, &sw_tag)?;
println!(
"system-wide operator tags: {:?}",
nethsm.get_user_tags(&default_operator_user_id)?
);
nethsm.use_credentials(&namespace1_admin_user_id)?;
let ns1_key = nethsm.generate_key(
key_type,
mechanisms.clone(),
length,
None,
Some(vec![ns1_tag.clone()]),
)?;
println!("Created namespace1 key: {}", &ns1_key);
nethsm.use_credentials(&namespace1_operator_user_id)?;
println!(
"{} key accessed by {} before tagging: {:?}",
&ns1_key,
&namespace1_operator_user_id,
nethsm.get_key(&ns1_key)?
);
if key_type != KeyType::Generic {
let public_key = nethsm.get_public_key(&ns1_key)?;
println!(
"{} public key retrieved by {}, before tagging: {:?}",
&ns1_key, &namespace1_operator_user_id, &public_key
);
nethsm.use_credentials(&namespace1_admin_user_id)?;
nethsm.import_key_certificate(&ns1_key, public_key.clone().into_bytes())?;
nethsm.use_credentials(&namespace1_operator_user_id)?;
let key_cert = nethsm
.get_key_certificate(&ns1_key)?
.expect("Certificate to be imported");
assert_eq!(key_cert, public_key.into_bytes());
}
nethsm.use_credentials(&namespace1_admin_user_id)?;
nethsm.add_user_tag(&namespace1_operator_user_id, &ns1_tag)?;
println!(
"namespace1 operator tags: {:?}",
nethsm.get_user_tags(&namespace1_operator_user_id)?
);
nethsm.use_credentials(&namespace2_admin_user_id)?;
let ns2_key = nethsm.generate_key(
key_type,
mechanisms.clone(),
length,
None,
Some(vec![ns2_tag.clone()]),
)?;
println!("Created namespace2 key: {}", &ns2_key);
nethsm.add_user_tag(&namespace2_operator_user_id, &ns2_tag)?;
println!(
"namespace2 operator tags: {:?}",
nethsm.get_user_tags(&namespace2_operator_user_id)?
);
nethsm.use_credentials(&default_operator_user_id)?;
assert_eq!(nethsm.get_keys(None)?.len(), 2);
println!("system-wide keys: {:?}", nethsm.get_keys(None)?);
assert!(nethsm.get_key(&sw_key).is_ok());
println!("system-wide key: {:?}", nethsm.get_key(&sw_key)?);
nethsm.use_credentials(&namespace1_operator_user_id)?;
assert_eq!(nethsm.get_keys(None)?.len(), 1);
println!("namespace1 keys: {:?}", nethsm.get_keys(None)?);
assert!(nethsm.get_key(&ns1_key).is_ok());
println!("namespace1 key: {:?}", nethsm.get_key(&ns1_key)?);
nethsm.use_credentials(&namespace2_operator_user_id)?;
assert_eq!(nethsm.get_keys(None)?.len(), 1);
println!("namespace2 keys: {:?}", nethsm.get_keys(None)?);
assert!(nethsm.get_key(&ns2_key).is_ok());
println!("namespace2 key: {:?}", nethsm.get_key(&ns2_key)?);
nethsm.use_credentials(&admin_user_id)?;
assert!(
nethsm
.add_user_tag(&namespace1_operator_user_id, "test")
.is_err()
);
assert!(
nethsm
.delete_user_tag(&namespace1_operator_user_id, &ns1_tag)
.is_err()
);
assert!(
nethsm
.add_user_tag(&namespace2_operator_user_id, "test")
.is_err()
);
assert!(
nethsm
.delete_user_tag(&namespace2_operator_user_id, &ns2_tag)
.is_err()
);
println!(
"namespace1 operator tags: {:?}",
nethsm.get_user_tags(&namespace1_operator_user_id)?
);
println!(
"namespace2 operator tags: {:?}",
nethsm.get_user_tags(&namespace2_operator_user_id)?
);
nethsm.delete_namespace(&namespace1)?;
println!("all users: {:?}", nethsm.get_users()?);
println!(
"namespace1 operator: {:?}",
nethsm.get_user(&namespace1_operator_user_id)?
);
println!(
"namespace1 operator tags: {:?}",
nethsm.get_user_tags(&namespace1_operator_user_id)?
);
nethsm.use_credentials(&namespace1_operator_user_id)?;
assert!(nethsm.get_keys(None).is_err());
assert!(nethsm.get_key(&ns1_key).is_err());
nethsm.use_credentials(&namespace1_admin_user_id)?;
assert!(nethsm.get_keys(None).is_err());
assert!(nethsm.get_key(&ns1_key).is_err());
Ok(())
}
#[fixture]
fn ed25519_key() -> TestResult<PrivateKeyImport> {
let private_key = ed25519_dalek::SigningKey::generate(&mut rand::rngs::OsRng);
Ok(PrivateKeyImport::new(
KeyType::Curve25519,
private_key.to_pkcs8_der()?.as_bytes(),
)?)
}
#[fixture]
fn ecp256_key() -> TestResult<PrivateKeyImport> {
let private_key = p256::SecretKey::random(&mut rand::rngs::OsRng);
Ok(PrivateKeyImport::new(
KeyType::EcP256,
private_key.to_pkcs8_der()?.as_bytes(),
)?)
}
#[fixture]
fn ecp384_key() -> TestResult<PrivateKeyImport> {
let private_key = p384::SecretKey::random(&mut rand::rngs::OsRng);
Ok(PrivateKeyImport::new(
KeyType::EcP384,
private_key.to_pkcs8_der()?.as_bytes(),
)?)
}
#[fixture]
fn ecp521_key() -> TestResult<PrivateKeyImport> {
let private_key = p521::SecretKey::random(&mut rand::rngs::OsRng);
Ok(PrivateKeyImport::new(
KeyType::EcP521,
private_key.to_pkcs8_der()?.as_bytes(),
)?)
}
#[fixture]
fn rsa_key() -> TestResult<PrivateKeyImport> {
let private_key =
rsa::RsaPrivateKey::new(&mut rand::rngs::OsRng, DEFAULT_RSA_BITS.try_into()?)?;
Ok(PrivateKeyImport::new(
KeyType::Rsa,
private_key.to_pkcs8_der()?.as_bytes(),
)?)
}
#[rstest]
#[tokio::test]
async fn import_keys(
#[future] nethsm_with_users: TestResult<(NetHsm, Container<NetHsmImage>)>,
ed25519_key: TestResult<PrivateKeyImport>,
ecp256_key: TestResult<PrivateKeyImport>,
ecp384_key: TestResult<PrivateKeyImport>,
ecp521_key: TestResult<PrivateKeyImport>,
rsa_key: TestResult<PrivateKeyImport>,
) -> TestResult {
let (nethsm, _container) = nethsm_with_users.await?;
let ed25519_key = ed25519_key?;
let ecp256_key = ecp256_key?;
let ecp384_key = ecp384_key?;
let ecp521_key = ecp521_key?;
let rsa_key = rsa_key?;
assert_eq!(nethsm.get_keys(None)?.len(), 0);
nethsm.import_key(
KeyMechanism::curve25519_mechanisms(),
ed25519_key,
None,
None,
)?;
assert_eq!(nethsm.get_keys(None)?.len(), 1);
nethsm.import_key(
KeyMechanism::elliptic_curve_mechanisms(),
ecp256_key,
None,
None,
)?;
assert_eq!(nethsm.get_keys(None)?.len(), 2);
nethsm.import_key(
KeyMechanism::elliptic_curve_mechanisms(),
ecp384_key,
None,
None,
)?;
assert_eq!(nethsm.get_keys(None)?.len(), 3);
nethsm.import_key(
KeyMechanism::elliptic_curve_mechanisms(),
ecp521_key,
None,
None,
)?;
assert_eq!(nethsm.get_keys(None)?.len(), 4);
nethsm.import_key(KeyMechanism::rsa_mechanisms(), rsa_key, None, None)?;
assert_eq!(nethsm.get_keys(None)?.len(), 5);
Ok(())
}