cuenv_core/secrets/
mod.rs1use crate::{Error, Result};
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::collections::HashMap;
9use tokio::process::Command;
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
13pub struct ExecResolver {
14 pub command: String,
16
17 pub args: Vec<String>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
24pub struct Secret {
25 pub resolver: String,
27
28 pub command: String,
30
31 #[serde(default)]
33 pub args: Vec<String>,
34
35 #[serde(flatten)]
37 pub extra: HashMap<String, Value>,
38}
39
40impl Secret {
41 pub fn new(command: String, args: Vec<String>) -> Self {
43 Secret {
44 resolver: "exec".to_string(),
45 command,
46 args,
47 extra: HashMap::new(),
48 }
49 }
50
51 pub fn with_extra(command: String, args: Vec<String>, extra: HashMap<String, Value>) -> Self {
53 Secret {
54 resolver: "exec".to_string(),
55 command,
56 args,
57 extra,
58 }
59 }
60
61 pub async fn resolve(&self) -> Result<String> {
63 match self.resolver.as_str() {
64 "exec" => {
65 let output = Command::new(&self.command)
66 .args(&self.args)
67 .output()
68 .await
69 .map_err(|e| {
70 Error::configuration(format!(
71 "Failed to execute secret resolver command '{}': {}",
72 self.command, e
73 ))
74 })?;
75
76 if !output.status.success() {
77 let stderr = String::from_utf8_lossy(&output.stderr);
78 return Err(Error::configuration(format!(
79 "Secret resolver command '{}' failed: {}",
80 self.command, stderr
81 )));
82 }
83
84 let stdout = String::from_utf8_lossy(&output.stdout);
85 Ok(stdout.trim().to_string())
86 }
87 other => Err(Error::configuration(format!(
88 "Unsupported secret resolver: {}",
89 other
90 ))),
91 }
92 }
93}