Skip to content

Commit 861baa3

Browse files
committed
implement secret function to use extensions
1 parent c81a939 commit 861baa3

File tree

2 files changed

+54
-10
lines changed

2 files changed

+54
-10
lines changed

dsc_lib/src/extensions/dscextension.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use schemars::JsonSchema;
88
use std::{fmt::Display, path::Path};
99
use tracing::{debug, info, trace};
1010

11-
use crate::{discovery::command_discovery::{load_manifest, ImportedManifest}, dscerror::DscError, dscresources::{command_resource::{invoke_command, process_args}, dscresource::DscResource}};
11+
use crate::{discovery::command_discovery::{load_manifest, ImportedManifest}, dscerror::DscError, dscresources::{command_resource::{invoke_command, process_args}, dscresource::DscResource}, extensions::secret::SecretResult};
1212

1313
use super::{discover::DiscoverResult, extension_manifest::ExtensionManifest, secret::SecretArgKind};
1414

@@ -129,7 +129,21 @@ impl DscExtension {
129129
}
130130
}
131131

132-
pub fn secret(&self, name: &str, vault: Option<&str>) -> Result<Value, DscError> {
132+
/// Retrieve a secret using the extension.
133+
///
134+
/// # Arguments
135+
///
136+
/// * `name` - The name of the secret to retrieve.
137+
/// * `vault` - An optional vault name to use for the secret.
138+
///
139+
/// # Returns
140+
///
141+
/// A result containing the secret as a string or an error.
142+
///
143+
/// # Errors
144+
///
145+
/// This function will return an error if the secret retrieval fails or if the extension does not support the secret capability.
146+
pub fn secret(&self, name: &str, vault: Option<&str>) -> Result<Option<String>, DscError> {
133147
if self.capabilities.contains(&Capability::Secret) {
134148
let extension = match serde_json::from_value::<ExtensionManifest>(self.manifest.clone()) {
135149
Ok(manifest) => manifest,
@@ -151,12 +165,15 @@ impl DscExtension {
151165
)?;
152166
if stdout.is_empty() {
153167
info!("{}", t!("extensions.dscextension.secretNoResults", extension = self.type_name));
154-
Ok(Value::Null)
168+
Ok(None)
155169
} else {
156-
match serde_json::from_str(&stdout) {
157-
Ok(value) => Ok(value),
158-
Err(err) => Err(DscError::Json(err)),
159-
}
170+
let result: SecretResult = match serde_json::from_str(&stdout) {
171+
Ok(value) => value,
172+
Err(err) => {
173+
return Err(DscError::Json(err));
174+
}
175+
};
176+
Ok(Some(result.secret))
160177
}
161178
} else {
162179
Err(DscError::UnsupportedCapability(

dsc_lib/src/functions/secret.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
use crate::DscError;
55
use crate::configure::context::Context;
6+
use crate::extensions::Capability;
67
use crate::functions::AcceptedArgKind;
78
use serde_json::Value;
89
use super::Function;
10+
use tracing::warn;
911

1012
#[derive(Debug, Default)]
1113
pub struct Secret {}
@@ -24,18 +26,43 @@ impl Function for Secret {
2426
}
2527

2628
fn invoke(&self, args: &[Value], context: &Context) -> Result<Value, DscError> {
27-
let secret = args[0].as_str().ok_or_else(|| {
29+
let secret_name = args[0].as_str().ok_or_else(|| {
2830
DscError::InvalidArgumentType("Secret function requires a string argument".to_string())
2931
})?.to_string();
30-
let vault: Option<String> = if args.len() > 1 {
32+
let vault_name: Option<String> = if args.len() > 1 {
3133
args[1].as_str().map(|s| s.to_string())
3234
} else {
3335
None
3436
};
3537

3638
// if no vault name is provided, we query all extensions supporting the secret method
3739
// to see if any of them can provide the secret. If none can or if multiple can, we return an error.
38-
40+
let extensions = context.extensions();
41+
let mut secret_returned = false;
42+
let mut result: String = String::new();
43+
for extension in extensions {
44+
if extension.capabilities().contains(&Capability::Secret) {
45+
match extension.secret(&secret_name, vault_name.as_deref()) {
46+
Ok(result) => {
47+
if secret_returned {
48+
return Err(DscError::MultipleSecretsFound(secret_name.clone()));
49+
}
50+
if let Some(secret_value) = result {
51+
result = secret_value;
52+
secret_returned = true;
53+
}
54+
},
55+
Err(err) => {
56+
warn!("Error occurred while retrieving secret from extension {}: {}", extension.type_name(), err);
57+
}
58+
}
59+
}
60+
}
61+
if !secret_returned {
62+
Err(DscError::SecretNotFound(secret_name))
63+
} else {
64+
Ok(Value::String(result))
65+
}
3966
}
4067
}
4168

0 commit comments

Comments
 (0)