cli: Register key on first `auth`
Registers the secret key with ssh-agent when `rad auth` is first called.
This commit is contained in:
parent
411c54a604
commit
e4b44370d3
|
|
@ -7,6 +7,7 @@ $ rad auth
|
||||||
Initializing your 🌱 profile and identity
|
Initializing your 🌱 profile and identity
|
||||||
|
|
||||||
✓ Creating your 🌱 Ed25519 keypair...
|
✓ Creating your 🌱 Ed25519 keypair...
|
||||||
|
! Adding your radicle key to ssh-agent...
|
||||||
✓ Your Radicle ID is did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi. This identifies your device.
|
✓ Your Radicle ID is did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi. This identifies your device.
|
||||||
|
|
||||||
👉 To create a radicle project, run `rad init` from a git repository.
|
👉 To create a radicle project, run `rad init` from a git repository.
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use std::ffi::OsString;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
|
||||||
use radicle::crypto::ssh;
|
use radicle::crypto::ssh;
|
||||||
|
use radicle::crypto::ssh::Passphrase;
|
||||||
use radicle::{profile, Profile};
|
use radicle::{profile, Profile};
|
||||||
|
|
||||||
use crate::terminal as term;
|
use crate::terminal as term;
|
||||||
|
|
@ -86,9 +87,16 @@ pub fn init(options: Options) -> anyhow::Result<()> {
|
||||||
term::passphrase_confirm()
|
term::passphrase_confirm()
|
||||||
}?;
|
}?;
|
||||||
let spinner = term::spinner("Creating your 🌱 Ed25519 keypair...");
|
let spinner = term::spinner("Creating your 🌱 Ed25519 keypair...");
|
||||||
let profile = Profile::init(home, passphrase)?;
|
let profile = Profile::init(home, passphrase.clone())?;
|
||||||
spinner.finish();
|
spinner.finish();
|
||||||
|
|
||||||
|
let spinner = term::spinner("Adding your radicle key to ssh-agent...");
|
||||||
|
if register(&profile, passphrase).is_ok() {
|
||||||
|
spinner.finish();
|
||||||
|
} else {
|
||||||
|
spinner.warn();
|
||||||
|
}
|
||||||
|
|
||||||
term::success!(
|
term::success!(
|
||||||
"Your Radicle ID is {}. This identifies your device.",
|
"Your Radicle ID is {}. This identifies your device.",
|
||||||
term::format::highlight(profile.did())
|
term::format::highlight(profile.did())
|
||||||
|
|
@ -124,12 +132,7 @@ pub fn authenticate(profile: &Profile, options: Options) -> anyhow::Result<()> {
|
||||||
term::passphrase()
|
term::passphrase()
|
||||||
}?;
|
}?;
|
||||||
let spinner = term::spinner("Unlocking...");
|
let spinner = term::spinner("Unlocking...");
|
||||||
let mut agent = ssh::agent::Agent::connect()?;
|
register(profile, passphrase)?;
|
||||||
let secret = profile
|
|
||||||
.keystore
|
|
||||||
.secret_key(passphrase)?
|
|
||||||
.ok_or_else(|| anyhow!("Key not found in {:?}", profile.keystore.path()))?;
|
|
||||||
agent.register(&secret)?;
|
|
||||||
spinner.finish();
|
spinner.finish();
|
||||||
|
|
||||||
term::success!("Radicle key added to ssh-agent");
|
term::success!("Radicle key added to ssh-agent");
|
||||||
|
|
@ -139,3 +142,16 @@ pub fn authenticate(profile: &Profile, options: Options) -> anyhow::Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register key with ssh-agent.
|
||||||
|
pub fn register(profile: &Profile, passphrase: Passphrase) -> anyhow::Result<()> {
|
||||||
|
let mut agent = ssh::agent::Agent::connect()?;
|
||||||
|
let secret = profile
|
||||||
|
.keystore
|
||||||
|
.secret_key(passphrase)?
|
||||||
|
.ok_or_else(|| anyhow!("Key not found in {:?}", profile.keystore.path()))?;
|
||||||
|
|
||||||
|
agent.register(&secret)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ use super::Error;
|
||||||
use super::{style, Paint};
|
use super::{style, Paint};
|
||||||
|
|
||||||
pub const ERROR_PREFIX: Paint<&str> = Paint::red("✗");
|
pub const ERROR_PREFIX: Paint<&str> = Paint::red("✗");
|
||||||
|
pub const WARNING_PREFIX: Paint<&str> = Paint::yellow("!");
|
||||||
pub const TAB: &str = " ";
|
pub const TAB: &str = " ";
|
||||||
|
|
||||||
/// Render configuration.
|
/// Render configuration.
|
||||||
|
|
@ -129,7 +130,7 @@ pub fn subcommand(msg: impl fmt::Display) {
|
||||||
pub fn warning(warning: &str) {
|
pub fn warning(warning: &str) {
|
||||||
println!(
|
println!(
|
||||||
"{} {} {warning}",
|
"{} {} {warning}",
|
||||||
Paint::yellow("!"),
|
WARNING_PREFIX,
|
||||||
Paint::yellow("Warning:").bold(),
|
Paint::yellow("Warning:").bold(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::mem::ManuallyDrop;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::{fmt, io, thread, time};
|
use std::{fmt, io, thread, time};
|
||||||
|
|
||||||
use crate::terminal::io::ERROR_PREFIX;
|
use crate::terminal::io::{ERROR_PREFIX, WARNING_PREFIX};
|
||||||
use crate::terminal::Paint;
|
use crate::terminal::Paint;
|
||||||
|
|
||||||
/// How much time to wait between spinner animation updates.
|
/// How much time to wait between spinner animation updates.
|
||||||
|
|
@ -34,6 +34,7 @@ enum State {
|
||||||
Running { cursor: usize },
|
Running { cursor: usize },
|
||||||
Canceled,
|
Canceled,
|
||||||
Done,
|
Done,
|
||||||
|
Warn,
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,6 +85,13 @@ impl Spinner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Cancel the spinner with a warning sign.
|
||||||
|
pub fn warn(self) {
|
||||||
|
if let Ok(mut progress) = self.progress.lock() {
|
||||||
|
progress.state = State::Warn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the spinner's message.
|
/// Set the spinner's message.
|
||||||
pub fn message(&mut self, msg: impl fmt::Display) {
|
pub fn message(&mut self, msg: impl fmt::Display) {
|
||||||
let msg = msg.to_string();
|
let msg = msg.to_string();
|
||||||
|
|
@ -150,6 +158,13 @@ pub fn spinner(message: impl ToString) -> Spinner {
|
||||||
.ok();
|
.ok();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Progress {
|
||||||
|
state: State::Warn,
|
||||||
|
message,
|
||||||
|
} => {
|
||||||
|
writeln!(stdout, "{WARNING_PREFIX} {message}").ok();
|
||||||
|
break;
|
||||||
|
}
|
||||||
Progress {
|
Progress {
|
||||||
state: State::Error,
|
state: State::Error,
|
||||||
message,
|
message,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue