Skip to main content

regent_sdk/hosts/
privilege.rs

1//! Privilege escalation and credentials
2//!
3//! This module provides types for specifying privilege levels and credentials
4//! for command execution on managed hosts.
5
6use serde::{Deserialize, Serialize};
7
8use crate::secrets::SecretReference;
9
10/// Specifies the privilege level for command execution.
11///
12/// This enum determines how commands are executed on the target host,
13/// including whether privilege escalation is used.
14///
15/// # Variants
16///
17/// - `None`: Execute as the currently authenticated user
18/// - `WithSudo`: Execute with `sudo` for root privileges
19/// - `WithSudoRs`: Execute with `sudo-rs` for root privileges
20///
21/// # Example
22///
23/// ```no_run
24/// use regent_sdk::Privilege;
25///
26/// // Execute as current user
27/// let privilege = Privilege::None;
28///
29/// // Execute with sudo
30/// let privilege = Privilege::WithSudo;
31///
32/// // Execute with sudo-rs
33/// let privilege = Privilege::WithSudoRs;
34/// ```
35#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
36pub enum Privilege {
37    /// Run command as the current authenticated user (no privilege escalation).
38    None,
39    // /// Run cmd as another user using su
40    // WithSuAsUser(Credentials),
41    /// Run command with sudo for root privileges.
42    WithSudo,
43    // /// Run cmd as another user using sudo
44    // WithSudoAsUser(Credentials),
45    /// Run command with sudo-rs for root privileges.
46    WithSudoRs,
47    // /// Run cmd as another user using sudo-rs
48    // WithSudoRsAsUser(Credentials),
49}
50
51/// User credentials for authentication.
52///
53/// Contains username and password for authenticating to a host.
54///
55/// # Example
56///
57/// ```no_run
58/// use regent_sdk::hosts::privilege::Credentials;
59///
60/// let creds = Credentials::from("admin", "secret_password");
61/// assert_eq!(creds.username(), "admin");
62/// assert_eq!(creds.password(), "secret_password");
63/// ```
64#[derive(Clone, PartialEq, Serialize, Deserialize)]
65#[serde(rename_all = "PascalCase")]
66pub struct Credentials {
67    /// The username for authentication.
68    username: String,
69    /// The password for authentication.
70    password: String,
71}
72
73impl std::fmt::Debug for Credentials {
74    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75        f.debug_struct("Credentials")
76            .field("username", &self.username)
77            .field("password", &format_args!("*REDACTED*"))
78            .finish()
79    }
80}
81
82impl Credentials {
83    /// Create new credentials from username and password.
84    ///
85    /// # Example
86    ///
87    /// ```no_run
88    /// use regent_sdk::hosts::privilege::Credentials;
89    ///
90    /// let creds = Credentials::from("admin", "password123");
91    /// ```
92    pub fn from(username: &str, password: &str) -> Credentials {
93        Credentials {
94            username: username.to_string(),
95            password: password.to_string(),
96        }
97    }
98
99    /// Get the username.
100    pub fn username(&self) -> &str {
101        &self.username
102    }
103
104    /// Get the password.
105    ///
106    /// **Warning**: Be cautious with this method as it exposes the password in plain text.
107    pub fn password(&self) -> &str {
108        &self.password
109    }
110}
111
112/// SSH login key for authentication.
113///
114/// Contains username and SSH private key for authenticating to a host via SSH.
115///
116/// # Example
117///
118/// ```no_run
119/// use regent_sdk::hosts::privilege::LoginKey;
120///
121/// let login_key = LoginKey::from(
122///     "admin".to_string(),
123///     "-----BEGIN RSA PRIVATE KEY-----\n...".to_string()
124/// );
125/// assert_eq!(login_key.username(), "admin");
126/// ```
127#[derive(Debug, Clone, Serialize, Deserialize)]
128#[serde(rename_all = "PascalCase")]
129pub struct LoginKey {
130    /// The username for SSH authentication.
131    username: String,
132    /// The private key for SSH authentication.
133    key: String,
134}
135
136impl LoginKey {
137    /// Create a new login key from username and private key (PEM format expected)
138    ///
139    /// # Example
140    ///
141    /// ```no_run
142    /// use regent_sdk::hosts::privilege::LoginKey;
143    ///
144    /// let login_key = LoginKey::from("admin".to_string(), "private_key_pem".to_string());
145    /// ```
146    pub fn from(username: String, key: String) -> Self {
147        Self { username, key }
148    }
149
150    /// Get the username.
151    pub fn username(&self) -> &str {
152        &self.username
153    }
154
155    /// Get the private key.
156    ///
157    /// **Warning**: Be cautious with this method as it exposes the private key in plain text.
158    pub fn key(&self) -> &str {
159        &self.key
160    }
161}
162
163/// Reference to an SSH login key stored in a secret provider.
164///
165/// Unlike [`LoginKey`], this struct doesn't contain the actual private key,
166/// but rather a reference to where the key can be retrieved from a secret provider.
167///
168/// # Example
169///
170/// ```no_run
171/// use regent_sdk::hosts::privilege::LoginKeyRef;
172/// use regent_sdk::secrets::SecretReference;
173///
174/// let key_ref = SecretReference::from("ssh_key_path", Some("files".to_string()));
175/// let login_key_ref = LoginKeyRef::from("admin".to_string(), key_ref);
176/// assert_eq!(login_key_ref.username(), "admin");
177/// ```
178#[derive(Debug, Clone, Serialize, Deserialize)]
179#[serde(rename_all = "PascalCase")]
180#[serde(deny_unknown_fields)]
181pub struct LoginKeyRef {
182    /// The username for SSH authentication.
183    username: String,
184    /// Reference to the secret containing the SSH private key.
185    key: SecretReference,
186}
187
188impl LoginKeyRef {
189    /// Create a new login key reference from username and secret reference.
190    ///
191    /// # Example
192    ///
193    /// ```no_run
194    /// use regent_sdk::hosts::privilege::LoginKeyRef;
195    /// use regent_sdk::secrets::SecretReference;
196    ///
197    /// let key_ref = SecretReference::from("my_ssh_key", Some("vault".to_string()));
198    /// let login_key_ref = LoginKeyRef::from("admin".to_string(), key_ref);
199    /// ```
200    pub fn from(username: String, key: SecretReference) -> Self {
201        Self { username, key }
202    }
203
204    /// Get the username.
205    pub fn username(&self) -> &str {
206        &self.username
207    }
208
209    /// Get the secret reference for the SSH key.
210    pub fn key_ref(&self) -> &SecretReference {
211        &self.key
212    }
213}