in tools/pubsys-setup/src/main.rs [74:174]
fn run() -> Result<()> {
// Parse and store the args passed to the program
let args = Args::from_args();
// SimpleLogger will send errors to stderr and anything less to stdout.
SimpleLogger::init(args.log_level, LogConfig::default()).context(error::Logger)?;
// Make /roles and /keys directories, if they don't exist, so we can write generated files.
let role_dir = args.root_role_path.parent().context(error::Path {
path: &args.root_role_path,
thing: "root role",
})?;
let key_dir = args.default_key_path.parent().context(error::Path {
path: &args.default_key_path,
thing: "key",
})?;
fs::create_dir_all(role_dir).context(error::Mkdir { path: role_dir })?;
fs::create_dir_all(key_dir).context(error::Mkdir { path: key_dir })?;
// Main branching logic for deciding whether to create role/key, use what we have, or error.
match find_root_role_and_key(&args)? {
(Some(_root_role_path), Some(_key_url)) => Ok(()),
(Some(_root_role_path), None) => {
ensure!(
args.allow_missing_key,
error::MissingKey { repo: args.repo }
);
Ok(())
}
// User is missing something, so we generate at least a root.json and maybe a key.
(None, maybe_key_url) => {
if maybe_key_url.is_some() {
info!("Didn't find root role in Infra.toml, generating...");
} else {
info!("Didn't find root role or signing key in Infra.toml, generating...");
}
let temp_root_role =
NamedTempFile::new_in(&role_dir).context(error::TempFileCreate {
purpose: "root role",
})?;
let temp_root_role_path = temp_root_role.path().display();
// Make tuftool calls to create an initial root.json with basic parameters.
tuftool!("root init '{}'", temp_root_role_path);
tuftool!("root expire '{}' 'in 52 weeks'", temp_root_role_path);
tuftool!("root set-threshold '{}' root 1", temp_root_role_path);
tuftool!("root set-threshold '{}' snapshot 1", temp_root_role_path);
tuftool!("root set-threshold '{}' targets 1", temp_root_role_path);
tuftool!("root set-threshold '{}' timestamp 1", temp_root_role_path);
let key_url = if let Some(key_url) = maybe_key_url {
// If the user has a key, add it to each role.
tuftool!("root add-key '{}' '{}' --role root --role snapshot --role targets --role timestamp",
temp_root_role_path, key_url);
key_url
} else {
// If the user has no key, build one and add it to each role.
tuftool!("root gen-rsa-key '{}' '{}' --role root --role snapshot --role targets --role timestamp",
temp_root_role_path, args.default_key_path.display());
warn!(
"Created a key at {} - note that for production use, you should \
use a key stored in a trusted service like KMS or SSM",
args.default_key_path.display()
);
Url::from_file_path(&args.default_key_path)
.ok()
.context(error::FileToUrl {
path: args.default_key_path,
})?
};
// Sign the role with the given key.
tuftool!("root sign '{}' -k '{}'", temp_root_role_path, key_url);
temp_root_role
.persist_noclobber(&args.root_role_path)
.context(error::TempFilePersist {
path: &args.root_role_path,
})?;
warn!(
"Created a root role at {} - note that for production use, you should create \
a role with a shorter expiration and higher thresholds",
args.root_role_path.display()
);
// Root role files don't need to be secret.
fs::set_permissions(&args.root_role_path, fs::Permissions::from_mode(0o644)).context(
error::SetMode {
path: &args.root_role_path,
},
)?;
Ok(())
}
}
}