auths_cli/adapters/
agent.rs1#[cfg(unix)]
8use auths_core::agent::{AgentStatus, add_identity, agent_sign, check_agent_status};
9#[cfg(unix)]
10use auths_core::crypto::ssh::{construct_sshsig_pem, construct_sshsig_signed_data};
11use auths_sdk::ports::agent::{AgentSigningError, AgentSigningPort};
12
13#[cfg(unix)]
14use crate::commands::agent::{ensure_agent_running, get_default_socket_path};
15
16#[cfg(unix)]
27pub struct CliAgentAdapter;
28
29#[cfg(unix)]
30impl AgentSigningPort for CliAgentAdapter {
31 fn try_sign(
32 &self,
33 namespace: &str,
34 pubkey: &[u8],
35 data: &[u8],
36 ) -> Result<String, AgentSigningError> {
37 if pubkey.len() != 32 {
38 return Err(AgentSigningError::Unavailable(
39 "no public key available for agent signing".into(),
40 ));
41 }
42
43 let socket_path =
44 get_default_socket_path().map_err(|e| AgentSigningError::Unavailable(e.to_string()))?;
45
46 match check_agent_status(&socket_path) {
47 AgentStatus::Running { key_count } if key_count > 0 => {}
48 AgentStatus::Running { .. } => {
49 return Err(AgentSigningError::Unavailable(
50 "agent running but no keys loaded".into(),
51 ));
52 }
53 AgentStatus::ConnectionFailed => {
54 return Err(AgentSigningError::ConnectionFailed(
55 "agent socket unreachable".into(),
56 ));
57 }
58 AgentStatus::NotRunning => {
59 return Err(AgentSigningError::Unavailable("agent not running".into()));
60 }
61 }
62
63 let sig_data = construct_sshsig_signed_data(data, namespace)
64 .map_err(|e| AgentSigningError::SigningFailed(e.to_string()))?;
65
66 let raw_sig = agent_sign(&socket_path, pubkey, &sig_data)
67 .map_err(|e| AgentSigningError::SigningFailed(e.to_string()))?;
68
69 construct_sshsig_pem(pubkey, &raw_sig, namespace)
70 .map_err(|e| AgentSigningError::SigningFailed(e.to_string()))
71 }
72
73 fn ensure_running(&self) -> Result<(), AgentSigningError> {
74 ensure_agent_running(true)
75 .map(|_| ())
76 .map_err(|e| AgentSigningError::StartupFailed(e.to_string()))
77 }
78
79 fn add_identity(&self, _namespace: &str, pkcs8_der: &[u8]) -> Result<(), AgentSigningError> {
80 let socket_path = get_default_socket_path()
81 .map_err(|e| AgentSigningError::ConnectionFailed(e.to_string()))?;
82
83 add_identity(&socket_path, pkcs8_der)
84 .map(|_| ())
85 .map_err(|e| AgentSigningError::SigningFailed(e.to_string()))
86 }
87}