git.delta.rocks / fleet / refs/commits / faec7071817b

difftreelog

source

crates/fleet-base/src/secret.rs2.5 KiBsourcehistory
1use std::collections::{BTreeMap, BTreeSet};23use chrono::{DateTime, Utc};45use crate::fleetdata::{Expectations, FleetSecretData, FleetSecretDistribution, GeneratorPart};67#[derive(thiserror::Error, Debug)]8pub enum RegenerationReason {9	#[error("owners added: {0:?}")]10	OwnersAdded(BTreeSet<String>),11	#[error("owners added: {0:?}")]12	OwnersRemoved(BTreeSet<String>),13	#[error("unexpected generation data, expected: {expected:?}, found: {found:?}")]14	GenerationData {15		expected: serde_json::Value,16		found: serde_json::Value,17	},18	#[error("unexpected part list, expected: {expected:?}, found: {found:?}")]19	PartList {20		expected: BTreeSet<String>,21		found: BTreeSet<String>,22	},23	#[error("part {0} is expected to be encrypted")]24	ExpectedPrivate(String),25	#[error("part {0} is not expected to be encrypted")]26	ExpectedPublic(String),27	#[error("secret is expired at {0}")]28	Expired(DateTime<Utc>),2930	#[error("secret is not generated for this host")]31	Missing,32}3334pub fn secret_needs_regeneration(35	secret: &FleetSecretDistribution,36	expectations: &Expectations,37) -> Option<RegenerationReason> {38	let added: BTreeSet<String> = expectations39		.owners40		.difference(&secret.owners)41		.cloned()42		.collect();43	if !added.is_empty() {44		return Some(RegenerationReason::OwnersAdded(added));45	}4647	let removed: BTreeSet<String> = secret48		.owners49		.difference(&expectations.owners)50		.cloned()51		.collect();52	if !removed.is_empty() {53		return Some(RegenerationReason::OwnersRemoved(removed));54	}5556	if secret.secret.generation_data != expectations.generation_data {57		return Some(RegenerationReason::GenerationData {58			expected: expectations.generation_data.clone(),59			found: secret.secret.generation_data.clone(),60		});61	}6263	let expected: BTreeSet<String> = expectations.parts.keys().cloned().collect();64	let found: BTreeSet<String> = secret.secret.parts.keys().cloned().collect();6566	if found != expected {67		return Some(RegenerationReason::PartList { expected, found });68	}6970	for (name, value) in secret.secret.parts.iter() {71		let expectation = expectations72			.parts73			.get(name)74			.expect("found == expected checked");75		if value.raw.encrypted {76			if !expectation.encrypted {77				return Some(RegenerationReason::ExpectedPrivate(name.clone()));78			}79		} else if expectation.encrypted {80			return Some(RegenerationReason::ExpectedPublic(name.clone()));81		}82	}8384	if let Some(expiration) = secret.secret.expires_at {85		// TODO: Leeway?86		if expiration < Utc::now() {87			return Some(RegenerationReason::Expired(expiration));88		}89	}9091	None92}