Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
cli: Improve passphrase handling
cloudhead committed 2 years ago
commit 87debf380e5b13f2d633e9e8c79929152b575d79
parent ebee41fbf12255b2b9699c9fb68bebf90553e9f0
4 files changed +30 -22
modified radicle-cli/src/commands/auth.rs
@@ -171,12 +171,12 @@ pub fn authenticate(options: Options, profile: &Profile) -> anyhow::Result<()> {
                term::success!("Radicle key already in ssh-agent");
                return Ok(());
            }
-

-
            let validator = term::io::PassphraseValidator::new(profile.keystore.clone());
-
            let passphrase = if options.stdin {
+
            let passphrase = if let Some(phrase) = profile::env::passphrase() {
+
                phrase
+
            } else if options.stdin {
                term::passphrase_stdin()?
            } else {
-
                term::passphrase(RAD_PASSPHRASE, validator)?
+
                term::io::passphrase(term::io::PassphraseValidator::new(profile.keystore.clone()))?
            };
            register(&mut agent, profile, passphrase)?;

@@ -191,7 +191,7 @@ pub fn authenticate(options: Options, profile: &Profile) -> anyhow::Result<()> {
    // Try RAD_PASSPHRASE fallback.
    if let Some(passphrase) = profile::env::passphrase() {
        ssh::keystore::MemorySigner::load(&profile.keystore, Some(passphrase))
-
            .map_err(|_| anyhow!("RAD_PASSPHRASE failed"))?;
+
            .map_err(|_| anyhow!("`{RAD_PASSPHRASE}` is invalid"))?;
        return Ok(());
    };

modified radicle-cli/src/commands/node/control.rs
@@ -31,7 +31,11 @@ pub fn start(
        // Ask passphrase here, otherwise it'll be a fatal error when running the daemon
        // without `RAD_PASSPHRASE`.
        let validator = term::io::PassphraseValidator::new(profile.keystore.clone());
-
        let Ok(passphrase) = term::io::passphrase(profile::env::RAD_PASSPHRASE, validator) else {
+
        let passphrase = if let Some(phrase) = profile::env::passphrase() {
+
            phrase
+
        } else if let Ok(phrase) = term::io::passphrase(validator) {
+
            phrase
+
        } else {
            anyhow::bail!("your radicle passphrase is required to start your node");
        };
        Some((profile::env::RAD_PASSPHRASE, passphrase))
modified radicle-cli/src/terminal/io.rs
@@ -39,13 +39,22 @@ impl inquire::validator::StringValidator for PassphraseValidator {
    }
}

-
/// Get the signer. First we try getting it from ssh-agent, otherwise we prompt the user.
+
/// Get the signer. First we try getting it from ssh-agent, otherwise we prompt the user,
+
/// if we're connected to a TTY.
pub fn signer(profile: &Profile) -> anyhow::Result<Box<dyn Signer>> {
    if let Ok(signer) = profile.signer() {
        return Ok(signer);
    }
    let validator = PassphraseValidator::new(profile.keystore.clone());
-
    let passphrase = passphrase(RAD_PASSPHRASE, validator)?;
+
    let passphrase = match passphrase(validator) {
+
        Ok(p) => p,
+
        Err(inquire::InquireError::NotTTY) => {
+
            return Err(anyhow::anyhow!(
+
                "running in non-interactive mode, please set `{RAD_PASSPHRASE}` to unseal your key",
+
            ));
+
        }
+
        Err(e) => return Err(e.into()),
+
    };
    let spinner = spinner("Unsealing key...");
    let signer = MemorySigner::load(&profile.keystore, Some(passphrase))?;

modified radicle-term/src/io.rs
@@ -214,22 +214,17 @@ where
    Ok(value)
}

-
pub fn passphrase<K: AsRef<OsStr>, V: validator::StringValidator + 'static>(
-
    var: K,
+
pub fn passphrase<V: validator::StringValidator + 'static>(
    validate: V,
) -> Result<Passphrase, inquire::InquireError> {
-
    if let Ok(p) = env::var(var) {
-
        Ok(Passphrase::from(p))
-
    } else {
-
        Ok(Passphrase::from(
-
            Password::new("Passphrase:")
-
                .with_render_config(*CONFIG)
-
                .with_display_mode(inquire::PasswordDisplayMode::Masked)
-
                .without_confirmation()
-
                .with_validator(validate)
-
                .prompt()?,
-
        ))
-
    }
+
    Ok(Passphrase::from(
+
        Password::new("Passphrase:")
+
            .with_render_config(*CONFIG)
+
            .with_display_mode(inquire::PasswordDisplayMode::Masked)
+
            .without_confirmation()
+
            .with_validator(validate)
+
            .prompt()?,
+
    ))
}

pub fn passphrase_confirm<K: AsRef<OsStr>>(