Allow disabling signature checking for testing

This commit is contained in:
Artemis Tosini 2024-07-16 19:46:40 +00:00
parent 0de55cce78
commit 78af1e1d88
Signed by: artemist
SSH key fingerprint: SHA256:w028LIB8Jqsri7H2uJ7RimKalF++o2LsV9iqq2QMpSE
6 changed files with 46 additions and 8 deletions

View file

@ -31,6 +31,8 @@ use crate::{
/// * NarHash must be sha256 /// * NarHash must be sha256
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct FetchAndUnpackNixSubstituter { pub struct FetchAndUnpackNixSubstituter {
/// Whether to require valid signatures when checking narinfo
require_sigs: bool,
/// Map from key name (e.g. cache.nixos.org-1) to parsed ed25519 key /// Map from key name (e.g. cache.nixos.org-1) to parsed ed25519 key
trusted_keys: HashMap<String, VerifyingKey>, trusted_keys: HashMap<String, VerifyingKey>,
/// Base URLs for substituters, e.g. https://cache.nixos.org/ /// Base URLs for substituters, e.g. https://cache.nixos.org/
@ -59,6 +61,7 @@ impl FetchAndUnpackNixSubstituter {
targets: Vec<PathBuf>, targets: Vec<PathBuf>,
dest: PathBuf, dest: PathBuf,
trusted_keys: Vec<String>, trusted_keys: Vec<String>,
require_sigs: bool,
substituters: Vec<Url>, substituters: Vec<Url>,
proxy: Option<Url>, proxy: Option<Url>,
ssl_cert_file: Option<PathBuf>, ssl_cert_file: Option<PathBuf>,
@ -86,7 +89,12 @@ impl FetchAndUnpackNixSubstituter {
.collect::<Result<Vec<_>, _>>() .collect::<Result<Vec<_>, _>>()
.map_err(Self::error)?; .map_err(Self::error)?;
if !require_sigs {
tracing::warn!("Signatures are not required during substitution. This is insecure.");
}
Ok(Self { Ok(Self {
require_sigs,
targets, targets,
trusted_keys: trusted_keys_parsed, trusted_keys: trusted_keys_parsed,
dest, dest,
@ -122,6 +130,7 @@ impl FetchAndUnpackNixSubstituter {
} }
let narinfo = NarInfo::parse_and_verify( let narinfo = NarInfo::parse_and_verify(
self.require_sigs,
&self.trusted_keys, &self.trusted_keys,
substituter, substituter,
&output, &output,
@ -458,7 +467,7 @@ struct NarInfo {
/// Other store paths referenced by the nar /// Other store paths referenced by the nar
pub references: Vec<StorePath>, pub references: Vec<StorePath>,
/// Signature of the nar, used to sign other items /// Signature of the nar, used to sign other items
pub sig: (String, Vec<u8>), pub sig: Option<(String, Vec<u8>)>,
} }
impl NarInfo { impl NarInfo {
@ -527,7 +536,7 @@ impl NarInfo {
nar_hash: nar_hash.ok_or_else(|| SubstitutionError::BadNarInfo)?, nar_hash: nar_hash.ok_or_else(|| SubstitutionError::BadNarInfo)?,
nar_size: nar_size.ok_or_else(|| SubstitutionError::BadNarInfo)?, nar_size: nar_size.ok_or_else(|| SubstitutionError::BadNarInfo)?,
references: references.ok_or_else(|| SubstitutionError::BadNarInfo)?, references: references.ok_or_else(|| SubstitutionError::BadNarInfo)?,
sig: sig.ok_or_else(|| SubstitutionError::BadNarInfo)?, sig,
}) })
} }
@ -535,7 +544,11 @@ impl NarInfo {
&self, &self,
trusted_keys: &HashMap<String, VerifyingKey>, trusted_keys: &HashMap<String, VerifyingKey>,
) -> Result<(), SubstitutionError> { ) -> Result<(), SubstitutionError> {
let Some(key) = trusted_keys.get(&self.sig.0) else { let Some(sig) = &self.sig else {
return Err(SubstitutionError::BadSignature);
};
let Some(key) = trusted_keys.get(&sig.0) else {
return Err(SubstitutionError::BadSignature); return Err(SubstitutionError::BadSignature);
}; };
@ -556,8 +569,7 @@ impl NarInfo {
key.verify_strict( key.verify_strict(
fingerprint.as_bytes(), fingerprint.as_bytes(),
&ed25519_dalek::Signature::from_bytes( &ed25519_dalek::Signature::from_bytes(
self.sig sig.1
.1
.as_slice() .as_slice()
.try_into() .try_into()
.map_err(|_| SubstitutionError::BadSignature)?, .map_err(|_| SubstitutionError::BadSignature)?,
@ -567,6 +579,7 @@ impl NarInfo {
} }
pub fn parse_and_verify( pub fn parse_and_verify(
require_sigs: bool,
trusted_keys: &HashMap<String, VerifyingKey>, trusted_keys: &HashMap<String, VerifyingKey>,
substituter_url: &Url, substituter_url: &Url,
expected_store_path: &StorePath, expected_store_path: &StorePath,
@ -578,7 +591,9 @@ impl NarInfo {
return Err(SubstitutionError::BadSignature); return Err(SubstitutionError::BadSignature);
} }
parsed.verify(trusted_keys)?; if require_sigs {
parsed.verify(trusted_keys)?;
}
Ok(parsed) Ok(parsed)
} }

View file

@ -62,6 +62,7 @@ impl ProvisionNix {
settings.substitution_targets.clone(), settings.substitution_targets.clone(),
PathBuf::from(SCRATCH_DIR), PathBuf::from(SCRATCH_DIR),
settings.substituter_trusted_keys.clone(), settings.substituter_trusted_keys.clone(),
settings.substituter_require_sigs,
settings.substituters.clone(), settings.substituters.clone(),
settings.proxy.clone(), settings.proxy.clone(),
settings.ssl_cert_file.clone(), settings.ssl_cert_file.clone(),

View file

@ -192,7 +192,7 @@ pub struct CommonSettings {
)] )]
pub substituter_trusted_keys: Vec<String>, pub substituter_trusted_keys: Vec<String>,
/// Output to download when use_substituters is set /// Store paths to download when use_substituters is set. Should include lix and cacert
#[cfg_attr( #[cfg_attr(
feature = "cli", feature = "cli",
clap(long, env = "NIX_INSTALLER_SUBSTITUTION_TARGETS",) clap(long, env = "NIX_INSTALLER_SUBSTITUTION_TARGETS",)
@ -223,6 +223,19 @@ pub struct CommonSettings {
)] )]
pub substitution_targets: Vec<PathBuf>, pub substitution_targets: Vec<PathBuf>,
/// Require trusted signatures when downloading from substituters
#[cfg_attr(
feature = "cli",
clap(
action(ArgAction::SetFalse),
default_value = "true",
global = true,
env = "NIX_INSTALLER_REQUIRE_SIGS",
long = "no-require-sigs"
)
)]
pub substituter_require_sigs: bool,
/// Download Lix from a substituter instead of an install tarball /// Download Lix from a substituter instead of an install tarball
#[cfg_attr(feature = "cli", clap(long, env = "NIX_INSTALLER_USE_SUBSTITUTER"))] #[cfg_attr(feature = "cli", clap(long, env = "NIX_INSTALLER_USE_SUBSTITUTER"))]
pub use_substituters: bool, pub use_substituters: bool,
@ -387,6 +400,7 @@ impl CommonSettings {
.iter() .iter()
.map(|s| PathBuf::from(*s)) .map(|s| PathBuf::from(*s))
.collect(), .collect(),
substituter_require_sigs: true,
use_substituters: false, use_substituters: false,
nix_package_url: url.parse()?, nix_package_url: url.parse()?,
proxy: Default::default(), proxy: Default::default(),
@ -409,6 +423,7 @@ impl CommonSettings {
substituters, substituters,
substituter_trusted_keys, substituter_trusted_keys,
substitution_targets, substitution_targets,
substituter_require_sigs,
use_substituters, use_substituters,
nix_package_url, nix_package_url,
proxy, proxy,
@ -443,7 +458,6 @@ impl CommonSettings {
"nix_build_user_count".into(), "nix_build_user_count".into(),
serde_json::to_value(nix_build_user_count)?, serde_json::to_value(nix_build_user_count)?,
); );
map.insert("substituters".into(), serde_json::to_value(substituters)?);
map.insert( map.insert(
"substituter_trusted_keys".into(), "substituter_trusted_keys".into(),
serde_json::to_value(substituter_trusted_keys)?, serde_json::to_value(substituter_trusted_keys)?,
@ -452,6 +466,10 @@ impl CommonSettings {
"substitution_targets".into(), "substitution_targets".into(),
serde_json::to_value(substitution_targets)?, serde_json::to_value(substitution_targets)?,
); );
map.insert(
"substituter_require_sigs".into(),
serde_json::to_value(substituter_require_sigs)?,
);
map.insert( map.insert(
"use_substituters".into(), "use_substituters".into(),
serde_json::to_value(use_substituters)?, serde_json::to_value(use_substituters)?,
@ -460,6 +478,7 @@ impl CommonSettings {
"nix_package_url".into(), "nix_package_url".into(),
serde_json::to_value(nix_package_url)?, serde_json::to_value(nix_package_url)?,
); );
map.insert("substituters".into(), serde_json::to_value(substituters)?);
map.insert("proxy".into(), serde_json::to_value(proxy)?); map.insert("proxy".into(), serde_json::to_value(proxy)?);
map.insert("ssl_cert_file".into(), serde_json::to_value(ssl_cert_file)?); map.insert("ssl_cert_file".into(), serde_json::to_value(ssl_cert_file)?);
map.insert("extra_conf".into(), serde_json::to_value(extra_conf)?); map.insert("extra_conf".into(), serde_json::to_value(extra_conf)?);

View file

@ -422,6 +422,7 @@
"substitution_targets": [ "substitution_targets": [
"/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0" "/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0"
], ],
"substituter_require_sigs": true,
"use_substituters": false, "use_substituters": false,
"nix_package_url": { "nix_package_url": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz"

View file

@ -406,6 +406,7 @@
"substitution_targets": [ "substitution_targets": [
"/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0" "/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0"
], ],
"substituter_require_sigs": true,
"use_substituters": false, "use_substituters": false,
"nix_package_url": { "nix_package_url": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz"

View file

@ -433,6 +433,7 @@
"substitution_target": [ "substitution_target": [
"/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0" "/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0"
], ],
"substituter_require_sigs": true,
"use_substituters": false, "use_substituters": false,
"nix_package_url": { "nix_package_url": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-darwin.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-darwin.tar.xz"