]> git.proxmox.com Git - proxmox-backup.git/blame - src/config.rs
split out pbs-buildcfg module
[proxmox-backup.git] / src / config.rs
CommitLineData
a8f268af
DM
1//! Proxmox Backup Server Configuration library
2//!
3//! This library contains helper to read, parse and write the
4//! configuration files.
5
f7d4e4b5 6use anyhow::{bail, format_err, Error};
f8fd5095
DM
7use std::path::PathBuf;
8use nix::sys::stat::Mode;
9use openssl::rsa::{Rsa};
10use openssl::x509::{X509Builder};
11use openssl::pkey::PKey;
a8f268af 12
f8fd5095 13use proxmox::tools::fs::{CreateOptions, replace_file};
9ea4bce4 14use proxmox::try_block;
e18a6c9e 15
af06decd 16use pbs_buildcfg::{self, configdir};
a8f268af 17
5c6cdf98 18pub mod acl;
cb67ecad 19pub mod acme;
423e6561 20pub mod cached_user_info;
90d515c9 21pub mod datastore;
f34d4401 22pub mod network;
79b902d5 23pub mod node;
90d515c9 24pub mod remote;
6f652b1b 25pub mod sync;
dc1fdd62 26pub mod tfa;
f8adf8f8 27pub mod token_shadow;
90d515c9 28pub mod user;
9b2bad7a 29pub mod verify;
a0765714 30pub mod drive;
1142350e 31pub mod media_pool;
d5a48b5c 32pub mod tape_encryption_keys;
be327dbc 33pub mod tape_job;
bbff6c49 34pub mod domains;
5c20e2da 35
a8f268af
DM
36/// Check configuration directory permissions
37///
38/// For security reasons, we want to make sure they are set correctly:
39/// * owned by 'backup' user/group
40/// * nobody else can read (mode 0700)
8fdef1a8 41pub fn check_configdir_permissions() -> Result<(), Error> {
af06decd 42 let cfgdir = pbs_buildcfg::CONFIGDIR;
f74a03da
DM
43
44 let backup_user = crate::backup::backup_user()?;
45 let backup_uid = backup_user.uid.as_raw();
46 let backup_gid = backup_user.gid.as_raw();
a8f268af
DM
47
48 try_block!({
49 let stat = nix::sys::stat::stat(cfgdir)?;
50
51 if stat.st_uid != backup_uid {
5c20e2da 52 bail!("wrong user ({} != {})", stat.st_uid, backup_uid);
a8f268af
DM
53 }
54 if stat.st_gid != backup_gid {
5c20e2da 55 bail!("wrong group ({} != {})", stat.st_gid, backup_gid);
a8f268af
DM
56 }
57
58 let perm = stat.st_mode & 0o777;
59 if perm != 0o700 {
5c20e2da 60 bail!("wrong permission ({:o} != {:o})", perm, 0o700);
a8f268af
DM
61 }
62 Ok(())
5c20e2da
WB
63 })
64 .map_err(|err| {
65 format_err!(
66 "configuration directory '{}' permission problem - {}",
67 cfgdir,
68 err
69 )
70 })
a8f268af
DM
71}
72
73pub fn create_configdir() -> Result<(), Error> {
af06decd 74 let cfgdir = pbs_buildcfg::CONFIGDIR;
a8f268af
DM
75
76 match nix::unistd::mkdir(cfgdir, Mode::from_bits_truncate(0o700)) {
5c20e2da 77 Ok(()) => {}
a8f268af 78 Err(nix::Error::Sys(nix::errno::Errno::EEXIST)) => {
8fdef1a8 79 check_configdir_permissions()?;
a8f268af 80 return Ok(());
5c20e2da
WB
81 }
82 Err(err) => bail!(
83 "unable to create configuration directory '{}' - {}",
84 cfgdir,
85 err
86 ),
a8f268af
DM
87 }
88
f74a03da 89 let backup_user = crate::backup::backup_user()?;
a8f268af 90
f74a03da
DM
91 nix::unistd::chown(cfgdir, Some(backup_user.uid), Some(backup_user.gid))
92 .map_err(|err| {
93 format_err!(
94 "unable to set configuration directory '{}' permissions - {}",
95 cfgdir,
96 err
97 )
98 })
a8f268af 99}
f8fd5095
DM
100
101/// Update self signed node certificate.
102pub fn update_self_signed_cert(force: bool) -> Result<(), Error> {
103
f8fd5095
DM
104 let key_path = PathBuf::from(configdir!("/proxy.key"));
105 let cert_path = PathBuf::from(configdir!("/proxy.pem"));
106
107 if key_path.exists() && cert_path.exists() && !force { return Ok(()); }
108
109 let rsa = Rsa::generate(4096).unwrap();
110
111 let priv_pem = rsa.private_key_to_pem()?;
112
f8fd5095
DM
113 let mut x509 = X509Builder::new()?;
114
115 x509.set_version(2)?;
116
117 let today = openssl::asn1::Asn1Time::days_from_now(0)?;
118 x509.set_not_before(&today)?;
119 let expire = openssl::asn1::Asn1Time::days_from_now(365*1000)?;
120 x509.set_not_after(&expire)?;
121
122 let nodename = proxmox::tools::nodename();
123 let mut fqdn = nodename.to_owned();
124
125 let resolv_conf = crate::api2::node::dns::read_etc_resolv_conf()?;
126 if let Some(search) = resolv_conf["search"].as_str() {
127 fqdn.push('.');
128 fqdn.push_str(search);
129 }
130
131 // we try to generate an unique 'subject' to avoid browser problems
132 //(reused serial numbers, ..)
133 let uuid = proxmox::tools::uuid::Uuid::generate();
134
135 let mut subject_name = openssl::x509::X509NameBuilder::new()?;
136 subject_name.append_entry_by_text("O", "Proxmox Backup Server")?;
137 subject_name.append_entry_by_text("OU", &format!("{:X}", uuid))?;
138 subject_name.append_entry_by_text("CN", &fqdn)?;
139 let subject_name = subject_name.build();
140
141 x509.set_subject_name(&subject_name)?;
142 x509.set_issuer_name(&subject_name)?;
143
144 let bc = openssl::x509::extension::BasicConstraints::new(); // CA = false
145 let bc = bc.build()?;
146 x509.append_extension(bc)?;
147
148 let usage = openssl::x509::extension::ExtendedKeyUsage::new()
149 .server_auth()
150 .build()?;
151 x509.append_extension(usage)?;
152
153 let context = x509.x509v3_context(None, None);
154
155 let mut alt_names = openssl::x509::extension::SubjectAlternativeName::new();
156
157 alt_names.ip("127.0.0.1");
158 alt_names.ip("::1");
159
160 alt_names.dns("localhost");
161
162 if nodename != "localhost" { alt_names.dns(nodename); }
163 if nodename != fqdn { alt_names.dns(&fqdn); }
164
165 let alt_names = alt_names.build(&context)?;
166
167 x509.append_extension(alt_names)?;
168
169 let pub_pem = rsa.public_key_to_pem()?;
170 let pubkey = PKey::public_key_from_pem(&pub_pem)?;
171
172 x509.set_pubkey(&pubkey)?;
173
174 let context = x509.x509v3_context(None, None);
175 let ext = openssl::x509::extension::SubjectKeyIdentifier::new().build(&context)?;
176 x509.append_extension(ext)?;
177
178 let context = x509.x509v3_context(None, None);
179 let ext = openssl::x509::extension::AuthorityKeyIdentifier::new()
180 .keyid(true)
181 .build(&context)?;
182 x509.append_extension(ext)?;
183
184 let privkey = PKey::from_rsa(rsa)?;
185
186 x509.sign(&privkey, openssl::hash::MessageDigest::sha256())?;
187
188 let x509 = x509.build();
189 let cert_pem = x509.to_pem()?;
190
fca1cef2 191 set_proxy_certificate(&cert_pem, &priv_pem)?;
f8fd5095
DM
192
193 Ok(())
194}
f912ba6a 195
fca1cef2 196pub(crate) fn set_proxy_certificate(cert_pem: &[u8], key_pem: &[u8]) -> Result<(), Error> {
f912ba6a
WB
197 let backup_user = crate::backup::backup_user()?;
198 let options = CreateOptions::new()
199 .perm(Mode::from_bits_truncate(0o0640))
200 .owner(nix::unistd::ROOT)
201 .group(backup_user.gid);
202 let key_path = PathBuf::from(configdir!("/proxy.key"));
203 let cert_path = PathBuf::from(configdir!("/proxy.pem"));
204
205 create_configdir()?;
206 replace_file(&key_path, &key_pem, options.clone())
207 .map_err(|err| format_err!("error writing certificate private key - {}", err))?;
208 replace_file(&cert_path, &cert_pem, options)
209 .map_err(|err| format_err!("error writing certificate file - {}", err))?;
4088d5bc 210
f912ba6a
WB
211 Ok(())
212}