1use std::collections::BTreeSet;
13
14use crate::error::{Error, Result};
15use crate::value::Value;
16
17pub const SECRET_MARKER: &str = "***SECRET***";
19
20pub fn from_active_value(value: &active_core::Value) -> Value {
25 use active_core::Value as ActiveValue;
26 match value {
27 ActiveValue::Null => Value::Null,
28 ActiveValue::Bool(flag) => Value::Bool(*flag),
29 ActiveValue::Int(number) => Value::Int(*number),
30 ActiveValue::Float(number) => Value::Float(*number),
31 ActiveValue::String(text) => Value::Text(text.clone()),
32 ActiveValue::DurationMs(ms) => Value::Map(
33 [("ms".to_string(), Value::Int(*ms as i64))]
34 .into_iter()
35 .collect(),
36 ),
37 ActiveValue::Quantity(amount, unit) => Value::Map(
38 [
39 ("value".to_string(), Value::Float(*amount)),
40 ("unit".to_string(), Value::Text(unit.suffix())),
41 ]
42 .into_iter()
43 .collect(),
44 ),
45 ActiveValue::Array(items) => Value::List(items.iter().map(from_active_value).collect()),
46 ActiveValue::Table(entries) => Value::Map(
47 entries
48 .iter()
49 .map(|(key, value)| (key.clone(), from_active_value(value)))
50 .collect(),
51 ),
52 ActiveValue::Secret(_) => Value::Secret,
53 }
54}
55
56pub fn redact_cone_labels(labels: Vec<String>, tainted: &BTreeSet<String>) -> Vec<String> {
61 if labels.iter().any(|label| tainted.contains(label)) {
62 vec![SECRET_MARKER.to_string()]
63 } else {
64 labels
65 }
66}
67
68pub fn redact_value(value: Value) -> Value {
72 match value {
73 Value::Secret => Value::Secret,
74 Value::List(items) => Value::List(items.into_iter().map(redact_value).collect()),
75 Value::Map(entries) => Value::Map(
76 entries
77 .into_iter()
78 .map(|(key, value)| (key, redact_value(value)))
79 .collect(),
80 ),
81 Value::Text(text) if text.contains(SECRET_MARKER) => Value::Secret,
82 other => other,
83 }
84}
85
86pub fn check_module_payload(bytes: &[u8]) -> Result<()> {
89 active_infinity::validate(bytes)
90 .map(|_| ())
91 .map_err(|error| Error::Payload(error.code().to_string()))
92}
93
94pub fn assert_no_secret_material(value: &Value) -> Result<()> {
102 match value {
103 Value::Secret => Err(Error::Provider {
104 code: "rpc/secret-material".to_string(),
105 }),
106 Value::List(items) => items.iter().try_for_each(assert_no_secret_material),
107 Value::Map(entries) => entries.values().try_for_each(assert_no_secret_material),
108 _ => Ok(()),
109 }
110}