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}