difftreelog
feat support secrets without secret data
in: trunk
4 files changed
cmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/secrets/mod.rs
+++ b/cmds/fleet/src/cmds/secrets/mod.rs
@@ -70,17 +70,21 @@
let mut input = vec![];
io::stdin().read_to_end(&mut input)?;
- let mut encrypted = vec![];
- let recipients = recipients
- .iter()
- .cloned()
- .map(|r| Box::new(r) as Box<dyn age::Recipient>)
- .collect();
- let mut encryptor =
- age::Encryptor::with_recipients(recipients).wrap_output(&mut encrypted)?;
- io::copy(&mut Cursor::new(input), &mut encryptor)?;
- encryptor.finish()?;
- encrypted
+ if input.is_empty() {
+ input
+ } else {
+ let mut encrypted = vec![];
+ let recipients = recipients
+ .iter()
+ .cloned()
+ .map(|r| Box::new(r) as Box<dyn age::Recipient>)
+ .collect();
+ let mut encryptor = age::Encryptor::with_recipients(recipients)
+ .wrap_output(&mut encrypted)?;
+ io::copy(&mut Cursor::new(input), &mut encryptor)?;
+ encryptor.finish()?;
+ encrypted
+ }
};
let mut data = config.data_mut();
cmds/fleet/src/fleetdata.rsdiffbeforeafterboth--- a/cmds/fleet/src/fleetdata.rs
+++ b/cmds/fleet/src/fleetdata.rs
@@ -39,7 +39,12 @@
pub expire_at: Option<DateTime<Utc>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub public: Option<String>,
- #[serde(serialize_with = "as_z85", deserialize_with = "from_z85")]
+ #[serde(
+ default,
+ skip_serializing_if = "Vec::is_empty",
+ serialize_with = "as_z85",
+ deserialize_with = "from_z85"
+ )]
pub secret: Vec<u8>,
}
cmds/install-secrets/src/main.rsdiffbeforeafterboth--- a/cmds/install-secrets/src/main.rs
+++ b/cmds/install-secrets/src/main.rs
@@ -29,16 +29,21 @@
mode: String,
owner: String,
#[serde(deserialize_with = "from_z85")]
- secret: Vec<u8>,
+ secret: Option<Vec<u8>>,
}
-fn from_z85<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
+fn from_z85<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error;
- String::deserialize(deserializer)
- .and_then(|string| z85::decode(&string).map_err(|err| Error::custom(err.to_string())))
+ if let Some(v) = <Option<String>>::deserialize(deserializer)? {
+ Ok(Some(
+ z85::decode(&v).map_err(|err| Error::custom(err.to_string()))?,
+ ))
+ } else {
+ Ok(None)
+ }
}
type Data = HashMap<String, DataItem>;
@@ -49,6 +54,11 @@
name: &str,
value: DataItem,
) -> Result<()> {
+ if value.secret.is_none() {
+ return Ok(());
+ }
+ let secret = value.secret.as_ref().unwrap();
+
let mut path = dir.to_path_buf();
path.push(name);
if path.strip_prefix(&dir).is_err() {
@@ -88,7 +98,7 @@
// File is owned by root, and only root can modify it
let decrypted = {
- let mut input = Cursor::new(&value.secret);
+ let mut input = Cursor::new(&secret);
let decryptor = Decryptor::new(&mut input).context("failed to init decryptor")?;
let decryptor = match decryptor {
Decryptor::Recipients(r) => r,
modules/nixos/secrets.nixdiffbeforeafterboth1{ lib, config, pkgs, ... }: with lib;2let3 sysConfig = config;4 secretType = types.submodule ({ config, ... }: {5 config = {6 path = mkOptionDefault "/run/secrets/${config._module.args.name}";7 };8 options = {9 public = mkOption {10 type = types.nullOr types.str;11 description = "Secret public data";12 default = null;13 };14 secret = mkOption {15 type = types.str;16 description = "Encrypted secret data";17 };18 mode = mkOption {19 type = types.str;20 description = "Secret mode";21 default = "0440";22 };23 owner = mkOption {24 type = types.str;25 description = "Owner of the secret";26 default = "root";27 };28 group = mkOption {29 type = types.str;30 description = "Group of the secret";31 default = sysConfig.users.users.${config.owner}.group;32 };3334 path = mkOption {35 type = types.str;36 readOnly = true;37 description = "Path to the decrypted secret";38 };39 };40 });41 secretsFile = pkgs.writeTextFile {42 name = "secrets.json";43 text = builtins.toJSON config.secrets;44 };45in46{47 options = {48 secrets = mkOption {49 type = types.attrsOf secretType;50 default = { };51 description = "Host-local secrets";52 };53 };54 config = {55 system.activationScripts.decryptSecrets = ''56 1>&2 echo "setting up secrets"57 ${pkgs.fleet-install-secrets}/bin/fleet-install-secrets ${secretsFile}58 '';59 };60}1{ lib, config, pkgs, ... }: with lib;2let3 sysConfig = config;4 secretType = types.submodule ({ config, ... }: {5 config = {6 path = mkOptionDefault (if config.secret == null then (error "secret is not set") else "/run/secrets/${config._module.args.name}");7 publicPath = mkOptionDefault (pkgs.writeText "pub-${config._module.args.name}" config.public);8 secret = mkIf (config.public != null) "";9 };10 options = {11 public = mkOption {12 type = types.nullOr types.str;13 description = "Secret public data";14 default = null;15 };16 secret = mkOption {17 type = types.nullOr types.str;18 description = "Encrypted secret data";19 };20 mode = mkOption {21 type = types.str;22 description = "Secret mode";23 default = "0440";24 };25 owner = mkOption {26 type = types.str;27 description = "Owner of the secret";28 default = "root";29 };30 group = mkOption {31 type = types.str;32 description = "Group of the secret";33 default = sysConfig.users.users.${config.owner}.group;34 };3536 path = mkOption {37 type = types.str;38 readOnly = true;39 description = "Path to the decrypted secret";40 };41 publicPath = mkOption {42 type = types.package;43 readOnly = true;44 description = "Path to the public part of secret";45 };46 };47 });48 secretsFile = pkgs.writeTextFile {49 name = "secrets.json";50 text = builtins.toJSON config.secrets;51 };52in53{54 options = {55 secrets = mkOption {56 type = types.attrsOf secretType;57 default = { };58 description = "Host-local secrets";59 };60 };61 config = {62 system.activationScripts.decryptSecrets = ''63 1>&2 echo "setting up secrets"64 ${pkgs.fleet-install-secrets}/bin/fleet-install-secrets ${secretsFile}65 '';66 };67}