Basic check of user data structure for errors
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-06-10 21:57:58 +02:00
parent ee733b04f3
commit 978a881372
5 changed files with 57 additions and 1 deletions

View File

@ -1982,6 +1982,16 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "libyml"
version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980"
dependencies = [
"anyhow",
"version_check",
]
[[package]] [[package]]
name = "light-openid" name = "light-openid"
version = "1.0.4" version = "1.0.4"
@ -3093,6 +3103,21 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_yml"
version = "0.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd"
dependencies = [
"indexmap",
"itoa",
"libyml",
"memchr",
"ryu",
"serde",
"version_check",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.10.6" version = "0.10.6"
@ -3754,6 +3779,7 @@ dependencies = [
"rust-embed", "rust-embed",
"serde", "serde",
"serde_json", "serde_json",
"serde_yml",
"sysinfo", "sysinfo",
"tempfile", "tempfile",
"thiserror 2.0.12", "thiserror 2.0.12",

View File

@ -22,6 +22,7 @@ actix-ws = "0.3.0"
actix-http = "3.10.0" actix-http = "3.10.0"
serde = { version = "1.0.219", features = ["derive"] } serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140" serde_json = "1.0.140"
serde_yml = "0.0.12"
quick-xml = { version = "0.37.5", features = ["serialize", "overlapped-lists"] } quick-xml = { version = "0.37.5", features = ["serialize", "overlapped-lists"] }
futures-util = "0.3.31" futures-util = "0.3.31"
anyhow = "1.0.98" anyhow = "1.0.98"

View File

@ -13,4 +13,6 @@ enum LibVirtStructError {
ParseFilteringChain(String), ParseFilteringChain(String),
#[error("NetworkFilterExtractionError: {0}")] #[error("NetworkFilterExtractionError: {0}")]
NetworkFilterExtraction(String), NetworkFilterExtraction(String),
#[error("CloudInitConfigurationError: {0}")]
CloudInitConfiguration(String),
} }

View File

@ -3,7 +3,9 @@ use crate::constants;
use crate::libvirt_lib_structures::XMLUuid; use crate::libvirt_lib_structures::XMLUuid;
use crate::libvirt_lib_structures::domain::*; use crate::libvirt_lib_structures::domain::*;
use crate::libvirt_rest_structures::LibVirtStructError; use crate::libvirt_rest_structures::LibVirtStructError;
use crate::libvirt_rest_structures::LibVirtStructError::StructureExtraction; use crate::libvirt_rest_structures::LibVirtStructError::{
CloudInitConfiguration, StructureExtraction,
};
use crate::utils::cloud_init_utils::CloudInitConfig; use crate::utils::cloud_init_utils::CloudInitConfig;
use crate::utils::file_size_utils::FileSize; use crate::utils::file_size_utils::FileSize;
use crate::utils::files_utils; use crate::utils::files_utils;
@ -142,6 +144,10 @@ impl VMInfo {
return Err(StructureExtraction("Invalid number of vCPU specified!").into()); return Err(StructureExtraction("Invalid number of vCPU specified!").into());
} }
if let Some(e) = self.cloud_init.check_error() {
return Err(CloudInitConfiguration(e).into());
}
let mut iso_absolute_files = vec![]; let mut iso_absolute_files = vec![];
// Process cloud init image // Process cloud init image

View File

@ -35,6 +35,27 @@ pub struct CloudInitConfig {
} }
impl CloudInitConfig { impl CloudInitConfig {
/// Check cloud init configuration
pub fn check_error(&self) -> Option<String> {
if !self.user_data.is_empty() {
// Check YAML content
if let Err(e) = serde_yml::from_str::<serde_json::Value>(&self.user_data) {
return Some(format!(
"user data is an invalid YAML file! Deserialization error: {e}"
));
}
// Check first line
if !self.user_data.starts_with("#cloud-config\n") {
return Some(
"user data file MUST start with '#cloud-config' as first line!".to_string(),
);
}
}
None
}
/// Generate disk image for nocloud usage /// Generate disk image for nocloud usage
pub fn generate_nocloud_disk(&self) -> anyhow::Result<Vec<u8>> { pub fn generate_nocloud_disk(&self) -> anyhow::Result<Vec<u8>> {
let temp_path = tempfile::tempdir_in(&AppConfig::get().temp_dir)?; let temp_path = tempfile::tempdir_in(&AppConfig::get().temp_dir)?;