use format_table::format_table;
use garage_util::error::*;
use garage_api_admin::api::*;
use crate::cli::structs::*;
use crate::cli_v2::*;
impl Cli {
pub async fn cmd_key(&self, cmd: KeyOperation) -> Result<(), Error> {
match cmd {
KeyOperation::List => self.cmd_list_keys().await,
KeyOperation::Info(query) => self.cmd_key_info(query).await,
KeyOperation::Create(query) => self.cmd_create_key(query).await,
KeyOperation::Rename(query) => self.cmd_rename_key(query).await,
KeyOperation::Delete(query) => self.cmd_delete_key(query).await,
KeyOperation::Allow(query) => self.cmd_allow_key(query).await,
KeyOperation::Deny(query) => self.cmd_deny_key(query).await,
KeyOperation::Import(query) => self.cmd_import_key(query).await,
}
}
pub async fn cmd_list_keys(&self) -> Result<(), Error> {
let keys = self.api_request(ListKeysRequest).await?;
println!("List of keys:");
let mut table = vec![];
for key in keys.0.iter() {
table.push(format!("\t{}\t{}", key.id, key.name));
}
format_table(table);
Ok(())
}
pub async fn cmd_key_info(&self, opt: KeyInfoOpt) -> Result<(), Error> {
let key = self
.api_request(GetKeyInfoRequest {
id: None,
search: Some(opt.key_pattern),
show_secret_key: opt.show_secret,
})
.await?;
print_key_info(&key);
Ok(())
}
pub async fn cmd_create_key(&self, opt: KeyNewOpt) -> Result<(), Error> {
let key = self
.api_request(CreateKeyRequest {
name: Some(opt.name),
})
.await?;
print_key_info(&key.0);
Ok(())
}
pub async fn cmd_rename_key(&self, opt: KeyRenameOpt) -> Result<(), Error> {
let key = self
.api_request(GetKeyInfoRequest {
id: None,
search: Some(opt.key_pattern),
show_secret_key: false,
})
.await?;
let new_key = self
.api_request(UpdateKeyRequest {
id: key.access_key_id,
body: UpdateKeyRequestBody {
name: Some(opt.new_name),
allow: None,
deny: None,
},
})
.await?;
print_key_info(&new_key.0);
Ok(())
}
pub async fn cmd_delete_key(&self, opt: KeyDeleteOpt) -> Result<(), Error> {
let key = self
.api_request(GetKeyInfoRequest {
id: None,
search: Some(opt.key_pattern),
show_secret_key: false,
})
.await?;
if !opt.yes {
println!("About to delete key {}...", key.access_key_id);
return Err(Error::Message(
"Add --yes flag to really perform this operation".to_string(),
));
}
self.api_request(DeleteKeyRequest {
id: key.access_key_id.clone(),
})
.await?;
println!("Access key {} has been deleted.", key.access_key_id);
Ok(())
}
pub async fn cmd_allow_key(&self, opt: KeyPermOpt) -> Result<(), Error> {
let key = self
.api_request(GetKeyInfoRequest {
id: None,
search: Some(opt.key_pattern),
show_secret_key: false,
})
.await?;
let new_key = self
.api_request(UpdateKeyRequest {
id: key.access_key_id,
body: UpdateKeyRequestBody {
name: None,
allow: Some(KeyPerm {
create_bucket: opt.create_bucket,
}),
deny: None,
},
})
.await?;
print_key_info(&new_key.0);
Ok(())
}
pub async fn cmd_deny_key(&self, opt: KeyPermOpt) -> Result<(), Error> {
let key = self
.api_request(GetKeyInfoRequest {
id: None,
search: Some(opt.key_pattern),
show_secret_key: false,
})
.await?;
let new_key = self
.api_request(UpdateKeyRequest {
id: key.access_key_id,
body: UpdateKeyRequestBody {
name: None,
allow: None,
deny: Some(KeyPerm {
create_bucket: opt.create_bucket,
}),
},
})
.await?;
print_key_info(&new_key.0);
Ok(())
}
pub async fn cmd_import_key(&self, opt: KeyImportOpt) -> Result<(), Error> {
if !opt.yes {
return Err(Error::Message("This command is intended to re-import keys that were previously generated by Garage. If you want to create a new key, use `garage key new` instead. Add the --yes flag if you really want to re-import a key.".to_string()));
}
let new_key = self
.api_request(ImportKeyRequest {
name: Some(opt.name),
access_key_id: opt.key_id,
secret_access_key: opt.secret_key,
})
.await?;
print_key_info(&new_key.0);
Ok(())
}
}
fn print_key_info(key: &GetKeyInfoResponse) {
println!("Key name: {}", key.name);
println!("Key ID: {}", key.access_key_id);
println!(
"Secret key: {}",
key.secret_access_key.as_deref().unwrap_or("(redacted)")
);
println!("Can create buckets: {}", key.permissions.create_bucket);
println!("\nKey-specific bucket aliases:");
let mut table = vec![];
for bucket in key.buckets.iter() {
for la in bucket.local_aliases.iter() {
table.push(format!(
"\t{}\t{}\t{}",
la,
bucket.global_aliases.join(","),
bucket.id
));
}
}
format_table(table);
println!("\nAuthorized buckets:");
let mut table = vec![];
for bucket in key.buckets.iter() {
let rflag = if bucket.permissions.read { "R" } else { " " };
let wflag = if bucket.permissions.write { "W" } else { " " };
let oflag = if bucket.permissions.owner { "O" } else { " " };
table.push(format!(
"\t{}{}{}\t{}\t{}\t{:.16}",
rflag,
wflag,
oflag,
bucket.global_aliases.join(","),
bucket.local_aliases.join(","),
bucket.id
));
}
format_table(table);
}