Skip to content

Commit 67f797f

Browse files
committed
Generalize traversing a Clevis config
Retain laziness in traversing the structure and early exit on error. Signed-off-by: mulhern <amulhern@redhat.com>
1 parent fd48484 commit 67f797f

1 file changed

Lines changed: 53 additions & 22 deletions

File tree

src/engine/strat_engine/crypt/shared.rs

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -204,14 +204,17 @@ pub fn clevis_info_from_metadata(
204204
pin_dispatch(&subjson, CLEVIS_RECURSION_LIMIT).map(Some)
205205
}
206206

207-
/// Returns true if the Tang config has a thumbprint or an advertisement
208-
/// or all Tang configs in the nested sss config have thumbprints or
209-
/// advertisements.
210-
fn all_tang_configs_have_url_trust_info(
207+
fn traverse_clevis_config<T>(
211208
pin: &str,
212209
clevis_config: &Value,
213210
recursion_limit: u64,
214-
) -> StratisResult<bool> {
211+
tang_func: &dyn Fn(&Map<String, Value>) -> StratisResult<T>,
212+
tpm2_func: &dyn Fn(&Map<String, Value>) -> StratisResult<T>,
213+
sss: &mut (&T, &mut dyn FnMut(T, T) -> StratisResult<T>),
214+
) -> StratisResult<T>
215+
where
216+
T: Clone,
217+
{
215218
if recursion_limit == 0 {
216219
return Err(StratisError::Msg(
217220
"Reached the recursion limit for parsing nested SSS tokens".to_string(),
@@ -220,14 +223,7 @@ fn all_tang_configs_have_url_trust_info(
220223

221224
if pin == "tang" {
222225
if let Some(obj) = clevis_config.as_object() {
223-
Ok(obj
224-
.get("thp")
225-
.map(|val| val.as_str().is_some())
226-
.or_else(|| {
227-
obj.get("adv")
228-
.map(|val| val.as_str().is_some() || val.as_object().is_some())
229-
})
230-
.unwrap_or(false))
226+
tang_func(obj)
231227
} else {
232228
Err(StratisError::Msg(format!(
233229
"configuration for Clevis is is not in JSON object format: {clevis_config}"
@@ -236,14 +232,16 @@ fn all_tang_configs_have_url_trust_info(
236232
} else if pin == "sss" {
237233
if let Some(obj) = clevis_config.as_object() {
238234
if let Some(obj) = obj.get("pins").and_then(|val| val.as_object()) {
239-
obj.iter().try_fold(true, |b, (pin, config)| {
240-
Ok(
241-
b && all_tang_configs_have_url_trust_info(
242-
pin,
243-
config,
244-
recursion_limit - 1,
245-
)?,
246-
)
235+
obj.iter().try_fold(sss.0.clone(), |acc, (pin, config)| {
236+
let res = traverse_clevis_config(
237+
pin,
238+
config,
239+
recursion_limit - 1,
240+
tang_func,
241+
tpm2_func,
242+
sss,
243+
)?;
244+
sss.1(acc, res)
247245
})
248246
} else {
249247
Err(StratisError::Msg(
@@ -256,12 +254,45 @@ fn all_tang_configs_have_url_trust_info(
256254
)))
257255
}
258256
} else if pin == "tpm2" {
259-
Ok(true)
257+
if let Some(obj) = clevis_config.as_object() {
258+
tpm2_func(obj)
259+
} else {
260+
Err(StratisError::Msg(format!(
261+
"configuration for Clevis is is not in JSON object format: {clevis_config}"
262+
)))
263+
}
260264
} else {
261265
Err(StratisError::Msg(format!("Unrecognized pin {pin}")))
262266
}
263267
}
264268

269+
/// Returns true if the Tang config has a thumbprint or an advertisement
270+
/// or all Tang configs in the nested sss config have thumbprints or
271+
/// advertisements.
272+
fn all_tang_configs_have_url_trust_info(
273+
pin: &str,
274+
clevis_config: &Value,
275+
recursion_limit: u64,
276+
) -> StratisResult<bool> {
277+
traverse_clevis_config(
278+
pin,
279+
clevis_config,
280+
recursion_limit,
281+
&|obj| {
282+
Ok(obj
283+
.get("thp")
284+
.map(|val| val.as_str().is_some())
285+
.or_else(|| {
286+
obj.get("adv")
287+
.map(|val| val.as_str().is_some() || val.as_object().is_some())
288+
})
289+
.unwrap_or(false))
290+
},
291+
&|_| Ok(true),
292+
&mut (&true, &mut |acc, premise| Ok(acc && premise)),
293+
)
294+
}
295+
265296
/// Interpret non-Clevis keys that may contain additional information about
266297
/// how to configure Clevis when binding. Remove any expected non-Clevis keys
267298
/// from the configuration.

0 commit comments

Comments
 (0)