Skip to main content

getmyid/
lib.rs

1//! # getmyid
2//!
3//! A Rust client library for the [whoami](https://github.com/tanbal/whoami) Identity-by-PID daemon.
4//!
5//! This library provides both synchronous and asynchronous clients for querying process identity
6//! from the whoami daemon, which uses the Linux kernel's `SO_PEERCRED` mechanism to securely
7//! identify local processes.
8//!
9//! ## Features
10//!
11//! - **Synchronous client**: Default, no additional dependencies
12//! - **Asynchronous client**: Enable the `tokio` feature for async support
13//! - **Runner context**: Send client context that gets merged with server identity
14//! - **Builder pattern**: Flexible client configuration
15//! - **Type-safe**: Strongly typed identity and error types
16//!
17//! ## Quick Start
18//!
19//! ### Synchronous Usage
20//!
21//! ```no_run
22//! use getmyid::Client;
23//!
24//! fn main() -> Result<(), getmyid::GetMyIdError> {
25//!     let client = Client::new();
26//!     let identity = client.get_identity()?;
27//!     
28//!     println!("Identity: {}", identity.identity);
29//!     println!("IDM URL: {}", identity.idm_url);
30//!     println!("Config URL: {}", identity.config_url);
31//!     println!("Token: {}", identity.token);
32//!     println!("Hostname: {}", identity.runner.hostname);
33//!     println!("Process: {} (PID: {})", identity.runner.process, identity.runner.pid);
34//!     
35//!     Ok(())
36//! }
37//! ```
38//!
39//! ### With Runner Context (for dynamic configuration)
40//!
41//! ```no_run
42//! use getmyid::{Client, RunnerRequest};
43//!
44//! fn main() -> Result<(), getmyid::GetMyIdError> {
45//!     let client = Client::new();
46//!     
47//!     // Send context that will be merged with identity in runner object
48//!     let runner_req = RunnerRequest::new()
49//!         .with_instance_id(42)
50//!         .with_current_timestamp();
51//!     
52//!     let identity = client.get_identity_with_runner(Some(runner_req))?;
53//!     
54//!     // The runner object can be passed directly to a config server
55//!     println!("Runner: {:?}", identity.runner);
56//!     
57//!     Ok(())
58//! }
59//! ```
60//!
61//! ### Asynchronous Usage (requires `tokio` feature)
62//!
63//! ```no_run
64//! use getmyid::AsyncClient;
65//!
66//! #[tokio::main]
67//! async fn main() -> Result<(), getmyid::GetMyIdError> {
68//!     let client = AsyncClient::new();
69//!     let identity = client.get_identity().await?;
70//!     
71//!     println!("Identity: {}", identity.identity);
72//!     
73//!     Ok(())
74//! }
75//! ```
76//!
77//! ### Custom Socket Path
78//!
79//! ```no_run
80//! use std::time::Duration;
81//! use getmyid::Client;
82//!
83//! let client = Client::builder()
84//!     .socket_path("/tmp/whoami.sock")
85//!     .timeout(Duration::from_secs(10))
86//!     .build();
87//! ```
88//!
89//! ## How It Works
90//!
91//! 1. Your application connects to the whoami daemon's Unix Domain Socket
92//! 2. Optionally sends a runner request with client context (instance_id, timestamp, etc.)
93//! 3. The daemon uses `SO_PEERCRED` to get your process's PID, UID, and GID from the kernel
94//! 4. The daemon reads additional info from `/proc/[PID]/` (process name, executable path)
95//! 5. The daemon matches your identity against configured rules
96//! 6. Returns identity with a `runner` object containing merged client + server fields
97//!
98//! The `runner` object is designed to be passed directly to a config server, which can
99//! use both the verified identity and client-provided context to route configuration.
100//!
101//! This provides zero-trust authentication where applications don't need passwords -
102//! the Linux kernel vouches for their identity.
103
104#![warn(missing_docs)]
105#![warn(rustdoc::missing_crate_level_docs)]
106
107mod client;
108mod error;
109mod types;
110
111#[cfg(feature = "tokio")]
112mod async_client;
113
114// Re-export main types
115pub use client::{Client, ClientBuilder, DEFAULT_SOCKET_PATH, DEFAULT_TIMEOUT};
116pub use error::{GetMyIdError, Result};
117pub use types::{Identity, Runner, RunnerRequest};
118
119#[cfg(feature = "tokio")]
120pub use async_client::{AsyncClient, AsyncClientBuilder};
121
122/// Convenience function to get identity using default settings.
123///
124/// This is equivalent to `Client::new().get_identity()`.
125///
126/// # Example
127///
128/// ```no_run
129/// let identity = getmyid::get_identity()?;
130/// println!("Identity: {}", identity.identity);
131/// # Ok::<(), getmyid::GetMyIdError>(())
132/// ```
133pub fn get_identity() -> Result<Identity> {
134    Client::new().get_identity()
135}
136
137/// Convenience function to get identity using a custom socket path.
138///
139/// # Example
140///
141/// ```no_run
142/// let identity = getmyid::get_identity_from("/tmp/whoami.sock")?;
143/// println!("Identity: {}", identity.identity);
144/// # Ok::<(), getmyid::GetMyIdError>(())
145/// ```
146pub fn get_identity_from<P: AsRef<std::path::Path>>(socket_path: P) -> Result<Identity> {
147    Client::builder()
148        .socket_path(socket_path)
149        .build()
150        .get_identity()
151}