use clap::Parser;
use cosmian_kms_client::{
KmsClient,
kmip_2_1::{
kmip_attributes::Attributes,
kmip_types::UniqueIdentifier,
requests::{
create_symmetric_key_kmip_object, import_object_request, symmetric_key_create_request,
},
},
reexport::cosmian_kms_client_utils::create_utils::{
SymmetricAlgorithm, prepare_sym_key_elements,
},
};
use crate::{
actions::kms::console,
error::result::{KmsCliResult, KmsCliResultHelper},
};
#[derive(Parser, Default)]
#[clap(verbatim_doc_comment)]
pub struct CreateKeyAction {
#[clap(
long = "number-of-bits",
short = 'l',
group = "key",
default_value = "256"
)]
pub number_of_bits: Option<usize>,
#[clap(long = "bytes-b64", short = 'k', required = false, group = "key")]
pub wrap_key_b64: Option<String>,
#[clap(
long = "algorithm",
short = 'a',
required = false,
default_value = "aes"
)]
pub algorithm: SymmetricAlgorithm,
#[clap(long = "tag", short = 't', value_name = "TAG")]
pub tags: Vec<String>,
#[clap(required = false)]
pub key_id: Option<String>,
#[clap(long = "sensitive", default_value = "false")]
pub sensitive: bool,
#[clap(
long = "wrapping-key-id",
short = 'w',
required = false,
verbatim_doc_comment
)]
pub wrapping_key_id: Option<String>,
}
impl CreateKeyAction {
pub async fn run(&self, kms_rest_client: KmsClient) -> KmsCliResult<UniqueIdentifier> {
let (number_of_bits, key_bytes, algorithm) =
prepare_sym_key_elements(self.number_of_bits, &self.wrap_key_b64, self.algorithm)
.with_context(|| "failed preparing key elements")?;
let vendor_id = kms_rest_client.config.vendor_id.as_str();
let unique_identifier = if let Some(key_bytes) = key_bytes {
let mut object = create_symmetric_key_kmip_object(
vendor_id,
key_bytes.as_slice(),
&Attributes {
cryptographic_algorithm: Some(algorithm),
..Default::default()
},
)?;
if let Some(wrapping_key_id) = &self.wrapping_key_id {
let attributes = object.attributes_mut()?;
attributes.set_wrapping_key_id(vendor_id, wrapping_key_id);
}
let import_object_request = import_object_request(
vendor_id,
self.key_id.clone(),
object,
None,
false,
false,
&self.tags,
)?;
kms_rest_client
.import(import_object_request)
.await
.with_context(|| "failed importing the key")?
.unique_identifier
} else {
let key_id = self
.key_id
.as_ref()
.map(|id| UniqueIdentifier::TextString(id.clone()));
let create_key_request = symmetric_key_create_request(
vendor_id,
key_id,
number_of_bits,
algorithm,
&self.tags,
self.sensitive,
self.wrapping_key_id.as_ref(),
)?;
kms_rest_client
.create(create_key_request)
.await
.with_context(|| "failed creating the key")?
.unique_identifier
};
let mut stdout = console::Stdout::new("The symmetric key was successfully generated.");
stdout.set_tags(Some(&self.tags));
stdout.set_unique_identifier(&unique_identifier);
stdout.write()?;
Ok(unique_identifier)
}
}