myc_repo_local_identity_bootstrap.rs (2759B)
1 #![forbid(unsafe_code)] 2 3 use std::env; 4 use std::path::{Path, PathBuf}; 5 use std::process::ExitCode; 6 7 use myc::identity_files::{load_encrypted_identity, store_encrypted_identity}; 8 use radroots_identity::RadrootsIdentity; 9 use radroots_runtime_paths::{ 10 RadrootsPathOverrides, RadrootsPathProfile, RadrootsPathResolver, RadrootsRuntimeNamespace, 11 }; 12 13 fn main() -> ExitCode { 14 match run() { 15 Ok(()) => ExitCode::SUCCESS, 16 Err(err) => { 17 eprintln!("{err}"); 18 ExitCode::from(1) 19 } 20 } 21 } 22 23 fn run() -> Result<(), String> { 24 let runtime_root = runtime_root_from_args()?; 25 let resolved = resolve_runtime_paths(&runtime_root)?; 26 27 ensure_identity(&resolved.signer_identity_path)?; 28 ensure_identity(&resolved.user_identity_path)?; 29 30 println!( 31 "ok bootstrap-myc-repo-local-identities {}", 32 runtime_root.display() 33 ); 34 Ok(()) 35 } 36 37 fn runtime_root_from_args() -> Result<PathBuf, String> { 38 let mut args = env::args_os(); 39 let _ = args.next(); 40 let Some(runtime_root) = args.next() else { 41 return Err("usage: myc_repo_local_identity_bootstrap <runtime-root>".to_owned()); 42 }; 43 if args.next().is_some() { 44 return Err("usage: myc_repo_local_identity_bootstrap <runtime-root>".to_owned()); 45 } 46 Ok(PathBuf::from(runtime_root)) 47 } 48 49 struct MycRuntimePaths { 50 signer_identity_path: PathBuf, 51 user_identity_path: PathBuf, 52 } 53 54 fn resolve_runtime_paths(runtime_root: &Path) -> Result<MycRuntimePaths, String> { 55 let base_paths = RadrootsPathResolver::current() 56 .resolve( 57 RadrootsPathProfile::RepoLocal, 58 &RadrootsPathOverrides::repo_local(runtime_root), 59 ) 60 .map_err(|err| format!("resolve repo_local runtime roots: {err}"))?; 61 let myc_namespace = RadrootsRuntimeNamespace::service("myc") 62 .map_err(|err| format!("resolve myc namespace: {err}"))?; 63 let myc_paths = base_paths.namespaced(&myc_namespace); 64 Ok(MycRuntimePaths { 65 signer_identity_path: myc_paths.secrets.join("signer-identity.json"), 66 user_identity_path: myc_paths.secrets.join("user-identity.json"), 67 }) 68 } 69 70 fn ensure_identity(path: &Path) -> Result<(), String> { 71 if path.is_file() { 72 load_encrypted_identity(path) 73 .map_err(|err| format!("load encrypted identity {}: {err}", path.display()))?; 74 return Ok(()); 75 } 76 77 if let Some(parent) = path.parent() { 78 std::fs::create_dir_all(parent) 79 .map_err(|err| format!("create identity dir {}: {err}", parent.display()))?; 80 } 81 let identity = RadrootsIdentity::generate(); 82 store_encrypted_identity(path, &identity) 83 .map_err(|err| format!("store encrypted identity {}: {err}", path.display()))?; 84 Ok(()) 85 }