From 0f3212a1b2d35e848672d8543b9ae721437b5476 Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Fri, 30 Jun 2023 14:02:44 +0200 Subject: [PATCH] cli: `rad self` improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add `--home` flag * Organize the information better Now looks like this: DID did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi └╴Node ID (NID) z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi SSH running (823) ├╴Key (hash) SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA └╴Key (full) ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1 Home [..] ├╴Storage [..]/storage ├╴Keys [..]/keys └╴Node [..]/node --- radicle-cli/examples/rad-auth.md | 12 ++------ radicle-cli/examples/rad-self.md | 21 +++++++++----- radicle-cli/src/commands/auth.rs | 2 +- radicle-cli/src/commands/self.rs | 42 ++++++++++++++++++++++------ radicle-node/src/test/environment.rs | 2 +- radicle-ssh/src/agent/client.rs | 11 ++++++-- 6 files changed, 62 insertions(+), 28 deletions(-) diff --git a/radicle-cli/examples/rad-auth.md b/radicle-cli/examples/rad-auth.md index cd3e9fbc..343adc4d 100644 --- a/radicle-cli/examples/rad-auth.md +++ b/radicle-cli/examples/rad-auth.md @@ -7,7 +7,7 @@ $ rad auth Initializing your radicle 👾 identity ✓ Creating your Ed25519 keypair... -✓ Your Radicle ID is did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi. This identifies your device. +✓ Your Radicle DID is did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi. This identifies your device. To create a radicle project, run `rad init` from a git repository. ``` @@ -15,12 +15,6 @@ To create a radicle project, run `rad init` from a git repository. You can get the above information at all times using the `self` command: ``` -$ rad self -DID did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi -Node ID (NID) z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi -Key (hash) SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA -Key (full) ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1 -Storage (git) [..]/storage -Storage (keys) [..]/keys -Node (socket) [..]/node/control.sock +$ rad self --did +did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi ``` diff --git a/radicle-cli/examples/rad-self.md b/radicle-cli/examples/rad-self.md index 1becbc1d..ad7257fa 100644 --- a/radicle-cli/examples/rad-self.md +++ b/radicle-cli/examples/rad-self.md @@ -3,13 +3,15 @@ device and node. ``` $ rad self -DID did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi -Node ID (NID) z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi -Key (hash) SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA -Key (full) ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1 -Storage (git) [..] -Storage (keys) [..] -Node (socket) [..] +DID did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi +└╴Node ID (NID) z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi +SSH not running +├╴Key (hash) SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA +└╴Key (full) ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1 +Home [..]/home/alice/.radicle +├╴Storage [..]/home/alice/.radicle/storage +├╴Keys [..]/home/alice/.radicle/keys +└╴Node [..]/home/alice/.radicle/node ``` If you need to display only your DID, Node ID, or SSH Public Key, you can use @@ -29,3 +31,8 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi $ rad self --ssh-key ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1 ``` + +``` +$ rad self --home +[..]/home/alice/.radicle +``` diff --git a/radicle-cli/src/commands/auth.rs b/radicle-cli/src/commands/auth.rs index 1f655cfa..35cae662 100644 --- a/radicle-cli/src/commands/auth.rs +++ b/radicle-cli/src/commands/auth.rs @@ -106,7 +106,7 @@ pub fn init(options: Options) -> anyhow::Result<()> { } term::success!( - "Your Radicle ID is {}. This identifies your device.", + "Your Radicle DID is {}. This identifies your device.", term::format::highlight(profile.did()) ); diff --git a/radicle-cli/src/commands/self.rs b/radicle-cli/src/commands/self.rs index fbb6bd16..aae20aa9 100644 --- a/radicle-cli/src/commands/self.rs +++ b/radicle-cli/src/commands/self.rs @@ -20,6 +20,7 @@ Options --nid Show your Node ID (NID) --did Show your DID + --home Show your Radicle home --ssh-key Show your public key in OpenSSH format --ssh-fingerprint Show your public key fingerprint in OpenSSH format --help Show help @@ -30,6 +31,7 @@ Options enum Show { NodeId, Did, + Home, SshKey, SshFingerprint, All, @@ -55,6 +57,9 @@ impl Args for Options { Long("did") if show.is_none() => { show = Some(Show::Did); } + Long("home") if show.is_none() => { + show = Some(Show::Home); + } Long("ssh-key") if show.is_none() => { show = Some(Show::SshKey); } @@ -87,6 +92,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { Show::Did => { term::print(profile.did()); } + Show::Home => { + term::print(profile.home().display()); + } Show::SshKey => { term::print(ssh::fmt::key(profile.id())); } @@ -110,38 +118,56 @@ fn all(profile: &Profile) -> anyhow::Result<()> { let node_id = profile.id(); table.push([ - term::format::style("Node ID (NID)").to_string(), + term::format::style("└╴Node ID (NID)").to_string(), term::format::tertiary(node_id).to_string(), ]); + let ssh_agent = match ssh::agent::Agent::connect() { + Ok(c) => term::format::positive(format!( + "running ({})", + c.pid().map(|p| p.to_string()).unwrap_or(String::from("?")) + )), + Err(e) if e.is_not_running() => term::format::yellow(String::from("not running")), + Err(e) => term::format::negative(format!("error: {e}")), + }; + table.push([ + term::format::style("SSH").to_string(), + ssh_agent.to_string(), + ]); + let ssh_short = ssh::fmt::fingerprint(node_id); table.push([ - term::format::style("Key (hash)").to_string(), + term::format::style("├╴Key (hash)").to_string(), term::format::tertiary(ssh_short).to_string(), ]); let ssh_long = ssh::fmt::key(node_id); table.push([ - term::format::style("Key (full)").to_string(), + term::format::style("└╴Key (full)").to_string(), term::format::tertiary(ssh_long).to_string(), ]); + let home = profile.home(); + table.push([ + term::format::style("Home").to_string(), + term::format::tertiary(home.display()).to_string(), + ]); + let storage_path = profile.home.storage(); table.push([ - term::format::style("Storage (git)").to_string(), + term::format::style("├╴Storage").to_string(), term::format::tertiary(storage_path.display()).to_string(), ]); let keys_path = profile.home.keys(); table.push([ - term::format::style("Storage (keys)").to_string(), + term::format::style("├╴Keys").to_string(), term::format::tertiary(keys_path.display()).to_string(), ]); - let socket_path = profile.socket(); table.push([ - term::format::style("Node (socket)").to_string(), - term::format::tertiary(socket_path.display()).to_string(), + term::format::style("└╴Node").to_string(), + term::format::tertiary(profile.home.node().display()).to_string(), ]); table.print(); diff --git a/radicle-node/src/test/environment.rs b/radicle-node/src/test/environment.rs index 6ecab175..ab305262 100644 --- a/radicle-node/src/test/environment.rs +++ b/radicle-node/src/test/environment.rs @@ -90,7 +90,7 @@ impl Environment { /// Create a new profile in this environment. /// This should be used when a running node is not required. pub fn profile(&mut self, name: &str) -> Profile { - let home = Home::new(self.tmp().join("home").join(name)).unwrap(); + let home = Home::new(self.tmp().join("home").join(name).join(".radicle")).unwrap(); let storage = Storage::open(home.storage()).unwrap(); let keystore = Keystore::new(&home.keys()); let keypair = KeyPair::from_seed(Seed::from([!(self.users as u8); 32])); diff --git a/radicle-ssh/src/agent/client.rs b/radicle-ssh/src/agent/client.rs index 8a747f02..881c16fc 100644 --- a/radicle-ssh/src/agent/client.rs +++ b/radicle-ssh/src/agent/client.rs @@ -3,6 +3,7 @@ use std::io::{Read, Write}; use std::ops::DerefMut; use std::os::unix::net::UnixStream; use std::path::Path; +use std::str::FromStr; use byteorder::{BigEndian, ByteOrder, WriteBytesExt}; use log::*; @@ -51,12 +52,18 @@ pub struct AgentClient { stream: S, } -// https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-4.1 impl AgentClient { /// Connect to an SSH agent via the provided stream (on Unix, usually a Unix-domain socket). pub fn connect(stream: S) -> Self { AgentClient { stream } } + + /// Get the agent PID. + pub fn pid(&self) -> Option { + std::env::var("SSH_AGENT_PID") + .ok() + .and_then(|v| u32::from_str(&v).ok()) + } } pub trait ClientStream: Sized + Send + Sync { @@ -76,7 +83,7 @@ pub trait ClientStream: Sized + Send + Sync { Err(Error::Io(io_err)) if io_err.kind() == std::io::ErrorKind::NotFound => { Err(Error::BadAuthSock) } - err => err, + other => other, } } }