diff --git a/crates/cli/src/commands/alias.rs b/crates/cli/src/commands/alias.rs index 80e799d..9fb4914 100644 --- a/crates/cli/src/commands/alias.rs +++ b/crates/cli/src/commands/alias.rs @@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize}; use crate::exit_code::ExitCode; use crate::output::{Formatter, OutputConfig}; +use crate::secret_input::{SecretSource, can_prompt, read_code_interactive}; use rc_core::{Alias, AliasManager, Error, ObjectStore as _, validate_alias_endpoint}; use rc_s3::S3Client; @@ -43,10 +44,10 @@ pub struct SetArgs { /// S3 endpoint URL (e.g., `http://localhost:9000`, `https://s3.amazonaws.com`) pub endpoint: String, - /// Access key ID (omit with --anonymous) + /// Access key ID (prompted on a terminal when omitted; omit with --anonymous) pub access_key: Option, - /// Secret access key (omit with --anonymous) + /// Secret access key (prompted on a terminal when omitted; omit with --anonymous) pub secret_key: Option, /// Send requests without SigV4 credentials @@ -236,7 +237,7 @@ pub async fn execute(cmd: AliasCommands, output_config: OutputConfig) -> ExitCod } } -async fn execute_set(args: SetArgs, manager: &AliasManager, formatter: &Formatter) -> ExitCode { +async fn execute_set(mut args: SetArgs, manager: &AliasManager, formatter: &Formatter) -> ExitCode { // Validate inputs if args.name.is_empty() { return formatter.fail(ExitCode::UsageError, "Alias name cannot be empty"); @@ -257,11 +258,11 @@ async fn execute_set(args: SetArgs, manager: &AliasManager, formatter: &Formatte ); } - let has_access_key = args + let mut has_access_key = args .access_key .as_ref() .is_some_and(|value| !value.is_empty()); - let has_secret_key = args + let mut has_secret_key = args .secret_key .as_ref() .is_some_and(|value| !value.is_empty()); @@ -273,6 +274,38 @@ async fn execute_set(args: SetArgs, manager: &AliasManager, formatter: &Formatte ); } + // Prompt for missing keys only on a terminal, so scripts and --json keep + // failing fast instead of hanging. This keeps the keys out of shell history. + if !args.anonymous && (!has_access_key || !has_secret_key) && can_prompt(formatter.is_json()) { + if !has_access_key { + match read_code_interactive("Enter Access Key: ") { + Ok(value) if !value.is_empty() => { + args.access_key = Some(value.to_string()); + has_access_key = true; + } + Ok(_) => {} + Err(e) => { + let code = exit_code_from_error(&e); + formatter.error_with_code(code, &e.to_string()); + return code; + } + } + } + if !has_secret_key { + match SecretSource::Prompt.load("Enter Secret Key: ") { + Ok(value) => { + args.secret_key = Some(value.to_string()); + has_secret_key = true; + } + Err(e) => { + let code = exit_code_from_error(&e); + formatter.error_with_code(code, &e.to_string()); + return code; + } + } + } + } + if !args.anonymous && (!has_access_key || !has_secret_key) { return formatter.fail( ExitCode::UsageError, diff --git a/docs/reference/rc/alias.md b/docs/reference/rc/alias.md index 981c7b5..04e6dcb 100644 --- a/docs/reference/rc/alias.md +++ b/docs/reference/rc/alias.md @@ -8,7 +8,7 @@ The `rc alias` operation manages named S3-compatible service endpoints in the lo ```bash rc [GLOBAL OPTIONS] alias -rc [GLOBAL OPTIONS] alias set [OPTIONS] +rc [GLOBAL OPTIONS] alias set [OPTIONS] [ACCESS_KEY] [SECRET_KEY] rc [GLOBAL OPTIONS] alias list [-l|--long] rc [GLOBAL OPTIONS] alias remove rc [GLOBAL OPTIONS] alias export [NAMES]... [--output ] [--include-credentials --acknowledge-credentials] @@ -31,8 +31,8 @@ rc [GLOBAL OPTIONS] alias import [--replace] | --- | --- | | `NAME` | Local alias name, such as `local`, `s3`, or `rustfs`. | | `ENDPOINT` | S3-compatible endpoint URL, such as `http://localhost:9000`. | -| `ACCESS_KEY` | Access key ID for the endpoint. | -| `SECRET_KEY` | Secret access key for the endpoint. | +| `ACCESS_KEY` | Access key ID for the endpoint. Prompted on a terminal when omitted. | +| `SECRET_KEY` | Secret access key for the endpoint. Prompted with hidden input on a terminal when omitted. | | `--region` | AWS region to associate with the alias. Defaults to `us-east-1`. | | `--signature` | Signature version, `v4` or `v2`. Defaults to `v4`. | | `--bucket-lookup` | Bucket lookup style: `auto`, `path`, or `dns`. Defaults to `auto`. | @@ -52,6 +52,14 @@ Configure a local RustFS or MinIO-compatible service: rc alias set local http://localhost:9000 ACCESS_KEY SECRET_KEY ``` +Omit the keys on a terminal to be prompted instead of typing them into the shell, where they would be saved in history: + +```bash +rc alias set local http://localhost:9000 +``` + +When stdin is not a terminal, or when `--json` is set, the keys are required on the command line. + Configure AWS S3 with an explicit region: ```bash