cli: `rad self` improvements

* Add `--home` flag
* Organize the information better

Now looks like this:

    DID             did🔑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
This commit is contained in:
Alexis Sellier 2023-06-30 14:02:44 +02:00
parent 613e3e5269
commit 0f3212a1b2
No known key found for this signature in database
6 changed files with 62 additions and 28 deletions

View File

@ -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
```

View File

@ -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
```

View File

@ -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())
);

View File

@ -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();

View File

@ -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]));

View File

@ -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<S> {
stream: S,
}
// https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-4.1
impl<S> AgentClient<S> {
/// 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<u32> {
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,
}
}
}