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