Generate a given identity
(
name: &str,
directory: &Path,
filename: &str,
parent: Option<&Identity>,
)
| 51 | |
| 52 | /// Generate a given identity |
| 53 | fn generate_or_load_identity( |
| 54 | name: &str, |
| 55 | directory: &Path, |
| 56 | filename: &str, |
| 57 | parent: Option<&Identity>, |
| 58 | ) -> Result<Identity> { |
| 59 | use std::io::Write; |
| 60 | use std::os::unix::fs::PermissionsExt; |
| 61 | // Just our naming convention here. |
| 62 | let cert_path = directory.join(format!("{}.pem", filename)); |
| 63 | let key_path = directory.join(format!("{}-key.pem", filename)); |
| 64 | // Did we have to generate a new key? In that case we also need to |
| 65 | // regenerate the certificate |
| 66 | if !key_path.exists() || !cert_path.exists() { |
| 67 | debug!( |
| 68 | "Generating a new keypair in {}, it didn't exist", |
| 69 | &key_path.display() |
| 70 | ); |
| 71 | let keypair = KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256)?; |
| 72 | |
| 73 | // Create the file but make it user-readable only: |
| 74 | let mut file = std::fs::File::create(&key_path)?; |
| 75 | let mut perms = std::fs::metadata(&key_path)?.permissions(); |
| 76 | perms.set_mode(0o600); |
| 77 | std::fs::set_permissions(&key_path, perms)?; |
| 78 | |
| 79 | // Only after changing the permissions we can write the |
| 80 | // private key |
| 81 | file.write_all(keypair.serialize_pem().as_bytes())?; |
| 82 | drop(file); |
| 83 | |
| 84 | debug!( |
| 85 | "Generating a new certificate for key {} at {}", |
| 86 | &key_path.display(), |
| 87 | &cert_path.display() |
| 88 | ); |
| 89 | |
| 90 | // Configure the certificate we want. |
| 91 | let subject_alt_names = vec!["cln".to_string(), "localhost".to_string()]; |
| 92 | let mut params = rcgen::CertificateParams::new(subject_alt_names)?; |
| 93 | if parent.is_none() { |
| 94 | params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); |
| 95 | params.key_usages.push(rcgen::KeyUsagePurpose::KeyCertSign); |
| 96 | } else { |
| 97 | params.is_ca = rcgen::IsCa::NoCa; |
| 98 | params |
| 99 | .key_usages |
| 100 | .push(rcgen::KeyUsagePurpose::DigitalSignature); |
| 101 | params |
| 102 | .key_usages |
| 103 | .push(rcgen::KeyUsagePurpose::KeyEncipherment); |
| 104 | params.key_usages.push(rcgen::KeyUsagePurpose::KeyAgreement); |
| 105 | } |
| 106 | params |
| 107 | .distinguished_name |
| 108 | .push(rcgen::DnType::CommonName, name); |
| 109 | params.use_authority_key_identifier_extension = true; |
| 110 |