use clap::Parser;
use cosmian_kms_client::{
KmsClient,
cosmian_kmip::kmip_2_1::kmip_types::UniqueIdentifier,
kmip_2_1::KmipOperation,
reexport::cosmian_kms_access::access::{
Access, AccessRightsObtainedResponse, ObjectOwnedResponse, UserAccessResponse,
},
};
use crate::{
actions::kms::console,
error::result::{KmsCliResult, KmsCliResultHelper},
};
#[derive(Parser, Debug)]
pub enum AccessAction {
Grant(GrantAccess),
Revoke(RevokeAccess),
List(ListAccessesGranted),
Owned(ListOwnedObjects),
Obtained(ListAccessRightsObtained),
}
impl AccessAction {
pub async fn process(&self, kms_rest_client: KmsClient) -> KmsCliResult<()> {
match self {
Self::Grant(action) => action.run(kms_rest_client).await?,
Self::Revoke(action) => action.run(kms_rest_client).await?,
Self::List(action) => {
action.run(kms_rest_client).await?;
}
Self::Owned(action) => {
action.run(kms_rest_client).await?;
}
Self::Obtained(action) => {
action.run(kms_rest_client).await?;
}
}
Ok(())
}
}
#[derive(Parser, Debug)]
pub struct GrantAccess {
#[clap(required = true)]
pub user: String,
#[clap(long, short = 'i')]
pub object_uid: Option<String>,
#[clap(required = true)]
pub operations: Vec<KmipOperation>,
}
impl GrantAccess {
pub async fn run(&self, kms_rest_client: KmsClient) -> KmsCliResult<()> {
let requires_object_uid = self
.operations
.iter()
.any(|op| *op != KmipOperation::Create);
let uid = if requires_object_uid {
let object_uid = self
.object_uid
.clone()
.context("Object UID is required for operations other than `create`")?;
Some(UniqueIdentifier::TextString(object_uid))
} else {
None
};
let access = Access {
unique_identifier: uid.clone(),
user_id: self.user.clone(),
operation_types: self.operations.clone(),
};
kms_rest_client
.grant_access(access)
.await
.with_context(|| "Can't execute the query on the kms server")?;
let stdout = format!(
"The following kmip operations: {:?}, were successfully granted to user `{}` on \
object `{}`",
self.operations,
self.user,
uid.as_ref()
.map_or_else(|| "N/A".to_owned(), std::string::ToString::to_string)
);
console::Stdout::new(&stdout).write()?;
Ok(())
}
}
#[derive(Parser, Debug)]
pub struct RevokeAccess {
#[clap(required = true)]
pub(crate) user: String,
#[clap(long, short = 'i')]
pub(crate) object_uid: Option<String>,
#[clap(required = true)]
pub(crate) operations: Vec<KmipOperation>,
}
impl RevokeAccess {
pub async fn run(&self, kms_rest_client: KmsClient) -> KmsCliResult<()> {
let requires_object_uid = self
.operations
.iter()
.any(|op| *op != KmipOperation::Create);
let uid = if requires_object_uid {
let object_uid = self
.object_uid
.clone()
.context("Object UID is required for operations other than `create`")?;
Some(UniqueIdentifier::TextString(object_uid))
} else {
None
};
let access = Access {
unique_identifier: uid.clone(),
user_id: self.user.clone(),
operation_types: self.operations.clone(),
};
kms_rest_client
.revoke_access(access)
.await
.with_context(|| "Can't execute the query on the kms server")?;
let stdout = format!(
"The following kmip operations: {:?}, have been removed for user `{}` on object `{}`",
self.operations,
self.user,
uid.as_ref()
.map_or_else(|| "N/A".to_owned(), std::string::ToString::to_string)
);
console::Stdout::new(&stdout).write()?;
Ok(())
}
}
#[derive(Parser, Debug)]
pub struct ListAccessesGranted {
#[clap(required = true)]
pub(crate) object_uid: String,
}
impl ListAccessesGranted {
pub async fn run(&self, kms_rest_client: KmsClient) -> KmsCliResult<Vec<UserAccessResponse>> {
let accesses = kms_rest_client
.list_access(&self.object_uid)
.await
.with_context(|| "Can't execute the query on the kms server")?;
let stdout = format!(
"The access rights granted on object {} are:",
&self.object_uid
);
let mut stdout = console::Stdout::new(&stdout);
stdout.set_accesses(&accesses);
stdout.write()?;
Ok(accesses)
}
}
#[derive(Parser, Default, Debug)]
pub struct ListOwnedObjects;
impl ListOwnedObjects {
pub async fn run(&self, kms_rest_client: KmsClient) -> KmsCliResult<Vec<ObjectOwnedResponse>> {
let objects = kms_rest_client
.list_owned_objects()
.await
.with_context(|| "Can't execute the query on the kms server")?;
if objects.is_empty() {
console::Stdout::new("No object owned by this user.").write()?;
} else {
let mut stdout = console::Stdout::new("The objects owned by this user are:");
stdout.set_object_owned(&objects);
stdout.write()?;
}
Ok(objects)
}
}
#[derive(Parser, Debug)]
pub struct ListAccessRightsObtained;
impl ListAccessRightsObtained {
pub async fn run(
&self,
kms_rest_client: KmsClient,
) -> KmsCliResult<Vec<AccessRightsObtainedResponse>> {
let objects = kms_rest_client
.list_access_rights_obtained()
.await
.with_context(|| "Can't execute the query on the kms server")?;
if objects.is_empty() {
console::Stdout::new("No access right obtained.").write()?;
} else {
let mut stdout = console::Stdout::new("The access rights obtained are: ");
stdout.set_access_rights_obtained(&objects);
stdout.write()?;
}
Ok(objects)
}
}