xianyun_pki/truststore/
install.rs1use std::path::Path;
6
7use crate::ca;
8use crate::truststore::command_runner::CommandRunner;
9use crate::truststore::nss;
10
11#[derive(Debug, thiserror::Error)]
12pub enum TrustError {
13 #[error("locating CA certificate: {0}")]
14 Locating(#[from] ca::PkiError),
15 #[error("installing CA in system trust store: {0}")]
16 InstallingSystem(String),
17 #[error("removing CA from system trust store: {0}")]
18 RemovingSystem(String),
19 #[error("earlier signings of the CA's key are still trusted: {0}")]
23 EarlierSigningsTrusted(String),
24}
25
26pub fn install(pki_dir: &Path, runner: &dyn CommandRunner) -> Result<(), TrustError> {
40 let cert_path = ca::cert_path(pki_dir)?;
41
42 println!("Installing Caproni Dev CA...");
43 println!(" CA: {}", cert_path.display());
44
45 system::install_system(runner, &cert_path)
46 .map_err(|e| TrustError::InstallingSystem(e.to_string()))?;
47 println!(" Done: installed in system trust store");
48
49 match nss::install_nss(&cert_path) {
50 Ok(()) => println!(" Done: installed in Firefox NSS store"),
51 Err(e) => println!(" Note: Firefox NSS: {e}"),
52 }
53
54 let removed = system::remove_superseded_system(runner, &cert_path)
55 .map_err(|e| TrustError::EarlierSigningsTrusted(e.to_string()))?;
56 announce_removed(removed);
57
58 Ok(())
59}
60
61pub fn uninstall(pki_dir: &Path, runner: &dyn CommandRunner) -> Result<(), TrustError> {
68 let cert_path = ca::cert_path(pki_dir)?;
69
70 println!("Removing Caproni Dev CA...");
71
72 system::uninstall_system(runner, &cert_path)
73 .map_err(|e| TrustError::RemovingSystem(e.to_string()))?;
74 println!(" Done: removed from system trust store");
75
76 report_superseded(&cert_path, runner);
77
78 match nss::uninstall_nss() {
79 Ok(()) => println!(" Done: removed from Firefox NSS store"),
80 Err(e) => println!(" Note: Firefox NSS: {e}"),
81 }
82
83 Ok(())
84}
85
86pub(crate) fn report_superseded(cert_path: &Path, runner: &dyn CommandRunner) {
88 match system::remove_superseded_system(runner, cert_path) {
89 Ok(removed) => announce_removed(removed),
90 Err(e) => println!(" Note: earlier Caproni Dev CA certificates: {e}"),
91 }
92}
93
94fn announce_removed(removed: usize) {
95 if removed > 0 {
96 println!(" Done: removed {removed} earlier certificate(s) for this CA's key");
97 }
98}
99
100#[cfg(target_os = "macos")]
101use crate::truststore::system_darwin as system;
102#[cfg(target_os = "linux")]
103use crate::truststore::system_linux as system;
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use crate::truststore::helpers::new_mock;
109
110 #[test]
112 fn install_fails_when_cert_not_found() {
113 let dir = tempfile::tempdir().unwrap();
114 let runner = new_mock();
115
116 let err = install(dir.path(), &runner).unwrap_err();
117 assert!(err.to_string().contains("CA certificate not found"));
118 }
119
120 #[test]
122 fn uninstall_fails_when_cert_not_found() {
123 let dir = tempfile::tempdir().unwrap();
124 let runner = new_mock();
125
126 let err = uninstall(dir.path(), &runner).unwrap_err();
127 assert!(err.to_string().contains("CA certificate not found"));
128 }
129}