Write configuration to file after validation.
(config: &mut Map<String, Value>, filepath: Option<&PathBuf>)
| 214 | |
| 215 | /// Write configuration to file after validation. |
| 216 | fn write_and_validate_config(config: &mut Map<String, Value>, filepath: Option<&PathBuf>) -> Result<(), SshdConfigError> { |
| 217 | debug!("{}", t!("set.writingTempConfig")); |
| 218 | CanonicalProperties::remove_all(config); |
| 219 | let mut config_text = SSHD_CONFIG_HEADER.to_string() + "\n" + SSHD_CONFIG_HEADER_VERSION + "\n" + SSHD_CONFIG_HEADER_WARNING + "\n"; |
| 220 | config_text.push_str(&write_config_map_to_text(config)?); |
| 221 | |
| 222 | // Write input to a temporary file and validate it with SSHD -T |
| 223 | let temp_file = tempfile::Builder::new() |
| 224 | .prefix("sshd_config_temp_") |
| 225 | .suffix(".tmp") |
| 226 | .tempfile()?; |
| 227 | let temp_path = temp_file.path().to_path_buf(); |
| 228 | let (file, path) = temp_file.keep()?; |
| 229 | debug!("{}", t!("set.tempFileCreated", path = temp_path.display())); |
| 230 | std::fs::write(&temp_path, &config_text) |
| 231 | .map_err(|e| SshdConfigError::CommandError(e.to_string()))?; |
| 232 | drop(file); |
| 233 | |
| 234 | let args = Some( |
| 235 | SshdCommandArgs { |
| 236 | filepath: Some(temp_path), |
| 237 | additional_args: None, |
| 238 | } |
| 239 | ); |
| 240 | |
| 241 | debug!("{}", t!("set.validatingTempConfig")); |
| 242 | let result = invoke_sshd_config_validation(args); |
| 243 | // Always cleanup temp file, regardless of result success or failure |
| 244 | if let Err(e) = std::fs::remove_file(&path) { |
| 245 | warn!("{}", t!("set.cleanupFailed", path = path.display(), error = e)); |
| 246 | } |
| 247 | // Propagate failure, if any |
| 248 | result?; |
| 249 | |
| 250 | let sshd_config_path = get_default_sshd_config_path(filepath.cloned())?; |
| 251 | |
| 252 | if sshd_config_path.exists() { |
| 253 | let mut sshd_config_content = String::new(); |
| 254 | if let Ok(mut file) = std::fs::OpenOptions::new().read(true).open(&sshd_config_path) { |
| 255 | use std::io::Read; |
| 256 | file.read_to_string(&mut sshd_config_content) |
| 257 | .map_err(|e| SshdConfigError::CommandError(e.to_string()))?; |
| 258 | } else { |
| 259 | return Err(SshdConfigError::CommandError(t!("set.sshdConfigReadFailed", path = sshd_config_path.display()).to_string())); |
| 260 | } |
| 261 | if !sshd_config_content.starts_with(SSHD_CONFIG_HEADER) { |
| 262 | // If config file is not already managed by this resource, create a backup of the existing file |
| 263 | debug!("{}", t!("set.backingUpConfig")); |
| 264 | let backup_path = format!("{}_backup", sshd_config_path.display()); |
| 265 | std::fs::write(&backup_path, &sshd_config_content) |
| 266 | .map_err(|e| SshdConfigError::CommandError(e.to_string()))?; |
| 267 | info!("{}", t!("set.backupCreated", path = backup_path)); |
| 268 | } |
| 269 | } else { |
| 270 | debug!("{}", t!("set.configDoesNotExist")); |
| 271 | } |
| 272 | |
| 273 | std::fs::write(&sshd_config_path, &config_text) |
no test coverage detected