git.delta.rocks / jrsonnet / refs/commits / 33f3601e24db

difftreelog

source

crates/fleet-base/src/primops.rs3.2 KiBsourcehistory
1use std::cell::OnceCell;2use std::collections::{BTreeMap, HashMap};3use std::sync::{Arc, Mutex, OnceLock};45use anyhow::{Context, bail};6use itertools::Itertools;7use nix_eval::{NativeFn, Value, nix_go, nix_go_json};8use serde::Deserialize;9use tracing::{info, warn};1011use crate::fleetdata::{FleetData, FleetSecrets};12use crate::host::Config;1314#[derive(thiserror::Error, Debug)]15enum Error {}1617struct Parts {18	encrypted: Vec<String>,19	public: Vec<String>,20}2122trait SecretsBackend {23	fn has_shared(&self, name: &str);24	fn has_host(&self, host: &str, name: &str);25	fn shared_parts(&self, name: &str) -> Parts;26	fn host_parts(&self, host: &str, name: &str) -> Parts;27}2829struct FsSecretsBackend {}3031pub static PRIMOPS_DATA: OnceLock<Config> = OnceLock::new();3233#[derive(Deserialize, Debug)]34struct GeneratorPart {35	encrypted: bool,36}3738pub fn init_primops() {39	info!("initializing primops");40	NativeFn::new(41		c"__fleetEnsureHostSecret",42		c"Ensure secret existence for a host, regenerating it in case of some mismatch",43		[c"host", c"secret", c"generator"],44		|es, [host, secret, generator]| {45			info!("get host");46			let host = host.to_string()?;47			info!("get secret");48			let secret = secret.to_string()?;4950			info!("get config");51			let config = PRIMOPS_DATA52				.get()53				.expect("primops data should be set on init");5455			info!("get pkgs");56			let nixpkgs = &config.nixpkgs;57			let default_pkgs = &config.default_pkgs;58			let default_mk_secret_generators = nix_go!(default_pkgs.mkSecretGenerators);59			let generators = nix_go!(default_mk_secret_generators(Obj {60				recipients: <Vec<String>>::new(),61			}));62			let pkgs_and_generators = default_pkgs.clone().attrs_update(generators)?;6364			info!("call package");65			let call_package = nix_go!(nixpkgs.lib.callPackageWith(pkgs_and_generators));66			let default_generator = call_package67				.call(generator.clone())68				.context("calling callPackage with generator")?69				.call(Value::new_attrs(HashMap::new()))70				.context("providing extra callPackage args")?;7172			info!("get parts");73			let mut parts: BTreeMap<String, GeneratorPart> = nix_go_json!(default_generator.parts);74			info!("got parts: {parts:?}");7576			let Some(existing) = config77				.host_secret(&host, &secret) else {78				bail!("missing secret {secret} for host {host}; secret needs regeneration")79			};8081			info!("got existing: {existing:?}");8283			let mut out = HashMap::new();8485			for (part_name, part) in &existing.secret.parts {86				let Some(definition) = parts.remove(part_name) else {87					warn!("secret {secret} part {part_name} is stored, but not defined in nixos config, it will not be passed to nix");88					continue;89				};90				if definition.encrypted != part.raw.encrypted {91					bail!("secret {secret} part {part_name} is supposed to be {}, but it is {}; secret needs regeneration", if definition.encrypted {"encrypted"} else {"unencrypted"}, if part.raw.encrypted {"encrypted"} else {"unencrypted"});92				}93				out.insert(part_name.as_str(), Value::new_attrs(HashMap::from_iter([("raw", Value::new_str(&part.raw.to_string()))])));94			}95			if !parts.is_empty(){96				let defs = parts.keys().collect_vec();97				bail!("secret parts are defined, but not stored: {defs:?}, secret needs regeneration")98			}99100			Ok(Value::new_attrs(out))101		},102	)103	.register();104}