Skip to content

Commit 4422abc

Browse files
authored
feat(admin): rc admin account and user two-factor commands (#358)
1 parent b611618 commit 4422abc

18 files changed

Lines changed: 3256 additions & 119 deletions

File tree

‎crates/cli/src/commands/admin/account.rs‎

Lines changed: 1024 additions & 0 deletions
Large diffs are not rendered by default.

‎crates/cli/src/commands/admin/config.rs‎

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use zeroize::Zeroizing;
1717
use super::get_admin_client;
1818
use crate::exit_code::ExitCode;
1919
use crate::output::Formatter;
20+
use crate::private_file::write_private_file;
2021

2122
#[derive(Subcommand, Debug)]
2223
#[command(disable_help_subcommand = true)]
@@ -839,20 +840,6 @@ fn read_protected_value_file(path: &Path) -> rc_core::Result<Zeroizing<String>>
839840
Ok(Zeroizing::new(value.to_string()))
840841
}
841842

842-
fn write_private_file(path: &Path, contents: &[u8]) -> rc_core::Result<()> {
843-
let mut options = std::fs::OpenOptions::new();
844-
options.write(true).create_new(true);
845-
#[cfg(unix)]
846-
{
847-
use std::os::unix::fs::OpenOptionsExt;
848-
options.mode(0o600);
849-
}
850-
let mut file = options.open(path)?;
851-
use std::io::Write;
852-
file.write_all(contents)?;
853-
Ok(())
854-
}
855-
856843
fn emit_error(error: &Error, formatter: &Formatter) -> ExitCode {
857844
let code = ExitCode::from_i32(error.exit_code()).unwrap_or(ExitCode::GeneralError);
858845
if formatter.is_json() {

‎crates/cli/src/commands/admin/idp.rs‎

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ use rc_core::{Error, Result};
99
use serde::Serialize;
1010
use serde_json::Value;
1111
use std::fs::File;
12-
use std::io::{BufRead, IsTerminal, Read, Write};
12+
use std::io::Read;
1313
use std::path::{Path, PathBuf};
1414
use zeroize::Zeroizing;
1515

1616
use super::{emit_observability_error, get_admin_client};
17+
use crate::confirm::{Confirmation, confirm};
1718
use crate::exit_code::ExitCode;
1819
use crate::output::Formatter;
1920

@@ -554,35 +555,19 @@ async fn prepare_and_delete(
554555
}
555556

556557
fn confirm_delete(provider: &OidcProvider, yes: bool, formatter: &Formatter) -> Result<()> {
557-
if yes {
558-
return Ok(());
559-
}
560-
if formatter.is_json() || !std::io::stdin().is_terminal() {
561-
return Err(Error::InvalidPath(
562-
"OIDC provider deletion requires --yes in non-interactive or JSON mode".to_string(),
563-
));
564-
}
565-
566-
let mut stderr = std::io::stderr().lock();
567-
write!(
568-
stderr,
569-
"Delete OIDC provider '{}'? [y/N] ",
558+
let prompt = format!(
559+
"Delete OIDC provider '{}'? [y/N]",
570560
safe(&provider.provider_id, formatter)
561+
);
562+
confirm(
563+
&Confirmation {
564+
prompt: &prompt,
565+
requires_yes: "OIDC provider deletion requires --yes in non-interactive or JSON mode",
566+
declined: "OIDC provider deletion was declined",
567+
},
568+
yes,
569+
formatter,
571570
)
572-
.map_err(Error::Io)?;
573-
stderr.flush().map_err(Error::Io)?;
574-
let mut answer = String::new();
575-
std::io::stdin()
576-
.lock()
577-
.read_line(&mut answer)
578-
.map_err(Error::Io)?;
579-
if matches!(answer.trim().to_ascii_lowercase().as_str(), "y" | "yes") {
580-
Ok(())
581-
} else {
582-
Err(Error::Interrupted(
583-
"OIDC provider deletion was declined".to_string(),
584-
))
585-
}
586571
}
587572

588573
async fn prepare_and_apply_mutation(

‎crates/cli/src/commands/admin/mod.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! service accounts, and cluster operations through the RustFS Admin API.
55
66
mod access_key;
7+
mod account;
78
mod bucket_metadata;
89
mod capabilities;
910
mod config;
@@ -39,6 +40,10 @@ use rc_s3::AdminClient;
3940
/// Admin subcommands for IAM and cluster management
4041
#[derive(Subcommand, Debug)]
4142
pub enum AdminCommands {
43+
/// Manage the identity this alias authenticates as
44+
#[command(subcommand)]
45+
Account(account::AccountCommands),
46+
4247
/// Discover effective RustFS runtime capabilities
4348
Capabilities(capabilities::CapabilitiesArgs),
4449

@@ -135,6 +140,7 @@ pub async fn execute(cmd: AdminCommands, output_config: OutputConfig) -> ExitCod
135140
let formatter = Formatter::new(output_config);
136141

137142
match cmd {
143+
AdminCommands::Account(account_cmd) => account::execute(account_cmd, &formatter).await,
138144
AdminCommands::Capabilities(args) => capabilities::execute(args, &formatter).await,
139145
AdminCommands::Diagnostics(command) => diagnostics::execute(command, &formatter).await,
140146
AdminCommands::Config(config_cmd) => config::execute(config_cmd, &formatter).await,

0 commit comments

Comments
 (0)