in tools/pubsys-setup/src/main.rs [177:294]
fn find_root_role_and_key(args: &Args) -> Result<(Option<&PathBuf>, Option<Url>)> {
let (mut root_role_path, mut key_url) = (None, None);
if InfraConfig::lock_or_infra_config_exists(&args.infra_config_path).context(error::Config)? {
let infra_config = InfraConfig::from_path_or_lock(&args.infra_config_path, false)
.context(error::Config)?;
trace!("Parsed infra config: {:?}", infra_config);
// Check whether the user has the relevant repo defined in their Infra.toml.
if let Some(repo_config) = infra_config
.repo
.as_ref()
.and_then(|repo_section| repo_section.get(&args.repo))
{
// If they have a root role URL and checksum defined, we can download it.
if let (Some(url), Some(sha512)) =
(&repo_config.root_role_url, &repo_config.root_role_sha512)
{
// If it's already been downloaded, just confirm the checksum.
if args.root_role_path.exists() {
let root_role_data =
fs::read_to_string(&args.root_role_path).context(error::ReadFile {
path: &args.root_role_path,
})?;
let mut d = Sha512::new();
d.update(&root_role_data);
let digest = hex::encode(d.finalize());
ensure!(
&digest == sha512,
error::Hash {
expected: sha512,
got: digest,
thing: args.root_role_path.to_string_lossy()
}
);
debug!(
"Using existing downloaded root role at {}",
args.root_role_path.display()
);
} else {
// Download the root role by URL and verify its checksum before writing it.
let root_role_data = if url.scheme() == "file" {
// reqwest won't fetch a file URL, so just read the file.
let path = url
.to_file_path()
.ok()
.with_context(|| error::UrlToFile { url: url.clone() })?;
fs::read_to_string(&path).context(error::ReadFile { path: &path })?
} else {
reqwest::blocking::get(url.clone())
.with_context(|| error::GetUrl { url: url.clone() })?
.text()
.with_context(|| error::GetUrl { url: url.clone() })?
};
let mut d = Sha512::new();
d.update(&root_role_data);
let digest = hex::encode(d.finalize());
ensure!(
&digest == sha512,
error::Hash {
expected: sha512,
got: digest,
thing: url.to_string()
}
);
// Write root role to expected path on disk.
fs::write(&args.root_role_path, &root_role_data).context(error::WriteFile {
path: &args.root_role_path,
})?;
debug!("Downloaded root role to {}", args.root_role_path.display());
}
root_role_path = Some(&args.root_role_path);
} else if repo_config.root_role_url.is_some() || repo_config.root_role_sha512.is_some()
{
// Must specify both URL and checksum.
error::RootRoleConfig.fail()?;
}
if let Some(key_config) = &repo_config.signing_keys {
key_url = Some(
Url::try_from(key_config.clone())
.ok()
.context(error::SigningKeyUrl { repo: &args.repo })?,
);
}
} else {
info!(
"No repo config in '{}' - using local roles/keys",
args.infra_config_path.display()
);
}
} else {
info!(
"No infra config at '{}' - using local roles/keys",
args.infra_config_path.display()
);
}
// If they don't have an Infra.toml or didn't define a root role / key there, check for them in
// expected local paths.
if root_role_path.is_none() && args.root_role_path.exists() {
root_role_path = Some(&args.root_role_path);
}
if key_url.is_none() && args.default_key_path.exists() {
key_url = Some(Url::from_file_path(&args.default_key_path).ok().context(
error::FileToUrl {
path: &args.default_key_path,
},
)?);
}
Ok((root_role_path, key_url))
}