rad-remote-helper: honor RAD_PASSPHRASE
Make testing more convenient by reducing rad-remote-helper's dependency on SSH Agent. It may be opted out of by setting the `RAD_PASSPHRASE` environment variable. Signed-off-by: Slack Coder <slackcoder@server.ky>
This commit is contained in:
parent
3682ef195b
commit
03bc9d84d6
|
|
@ -7,7 +7,7 @@ use radicle::cob::issue::Issue;
|
|||
use radicle::cob::thread::CommentId;
|
||||
use radicle::crypto::ssh::keystore::Passphrase;
|
||||
use radicle::crypto::Signer;
|
||||
use radicle::profile::env::RAD_PASSPHRASE;
|
||||
use radicle::profile;
|
||||
use radicle::profile::Profile;
|
||||
|
||||
use radicle_crypto::ssh::keystore::MemorySigner;
|
||||
|
|
@ -177,19 +177,16 @@ pub fn abort<D: fmt::Display>(prompt: D) -> bool {
|
|||
|
||||
/// Get the signer. First we try getting it from ssh-agent, otherwise we prompt the user.
|
||||
pub fn signer(profile: &Profile) -> anyhow::Result<Box<dyn Signer>> {
|
||||
let signer = if let Ok(passphrase) = read_passphrase_from_env_var() {
|
||||
MemorySigner::load(&profile.keystore, passphrase)?.boxed()
|
||||
} else if let Ok(signer) = profile.signer() {
|
||||
signer.boxed()
|
||||
} else {
|
||||
let passphrase = secret_input();
|
||||
let spinner = spinner("Unsealing key...");
|
||||
let signer = MemorySigner::load(&profile.keystore, passphrase)?;
|
||||
if let Ok(signer) = profile.signer() {
|
||||
return Ok(signer);
|
||||
}
|
||||
|
||||
spinner.finish();
|
||||
signer.boxed()
|
||||
};
|
||||
Ok(signer)
|
||||
let passphrase = secret_input();
|
||||
let spinner = spinner("Unsealing key...");
|
||||
let signer = MemorySigner::load(&profile.keystore, passphrase)?;
|
||||
|
||||
spinner.finish();
|
||||
Ok(signer.boxed())
|
||||
}
|
||||
|
||||
pub fn theme() -> ColorfulTheme {
|
||||
|
|
@ -313,9 +310,9 @@ pub fn secret_stdin() -> Result<Passphrase, anyhow::Error> {
|
|||
}
|
||||
|
||||
pub fn read_passphrase(stdin: bool, confirm: bool) -> Result<Passphrase, anyhow::Error> {
|
||||
let passphrase = match read_passphrase_from_env_var() {
|
||||
Ok(input) => input,
|
||||
_ => {
|
||||
let passphrase = match profile::env::read_passphrase() {
|
||||
Some(input) => input,
|
||||
None => {
|
||||
if stdin {
|
||||
secret_stdin()?
|
||||
} else if confirm {
|
||||
|
|
@ -329,12 +326,6 @@ pub fn read_passphrase(stdin: bool, confirm: bool) -> Result<Passphrase, anyhow:
|
|||
Ok(passphrase)
|
||||
}
|
||||
|
||||
pub fn read_passphrase_from_env_var() -> Result<Passphrase, anyhow::Error> {
|
||||
let passphrase = std::env::var(RAD_PASSPHRASE)?;
|
||||
|
||||
Ok(Passphrase::from(passphrase.trim_end().to_owned()))
|
||||
}
|
||||
|
||||
pub fn select<'a, T>(options: &'a [T], active: &'a T) -> Option<&'a T>
|
||||
where
|
||||
T: fmt::Display + Eq + PartialEq,
|
||||
|
|
|
|||
|
|
@ -15,13 +15,15 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::crypto::ssh::agent::{Agent, AgentSigner};
|
||||
use crate::crypto::ssh::agent::Agent;
|
||||
use crate::crypto::ssh::{Keystore, Passphrase};
|
||||
use crate::crypto::PublicKey;
|
||||
use crate::crypto::{PublicKey, Signer};
|
||||
use crate::node;
|
||||
use crate::storage::git::transport;
|
||||
use crate::storage::git::Storage;
|
||||
|
||||
use radicle_crypto::ssh::keystore;
|
||||
|
||||
/// Environment variables used by radicle.
|
||||
pub mod env {
|
||||
pub use std::env::*;
|
||||
|
|
@ -32,6 +34,14 @@ pub mod env {
|
|||
pub const RAD_SOCKET: &str = "RAD_SOCKET";
|
||||
/// Passphrase for the encrypted radicle secret key.
|
||||
pub const RAD_PASSPHRASE: &str = "RAD_PASSPHRASE";
|
||||
|
||||
pub fn read_passphrase() -> Option<super::Passphrase> {
|
||||
let Ok(passphrase) = std::env::var(RAD_PASSPHRASE) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(super::Passphrase::from(passphrase.trim_end().to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
|
@ -40,6 +50,8 @@ pub enum Error {
|
|||
Io(#[from] io::Error),
|
||||
#[error(transparent)]
|
||||
Keystore(#[from] crate::crypto::ssh::keystore::Error),
|
||||
#[error(transparent)]
|
||||
MemorySigner(#[from] keystore::MemorySignerError),
|
||||
#[error("no profile found at the filepath '{0}'")]
|
||||
NotFound(PathBuf),
|
||||
#[error("error connecting to ssh-agent: {0}")]
|
||||
|
|
@ -95,12 +107,17 @@ impl Profile {
|
|||
&self.public_key
|
||||
}
|
||||
|
||||
pub fn signer(&self) -> Result<AgentSigner, Error> {
|
||||
pub fn signer(&self) -> Result<Box<dyn Signer>, Error> {
|
||||
if let Some(passphrase) = env::read_passphrase() {
|
||||
let signer = keystore::MemorySigner::load(&self.keystore, passphrase)?;
|
||||
return Ok(signer.boxed());
|
||||
}
|
||||
|
||||
match Agent::connect() {
|
||||
Ok(agent) => {
|
||||
let signer = agent.signer(self.public_key);
|
||||
if signer.is_ready()? {
|
||||
Ok(signer)
|
||||
Ok(signer.boxed())
|
||||
} else {
|
||||
Err(Error::KeyNotRegistered(self.public_key))
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue