mirror of
git://git.proxmox.com/git/proxmox-backup.git
synced 2025-01-08 21:18:07 +03:00
pbs-api-types: use const_format and new api-types from proxmox-schema
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
This commit is contained in:
parent
ffc62ac94d
commit
2416aea8d4
@ -108,6 +108,7 @@ bitflags = "1.2.1"
|
||||
bytes = "1.0"
|
||||
cidr = "0.2.1"
|
||||
crc32fast = "1"
|
||||
const_format = "0.2"
|
||||
crossbeam-channel = "0.5"
|
||||
endian_trait = { version = "0.6", features = ["arrays"] }
|
||||
env_logger = "0.10"
|
||||
@ -158,6 +159,7 @@ base64.workspace = true
|
||||
bitflags.workspace = true
|
||||
bytes.workspace = true
|
||||
cidr.workspace = true
|
||||
const_format.workspace = true
|
||||
crc32fast.workspace = true
|
||||
crossbeam-channel.workspace = true
|
||||
endian_trait.workspace = true
|
||||
|
@ -7,6 +7,7 @@ description = "general API type helpers for PBS"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
const_format.workspace = true
|
||||
hex.workspace = true
|
||||
lazy_static.workspace = true
|
||||
percent-encoding.workspace = true
|
||||
|
@ -2,14 +2,17 @@ use std::str::FromStr;
|
||||
|
||||
use serde::de::{value, IntoDeserializer};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use const_format::concatcp;
|
||||
|
||||
use proxmox_lang::constnamedbitmap;
|
||||
use proxmox_schema::{
|
||||
api, const_regex, ApiStringFormat, BooleanSchema, EnumEntry, Schema, StringSchema,
|
||||
};
|
||||
|
||||
use crate::PROXMOX_SAFE_ID_REGEX_STR;
|
||||
|
||||
const_regex! {
|
||||
pub ACL_PATH_REGEX = concat!(r"^(?:/|", r"(?:/", PROXMOX_SAFE_ID_REGEX_STR!(), ")+", r")$");
|
||||
pub ACL_PATH_REGEX = concatcp!(r"^(?:/|", r"(?:/", PROXMOX_SAFE_ID_REGEX_STR, ")+", r")$");
|
||||
}
|
||||
|
||||
// define Privilege bitfield
|
||||
|
@ -1,78 +0,0 @@
|
||||
//! Predefined Regular Expressions
|
||||
//!
|
||||
//! This is a collection of useful regular expressions
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! IPV4OCTET { () => (r"(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9])?[0-9])") }
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! IPV6H16 { () => (r"(?:[0-9a-fA-F]{1,4})") }
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! IPV6LS32 { () => (concat!(r"(?:(?:", IPV4RE!(), "|", IPV6H16!(), ":", IPV6H16!(), "))" )) }
|
||||
|
||||
/// Returns the regular expression string to match IPv4 addresses
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! IPV4RE { () => (concat!(r"(?:(?:", IPV4OCTET!(), r"\.){3}", IPV4OCTET!(), ")")) }
|
||||
|
||||
/// Returns the regular expression string to match IPv6 addresses
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! IPV6RE { () => (concat!(r"(?:",
|
||||
r"(?:(?:", r"(?:", IPV6H16!(), r":){6})", IPV6LS32!(), r")|",
|
||||
r"(?:(?:", r"::(?:", IPV6H16!(), r":){5})", IPV6LS32!(), r")|",
|
||||
r"(?:(?:(?:", IPV6H16!(), r")?::(?:", IPV6H16!(), r":){4})", IPV6LS32!(), r")|",
|
||||
r"(?:(?:(?:(?:", IPV6H16!(), r":){0,1}", IPV6H16!(), r")?::(?:", IPV6H16!(), r":){3})", IPV6LS32!(), r")|",
|
||||
r"(?:(?:(?:(?:", IPV6H16!(), r":){0,2}", IPV6H16!(), r")?::(?:", IPV6H16!(), r":){2})", IPV6LS32!(), r")|",
|
||||
r"(?:(?:(?:(?:", IPV6H16!(), r":){0,3}", IPV6H16!(), r")?::(?:", IPV6H16!(), r":){1})", IPV6LS32!(), r")|",
|
||||
r"(?:(?:(?:(?:", IPV6H16!(), r":){0,4}", IPV6H16!(), r")?::", ")", IPV6LS32!(), r")|",
|
||||
r"(?:(?:(?:(?:", IPV6H16!(), r":){0,5}", IPV6H16!(), r")?::", ")", IPV6H16!(), r")|",
|
||||
r"(?:(?:(?:(?:", IPV6H16!(), r":){0,6}", IPV6H16!(), r")?::", ")))"))
|
||||
}
|
||||
|
||||
/// Returns the regular expression string to match IP addresses (v4 or v6)
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! IPRE { () => (concat!(r"(?:", IPV4RE!(), "|", IPV6RE!(), ")")) }
|
||||
|
||||
/// Regular expression string to match IP addresses where IPv6 addresses require brackets around
|
||||
/// them, while for IPv4 they are forbidden.
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! IPRE_BRACKET { () => (
|
||||
concat!(r"(?:",
|
||||
IPV4RE!(),
|
||||
r"|\[(?:",
|
||||
IPV6RE!(),
|
||||
r")\]",
|
||||
r")"))
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref IP_REGEX: Regex = Regex::new(concat!(r"^", IPRE!(), r"$")).unwrap();
|
||||
pub static ref IP_BRACKET_REGEX: Regex =
|
||||
Regex::new(concat!(r"^", IPRE_BRACKET!(), r"$")).unwrap();
|
||||
pub static ref SHA256_HEX_REGEX: Regex = Regex::new(r"^[a-f0-9]{64}$").unwrap();
|
||||
pub static ref SYSTEMD_DATETIME_REGEX: Regex =
|
||||
Regex::new(r"^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_regexes() {
|
||||
assert!(IP_REGEX.is_match("127.0.0.1"));
|
||||
assert!(IP_REGEX.is_match("::1"));
|
||||
assert!(IP_REGEX.is_match("2014:b3a::27"));
|
||||
assert!(IP_REGEX.is_match("2014:b3a::192.168.0.1"));
|
||||
assert!(IP_REGEX.is_match("2014:b3a:0102:adf1:1234:4321:4afA:BCDF"));
|
||||
|
||||
assert!(IP_BRACKET_REGEX.is_match("127.0.0.1"));
|
||||
assert!(IP_BRACKET_REGEX.is_match("[::1]"));
|
||||
assert!(IP_BRACKET_REGEX.is_match("[2014:b3a::27]"));
|
||||
assert!(IP_BRACKET_REGEX.is_match("[2014:b3a::192.168.0.1]"));
|
||||
assert!(IP_BRACKET_REGEX.is_match("[2014:b3a:0102:adf1:1234:4321:4afA:BCDF]"));
|
||||
}
|
@ -2,6 +2,7 @@ use std::fmt;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{bail, format_err, Error};
|
||||
use const_format::concatcp;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use proxmox_schema::{
|
||||
@ -10,31 +11,33 @@ use proxmox_schema::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Authid, CryptMode, Fingerprint, GroupFilter, MaintenanceMode, Userid,
|
||||
DATASTORE_NOTIFY_STRING_SCHEMA, GC_SCHEDULE_SCHEMA, PROXMOX_SAFE_ID_FORMAT,
|
||||
PRUNE_SCHEDULE_SCHEMA, SHA256_HEX_REGEX, SINGLE_LINE_COMMENT_SCHEMA, UPID,
|
||||
Authid, CryptMode, Fingerprint, GroupFilter, MaintenanceMode, Userid, BACKUP_ID_RE,
|
||||
BACKUP_NS_RE, BACKUP_TIME_RE, BACKUP_TYPE_RE, DATASTORE_NOTIFY_STRING_SCHEMA,
|
||||
GC_SCHEDULE_SCHEMA, GROUP_OR_SNAPSHOT_PATH_REGEX_STR, PROXMOX_SAFE_ID_FORMAT,
|
||||
PROXMOX_SAFE_ID_REGEX_STR, PRUNE_SCHEDULE_SCHEMA, SHA256_HEX_REGEX, SINGLE_LINE_COMMENT_SCHEMA,
|
||||
SNAPSHOT_PATH_REGEX_STR, UPID,
|
||||
};
|
||||
|
||||
const_regex! {
|
||||
pub BACKUP_NAMESPACE_REGEX = concat!(r"^", BACKUP_NS_RE!(), r"$");
|
||||
pub BACKUP_NAMESPACE_REGEX = concatcp!(r"^", BACKUP_NS_RE, r"$");
|
||||
|
||||
pub BACKUP_TYPE_REGEX = concat!(r"^(", BACKUP_TYPE_RE!(), r")$");
|
||||
pub BACKUP_TYPE_REGEX = concatcp!(r"^(", BACKUP_TYPE_RE, r")$");
|
||||
|
||||
pub BACKUP_ID_REGEX = concat!(r"^", BACKUP_ID_RE!(), r"$");
|
||||
pub BACKUP_ID_REGEX = concatcp!(r"^", BACKUP_ID_RE, r"$");
|
||||
|
||||
pub BACKUP_DATE_REGEX = concat!(r"^", BACKUP_TIME_RE!() ,r"$");
|
||||
pub BACKUP_DATE_REGEX = concatcp!(r"^", BACKUP_TIME_RE ,r"$");
|
||||
|
||||
pub GROUP_PATH_REGEX = concat!(
|
||||
r"^(", BACKUP_TYPE_RE!(), ")/",
|
||||
r"(", BACKUP_ID_RE!(), r")$",
|
||||
pub GROUP_PATH_REGEX = concatcp!(
|
||||
r"^(", BACKUP_TYPE_RE, ")/",
|
||||
r"(", BACKUP_ID_RE, r")$",
|
||||
);
|
||||
|
||||
pub BACKUP_FILE_REGEX = r"^.*\.([fd]idx|blob)$";
|
||||
|
||||
pub SNAPSHOT_PATH_REGEX = concat!(r"^", SNAPSHOT_PATH_REGEX_STR!(), r"$");
|
||||
pub GROUP_OR_SNAPSHOT_PATH_REGEX = concat!(r"^", GROUP_OR_SNAPSHOT_PATH_REGEX_STR!(), r"$");
|
||||
pub SNAPSHOT_PATH_REGEX = concatcp!(r"^", SNAPSHOT_PATH_REGEX_STR, r"$");
|
||||
pub GROUP_OR_SNAPSHOT_PATH_REGEX = concatcp!(r"^", GROUP_OR_SNAPSHOT_PATH_REGEX_STR, r"$");
|
||||
|
||||
pub DATASTORE_MAP_REGEX = concat!(r"^(?:", PROXMOX_SAFE_ID_REGEX_STR!(), r"=)?", PROXMOX_SAFE_ID_REGEX_STR!(), r"$");
|
||||
pub DATASTORE_MAP_REGEX = concatcp!(r"^(?:", PROXMOX_SAFE_ID_REGEX_STR, r"=)?", PROXMOX_SAFE_ID_REGEX_STR, r"$");
|
||||
}
|
||||
|
||||
pub const CHUNK_DIGEST_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SHA256_HEX_REGEX);
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::bail;
|
||||
use const_format::concatcp;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -8,17 +9,17 @@ use proxmox_schema::*;
|
||||
|
||||
use crate::{
|
||||
Authid, BackupNamespace, BackupType, RateLimitConfig, Userid, BACKUP_GROUP_SCHEMA,
|
||||
BACKUP_NAMESPACE_SCHEMA, DATASTORE_SCHEMA, DRIVE_NAME_SCHEMA, MEDIA_POOL_NAME_SCHEMA,
|
||||
NS_MAX_DEPTH_REDUCED_SCHEMA, PROXMOX_SAFE_ID_FORMAT, REMOTE_ID_SCHEMA,
|
||||
SINGLE_LINE_COMMENT_SCHEMA,
|
||||
BACKUP_NAMESPACE_SCHEMA, BACKUP_NS_RE, DATASTORE_SCHEMA, DRIVE_NAME_SCHEMA,
|
||||
MEDIA_POOL_NAME_SCHEMA, NS_MAX_DEPTH_REDUCED_SCHEMA, PROXMOX_SAFE_ID_FORMAT,
|
||||
PROXMOX_SAFE_ID_REGEX_STR, REMOTE_ID_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA,
|
||||
};
|
||||
|
||||
const_regex! {
|
||||
|
||||
/// Regex for verification jobs 'DATASTORE:ACTUAL_JOB_ID'
|
||||
pub VERIFICATION_JOB_WORKER_ID_REGEX = concat!(r"^(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):");
|
||||
pub VERIFICATION_JOB_WORKER_ID_REGEX = concatcp!(r"^(", PROXMOX_SAFE_ID_REGEX_STR, r"):");
|
||||
/// Regex for sync jobs '(REMOTE|\-):REMOTE_DATASTORE:LOCAL_DATASTORE:(?:LOCAL_NS_ANCHOR:)ACTUAL_JOB_ID'
|
||||
pub SYNC_JOB_WORKER_ID_REGEX = concat!(r"^(", PROXMOX_SAFE_ID_REGEX_STR!(), r"|\-):(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(", PROXMOX_SAFE_ID_REGEX_STR!(), r")(?::(", BACKUP_NS_RE!(), r"))?:");
|
||||
pub SYNC_JOB_WORKER_ID_REGEX = concatcp!(r"^(", PROXMOX_SAFE_ID_REGEX_STR, r"|\-):(", PROXMOX_SAFE_ID_REGEX_STR, r"):(", PROXMOX_SAFE_ID_REGEX_STR, r")(?::(", BACKUP_NS_RE, r"))?:");
|
||||
}
|
||||
|
||||
pub const JOB_ID_SCHEMA: Schema = StringSchema::new("Job ID.")
|
||||
|
@ -1,10 +1,8 @@
|
||||
//! Basic API types used by most of the PBS code.
|
||||
|
||||
use const_format::concatcp;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use proxmox_auth_api::{APITOKEN_ID_REGEX_STR, USER_ID_REGEX_STR};
|
||||
|
||||
pub mod common_regex;
|
||||
pub mod percent_encoding;
|
||||
|
||||
use proxmox_schema::{
|
||||
@ -12,59 +10,78 @@ use proxmox_schema::{
|
||||
};
|
||||
use proxmox_time::parse_daily_duration;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! PROXMOX_SAFE_ID_REGEX_STR { () => { r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)" }; }
|
||||
use proxmox_auth_api::types::{APITOKEN_ID_REGEX_STR, USER_ID_REGEX_STR};
|
||||
|
||||
pub use proxmox_schema::api_types::SAFE_ID_FORMAT as PROXMOX_SAFE_ID_FORMAT;
|
||||
pub use proxmox_schema::api_types::SAFE_ID_REGEX as PROXMOX_SAFE_ID_REGEX;
|
||||
pub use proxmox_schema::api_types::SAFE_ID_REGEX_STR as PROXMOX_SAFE_ID_REGEX_STR;
|
||||
pub use proxmox_schema::api_types::{
|
||||
BLOCKDEVICE_DISK_AND_PARTITION_NAME_REGEX, BLOCKDEVICE_NAME_REGEX,
|
||||
};
|
||||
pub use proxmox_schema::api_types::{DNS_ALIAS_REGEX, DNS_NAME_OR_IP_REGEX, DNS_NAME_REGEX};
|
||||
pub use proxmox_schema::api_types::{FINGERPRINT_SHA256_REGEX, SHA256_HEX_REGEX};
|
||||
pub use proxmox_schema::api_types::{
|
||||
GENERIC_URI_REGEX, HOSTNAME_REGEX, HOST_PORT_REGEX, HTTP_URL_REGEX,
|
||||
};
|
||||
pub use proxmox_schema::api_types::{MULTI_LINE_COMMENT_REGEX, SINGLE_LINE_COMMENT_REGEX};
|
||||
pub use proxmox_schema::api_types::{PASSWORD_REGEX, SYSTEMD_DATETIME_REGEX, UUID_REGEX};
|
||||
|
||||
pub use proxmox_schema::api_types::{CIDR_FORMAT, CIDR_REGEX};
|
||||
pub use proxmox_schema::api_types::{CIDR_V4_FORMAT, CIDR_V4_REGEX};
|
||||
pub use proxmox_schema::api_types::{CIDR_V6_FORMAT, CIDR_V6_REGEX};
|
||||
pub use proxmox_schema::api_types::{IPRE_STR, IP_FORMAT, IP_REGEX};
|
||||
pub use proxmox_schema::api_types::{IPV4RE_STR, IP_V4_FORMAT, IP_V4_REGEX};
|
||||
pub use proxmox_schema::api_types::{IPV6RE_STR, IP_V6_FORMAT, IP_V6_REGEX};
|
||||
|
||||
pub use proxmox_schema::api_types::COMMENT_SCHEMA as SINGLE_LINE_COMMENT_SCHEMA;
|
||||
pub use proxmox_schema::api_types::HOSTNAME_SCHEMA;
|
||||
pub use proxmox_schema::api_types::HOST_PORT_SCHEMA;
|
||||
pub use proxmox_schema::api_types::HTTP_URL_SCHEMA;
|
||||
pub use proxmox_schema::api_types::MULTI_LINE_COMMENT_SCHEMA;
|
||||
pub use proxmox_schema::api_types::NODE_SCHEMA;
|
||||
pub use proxmox_schema::api_types::SINGLE_LINE_COMMENT_FORMAT;
|
||||
pub use proxmox_schema::api_types::{
|
||||
BLOCKDEVICE_DISK_AND_PARTITION_NAME_SCHEMA, BLOCKDEVICE_NAME_SCHEMA,
|
||||
};
|
||||
pub use proxmox_schema::api_types::{CERT_FINGERPRINT_SHA256_SCHEMA, FINGERPRINT_SHA256_FORMAT};
|
||||
pub use proxmox_schema::api_types::{DISK_ARRAY_SCHEMA, DISK_LIST_SCHEMA};
|
||||
pub use proxmox_schema::api_types::{DNS_ALIAS_FORMAT, DNS_NAME_FORMAT, DNS_NAME_OR_IP_SCHEMA};
|
||||
pub use proxmox_schema::api_types::{PASSWORD_FORMAT, PASSWORD_SCHEMA};
|
||||
pub use proxmox_schema::api_types::{SERVICE_ID_SCHEMA, UUID_FORMAT};
|
||||
pub use proxmox_schema::api_types::{SYSTEMD_DATETIME_FORMAT, TIME_ZONE_SCHEMA};
|
||||
|
||||
use proxmox_schema::api_types::{DNS_NAME_STR, IPRE_BRACKET_STR};
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! BACKUP_ID_RE { () => (r"[A-Za-z0-9_][A-Za-z0-9._\-]*") }
|
||||
pub const BACKUP_ID_RE: &str = r"[A-Za-z0-9_][A-Za-z0-9._\-]*";
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! BACKUP_TYPE_RE { () => (r"(?:host|vm|ct)") }
|
||||
pub const BACKUP_TYPE_RE: &str = r"(?:host|vm|ct)";
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! BACKUP_TIME_RE { () => (r"[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z") }
|
||||
pub const BACKUP_TIME_RE: &str = r"[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z";
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! BACKUP_NS_RE {
|
||||
() => (
|
||||
concat!("(?:",
|
||||
"(?:", PROXMOX_SAFE_ID_REGEX_STR!(), r"/){0,7}", PROXMOX_SAFE_ID_REGEX_STR!(),
|
||||
")?")
|
||||
pub const BACKUP_NS_RE: &str =
|
||||
concatcp!("(?:",
|
||||
"(?:", PROXMOX_SAFE_ID_REGEX_STR, r"/){0,7}", PROXMOX_SAFE_ID_REGEX_STR,
|
||||
")?");
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub const BACKUP_NS_PATH_RE: &str =
|
||||
concatcp!(r"(?:ns/", PROXMOX_SAFE_ID_REGEX_STR, r"/){0,7}ns/", PROXMOX_SAFE_ID_REGEX_STR, r"/");
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub const SNAPSHOT_PATH_REGEX_STR: &str =
|
||||
concatcp!(
|
||||
r"(", BACKUP_TYPE_RE, ")/(", BACKUP_ID_RE, ")/(", BACKUP_TIME_RE, r")",
|
||||
);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! BACKUP_NS_PATH_RE {
|
||||
() => (
|
||||
concat!(r"(?:ns/", PROXMOX_SAFE_ID_REGEX_STR!(), r"/){0,7}ns/", PROXMOX_SAFE_ID_REGEX_STR!(), r"/")
|
||||
pub const GROUP_OR_SNAPSHOT_PATH_REGEX_STR: &str =
|
||||
concatcp!(
|
||||
r"(", BACKUP_TYPE_RE, ")/(", BACKUP_ID_RE, ")(?:/(", BACKUP_TIME_RE, r"))?",
|
||||
);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! SNAPSHOT_PATH_REGEX_STR {
|
||||
() => (
|
||||
concat!(
|
||||
r"(", BACKUP_TYPE_RE!(), ")/(", BACKUP_ID_RE!(), ")/(", BACKUP_TIME_RE!(), r")",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_export]
|
||||
macro_rules! GROUP_OR_SNAPSHOT_PATH_REGEX_STR {
|
||||
() => {
|
||||
concat!(
|
||||
r"(", BACKUP_TYPE_RE!(), ")/(", BACKUP_ID_RE!(), ")(?:/(", BACKUP_TIME_RE!(), r"))?",
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
mod acl;
|
||||
pub use acl::*;
|
||||
@ -128,102 +145,28 @@ pub use zfs::*;
|
||||
mod metrics;
|
||||
pub use metrics::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[macro_use]
|
||||
mod local_macros {
|
||||
macro_rules! DNS_LABEL { () => (r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") }
|
||||
macro_rules! DNS_NAME { () => (concat!(r"(?:(?:", DNS_LABEL!() , r"\.)*", DNS_LABEL!(), ")")) }
|
||||
macro_rules! CIDR_V4_REGEX_STR { () => (concat!(r"(?:", IPV4RE!(), r"/\d{1,2})$")) }
|
||||
macro_rules! CIDR_V6_REGEX_STR { () => (concat!(r"(?:", IPV6RE!(), r"/\d{1,3})$")) }
|
||||
macro_rules! DNS_ALIAS_LABEL { () => (r"(?:[a-zA-Z0-9_](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") }
|
||||
macro_rules! DNS_ALIAS_NAME {
|
||||
() => (concat!(r"(?:(?:", DNS_ALIAS_LABEL!() , r"\.)*", DNS_ALIAS_LABEL!(), ")"))
|
||||
}
|
||||
macro_rules! PORT_REGEX_STR { () => (r"(?:[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])") }
|
||||
}
|
||||
|
||||
const_regex! {
|
||||
pub IP_V4_REGEX = concat!(r"^", IPV4RE!(), r"$");
|
||||
pub IP_V6_REGEX = concat!(r"^", IPV6RE!(), r"$");
|
||||
pub IP_REGEX = concat!(r"^", IPRE!(), r"$");
|
||||
pub CIDR_V4_REGEX = concat!(r"^", CIDR_V4_REGEX_STR!(), r"$");
|
||||
pub CIDR_V6_REGEX = concat!(r"^", CIDR_V6_REGEX_STR!(), r"$");
|
||||
pub CIDR_REGEX = concat!(r"^(?:", CIDR_V4_REGEX_STR!(), "|", CIDR_V6_REGEX_STR!(), r")$");
|
||||
pub HOSTNAME_REGEX = r"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)$";
|
||||
pub DNS_NAME_REGEX = concat!(r"^", DNS_NAME!(), r"$");
|
||||
pub DNS_ALIAS_REGEX = concat!(r"^", DNS_ALIAS_NAME!(), r"$");
|
||||
pub DNS_NAME_OR_IP_REGEX = concat!(r"^(?:", DNS_NAME!(), "|", IPRE!(), r")$");
|
||||
pub HOST_PORT_REGEX = concat!(r"^(?:", DNS_NAME!(), "|", IPRE_BRACKET!(), "):", PORT_REGEX_STR!() ,"$");
|
||||
pub HTTP_URL_REGEX = concat!(r"^https?://(?:(?:(?:", DNS_NAME!(), "|", IPRE_BRACKET!(), ")(?::", PORT_REGEX_STR!() ,")?)|", IPV6RE!(),")(?:/[^\x00-\x1F\x7F]*)?$");
|
||||
|
||||
pub SHA256_HEX_REGEX = r"^[a-f0-9]{64}$"; // fixme: define in common_regex ?
|
||||
|
||||
pub PASSWORD_REGEX = r"^[[:^cntrl:]]*$"; // everything but control characters
|
||||
|
||||
pub UUID_REGEX = r"^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$";
|
||||
|
||||
pub SYSTEMD_DATETIME_REGEX = r"^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$"; // fixme: define in common_regex ?
|
||||
|
||||
pub FINGERPRINT_SHA256_REGEX = r"^(?:[0-9a-fA-F][0-9a-fA-F])(?::[0-9a-fA-F][0-9a-fA-F]){31}$";
|
||||
|
||||
// just a rough check - dummy acceptor is used before persisting
|
||||
pub OPENSSL_CIPHERS_REGEX = r"^[0-9A-Za-z_:, +!\-@=.]+$";
|
||||
|
||||
/// Regex for safe identifiers.
|
||||
///
|
||||
/// This
|
||||
/// [article](https://dwheeler.com/essays/fixing-unix-linux-filenames.html)
|
||||
/// contains further information why it is reasonable to restict
|
||||
/// names this way. This is not only useful for filenames, but for
|
||||
/// any identifier command line tools work with.
|
||||
pub PROXMOX_SAFE_ID_REGEX = concat!(r"^", PROXMOX_SAFE_ID_REGEX_STR!(), r"$");
|
||||
|
||||
/// Regex that (loosely) matches URIs according to [RFC 2396](https://www.rfc-editor.org/rfc/rfc2396.txt)
|
||||
/// This does not completely match a URI, but rather disallows all the prohibited characters
|
||||
/// specified in the RFC.
|
||||
pub GENERIC_URI_REGEX = r#"^[^\x00-\x1F\x7F <>#"]*$"#;
|
||||
|
||||
pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$";
|
||||
|
||||
pub MULTI_LINE_COMMENT_REGEX = r"(?m)^([[:^cntrl:]]*)$";
|
||||
|
||||
pub BACKUP_REPO_URL_REGEX = concat!(
|
||||
pub BACKUP_REPO_URL_REGEX = concatcp!(
|
||||
r"^^(?:(?:(",
|
||||
USER_ID_REGEX_STR!(), "|", APITOKEN_ID_REGEX_STR!(),
|
||||
USER_ID_REGEX_STR, "|", APITOKEN_ID_REGEX_STR,
|
||||
")@)?(",
|
||||
DNS_NAME!(), "|", IPRE_BRACKET!(),
|
||||
"):)?(?:([0-9]{1,5}):)?(", PROXMOX_SAFE_ID_REGEX_STR!(), r")$"
|
||||
DNS_NAME_STR, "|", IPRE_BRACKET_STR,
|
||||
"):)?(?:([0-9]{1,5}):)?(", PROXMOX_SAFE_ID_REGEX_STR, r")$"
|
||||
);
|
||||
|
||||
pub BLOCKDEVICE_NAME_REGEX = r"^(?:(?:h|s|x?v)d[a-z]+)|(?:nvme\d+n\d+)$";
|
||||
pub BLOCKDEVICE_DISK_AND_PARTITION_NAME_REGEX = r"^(?:(?:h|s|x?v)d[a-z]+\d*)|(?:nvme\d+n\d+(p\d+)?)$";
|
||||
pub SUBSCRIPTION_KEY_REGEX = concat!(r"^pbs(?:[cbsp])-[0-9a-f]{10}$");
|
||||
pub SUBSCRIPTION_KEY_REGEX = concat!(r"^pbs(?:[cbsp])-[0-9a-f]{10}$");
|
||||
}
|
||||
|
||||
pub const IP_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V4_REGEX);
|
||||
pub const IP_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V6_REGEX);
|
||||
pub const IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_REGEX);
|
||||
pub const CIDR_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V4_REGEX);
|
||||
pub const CIDR_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V6_REGEX);
|
||||
pub const CIDR_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_REGEX);
|
||||
pub const PVE_CONFIG_DIGEST_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SHA256_HEX_REGEX);
|
||||
pub const PASSWORD_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PASSWORD_REGEX);
|
||||
pub const UUID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&UUID_REGEX);
|
||||
pub const BLOCKDEVICE_NAME_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::Pattern(&BLOCKDEVICE_NAME_REGEX);
|
||||
pub const BLOCKDEVICE_DISK_AND_PARTITION_NAME_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::Pattern(&BLOCKDEVICE_DISK_AND_PARTITION_NAME_REGEX);
|
||||
|
||||
pub const SUBSCRIPTION_KEY_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::Pattern(&SUBSCRIPTION_KEY_REGEX);
|
||||
pub const SYSTEMD_DATETIME_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::Pattern(&SYSTEMD_DATETIME_REGEX);
|
||||
pub const HOSTNAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HOSTNAME_REGEX);
|
||||
|
||||
pub const OPENSSL_CIPHERS_TLS_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::Pattern(&OPENSSL_CIPHERS_REGEX);
|
||||
pub const HOST_PORT_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HOST_PORT_REGEX);
|
||||
pub const HTTP_URL_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HTTP_URL_REGEX);
|
||||
|
||||
pub const DNS_ALIAS_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_ALIAS_REGEX);
|
||||
|
||||
pub const DAILY_DURATION_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::VerifyFn(|s| parse_daily_duration(s).map(drop));
|
||||
@ -243,10 +186,6 @@ pub const THIRD_DNS_SERVER_SCHEMA: Schema = StringSchema::new("Third name server
|
||||
.format(&IP_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const HOSTNAME_SCHEMA: Schema = StringSchema::new("Hostname (as defined in RFC1123).")
|
||||
.format(&HOSTNAME_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const OPENSSL_CIPHERS_TLS_1_2_SCHEMA: Schema =
|
||||
StringSchema::new("OpenSSL cipher list used by the proxy for TLS <= 1.2")
|
||||
.format(&OPENSSL_CIPHERS_TLS_FORMAT)
|
||||
@ -257,62 +196,6 @@ pub const OPENSSL_CIPHERS_TLS_1_3_SCHEMA: Schema =
|
||||
.format(&OPENSSL_CIPHERS_TLS_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const DNS_NAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_NAME_REGEX);
|
||||
|
||||
pub const DNS_NAME_OR_IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_NAME_OR_IP_REGEX);
|
||||
|
||||
pub const DNS_NAME_OR_IP_SCHEMA: Schema = StringSchema::new("DNS name or IP address.")
|
||||
.format(&DNS_NAME_OR_IP_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const HOST_PORT_SCHEMA: Schema =
|
||||
StringSchema::new("host:port combination (Host can be DNS name or IP address).")
|
||||
.format(&HOST_PORT_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const HTTP_URL_SCHEMA: Schema = StringSchema::new("HTTP(s) url with optional port.")
|
||||
.format(&HTTP_URL_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const NODE_SCHEMA: Schema = StringSchema::new("Node name (or 'localhost')")
|
||||
.format(&HOSTNAME_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const TIME_ZONE_SCHEMA: Schema = StringSchema::new(
|
||||
"Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.",
|
||||
)
|
||||
.format(&SINGLE_LINE_COMMENT_FORMAT)
|
||||
.min_length(2)
|
||||
.max_length(64)
|
||||
.schema();
|
||||
|
||||
pub const BLOCKDEVICE_NAME_SCHEMA: Schema =
|
||||
StringSchema::new("Block device name (/sys/block/<name>).")
|
||||
.format(&BLOCKDEVICE_NAME_FORMAT)
|
||||
.min_length(3)
|
||||
.max_length(64)
|
||||
.schema();
|
||||
|
||||
pub const BLOCKDEVICE_DISK_AND_PARTITION_NAME_SCHEMA: Schema =
|
||||
StringSchema::new("(Partition) block device name (/sys/class/block/<name>).")
|
||||
.format(&BLOCKDEVICE_DISK_AND_PARTITION_NAME_FORMAT)
|
||||
.min_length(3)
|
||||
.max_length(64)
|
||||
.schema();
|
||||
|
||||
pub const DISK_ARRAY_SCHEMA: Schema =
|
||||
ArraySchema::new("Disk name list.", &BLOCKDEVICE_NAME_SCHEMA).schema();
|
||||
|
||||
pub const DISK_LIST_SCHEMA: Schema = StringSchema::new("A list of disk names, comma separated.")
|
||||
.format(&ApiStringFormat::PropertyString(&DISK_ARRAY_SCHEMA))
|
||||
.schema();
|
||||
|
||||
pub const PASSWORD_SCHEMA: Schema = StringSchema::new("Password.")
|
||||
.format(&PASSWORD_FORMAT)
|
||||
.min_length(1)
|
||||
.max_length(1024)
|
||||
.schema();
|
||||
|
||||
pub const PBS_PASSWORD_SCHEMA: Schema = StringSchema::new("User Password.")
|
||||
.format(&PASSWORD_FORMAT)
|
||||
.min_length(5)
|
||||
@ -325,31 +208,6 @@ pub const REALM_ID_SCHEMA: Schema = StringSchema::new("Realm name.")
|
||||
.max_length(32)
|
||||
.schema();
|
||||
|
||||
pub const FINGERPRINT_SHA256_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::Pattern(&FINGERPRINT_SHA256_REGEX);
|
||||
|
||||
pub const CERT_FINGERPRINT_SHA256_SCHEMA: Schema =
|
||||
StringSchema::new("X509 certificate fingerprint (sha256).")
|
||||
.format(&FINGERPRINT_SHA256_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const PROXMOX_SAFE_ID_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX);
|
||||
|
||||
pub const SINGLE_LINE_COMMENT_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::Pattern(&SINGLE_LINE_COMMENT_REGEX);
|
||||
|
||||
pub const SINGLE_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (single line).")
|
||||
.format(&SINGLE_LINE_COMMENT_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const MULTI_LINE_COMMENT_FORMAT: ApiStringFormat =
|
||||
ApiStringFormat::Pattern(&MULTI_LINE_COMMENT_REGEX);
|
||||
|
||||
pub const MULTI_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (multiple lines).")
|
||||
.format(&MULTI_LINE_COMMENT_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const SUBSCRIPTION_KEY_SCHEMA: Schema =
|
||||
StringSchema::new("Proxmox Backup Server subscription key.")
|
||||
.format(&SUBSCRIPTION_KEY_FORMAT)
|
||||
@ -357,8 +215,6 @@ pub const SUBSCRIPTION_KEY_SCHEMA: Schema =
|
||||
.max_length(16)
|
||||
.schema();
|
||||
|
||||
pub const SERVICE_ID_SCHEMA: Schema = StringSchema::new("Service ID.").max_length(256).schema();
|
||||
|
||||
pub const PROXMOX_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new(
|
||||
"Prevent changes if current configuration file has different \
|
||||
SHA256 digest. This can be used to prevent concurrent \
|
||||
|
@ -22,15 +22,19 @@ pub use media_location::*;
|
||||
mod media;
|
||||
pub use media::*;
|
||||
|
||||
use const_format::concatcp;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use proxmox_schema::{api, const_regex, ApiStringFormat, Schema, StringSchema};
|
||||
use proxmox_uuid::Uuid;
|
||||
|
||||
use crate::{BackupType, BACKUP_ID_SCHEMA, FINGERPRINT_SHA256_FORMAT};
|
||||
use crate::{
|
||||
BackupType, BACKUP_ID_SCHEMA, BACKUP_NS_PATH_RE, FINGERPRINT_SHA256_FORMAT,
|
||||
PROXMOX_SAFE_ID_REGEX_STR, SNAPSHOT_PATH_REGEX_STR,
|
||||
};
|
||||
|
||||
const_regex! {
|
||||
pub TAPE_RESTORE_SNAPSHOT_REGEX = concat!(r"^", PROXMOX_SAFE_ID_REGEX_STR!(), r":(?:", BACKUP_NS_PATH_RE!(),")?", SNAPSHOT_PATH_REGEX_STR!(), r"$");
|
||||
pub TAPE_RESTORE_SNAPSHOT_REGEX = concatcp!(r"^", PROXMOX_SAFE_ID_REGEX_STR, r":(?:", BACKUP_NS_PATH_RE,")?", SNAPSHOT_PATH_REGEX_STR, r"$");
|
||||
}
|
||||
|
||||
pub const TAPE_RESTORE_SNAPSHOT_FORMAT: ApiStringFormat =
|
||||
|
@ -89,13 +89,6 @@ pub fn check_netmask(mask: u8, is_v6: bool) -> Result<(), Error> {
|
||||
|
||||
// parse ip address with optional cidr mask
|
||||
pub fn parse_address_or_cidr(cidr: &str) -> Result<(String, Option<u8>, bool), Error> {
|
||||
lazy_static! {
|
||||
pub static ref CIDR_V4_REGEX: Regex =
|
||||
Regex::new(concat!(r"^(", IPV4RE!(), r")(?:/(\d{1,2}))?$")).unwrap();
|
||||
pub static ref CIDR_V6_REGEX: Regex =
|
||||
Regex::new(concat!(r"^(", IPV6RE!(), r")(?:/(\d{1,3}))?$")).unwrap();
|
||||
}
|
||||
|
||||
if let Some(caps) = CIDR_V4_REGEX.captures(cidr) {
|
||||
let address = &caps[1];
|
||||
if let Some(mask) = caps.get(2) {
|
||||
|
@ -192,7 +192,7 @@ impl<R: BufRead> NetworkParser<R> {
|
||||
self.eat(Token::Gateway)?;
|
||||
let gateway = self.next_text()?;
|
||||
|
||||
if pbs_api_types::common_regex::IP_REGEX.is_match(&gateway) {
|
||||
if pbs_api_types::IP_REGEX.is_match(&gateway) {
|
||||
if gateway.contains(':') {
|
||||
set_gateway_v6(interface, gateway)?;
|
||||
} else {
|
||||
|
@ -2,12 +2,14 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
use ::serde::{Deserialize, Serialize};
|
||||
use anyhow::Error;
|
||||
use const_format::concatcp;
|
||||
use lazy_static::lazy_static;
|
||||
use openssl::sha;
|
||||
use regex::Regex;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use pbs_api_types::{IPRE, IPV4OCTET, IPV4RE, IPV6H16, IPV6LS32, IPV6RE};
|
||||
use pbs_api_types::IPRE_STR;
|
||||
|
||||
use proxmox_router::{ApiMethod, Permission, Router, RpcEnvironment};
|
||||
use proxmox_schema::api;
|
||||
use proxmox_sys::fs::{file_get_contents, replace_file, CreateOptions};
|
||||
@ -47,7 +49,7 @@ pub fn read_etc_resolv_conf() -> Result<Value, Error> {
|
||||
lazy_static! {
|
||||
static ref DOMAIN_REGEX: Regex = Regex::new(r"^\s*(?:search|domain)\s+(\S+)\s*").unwrap();
|
||||
static ref SERVER_REGEX: Regex =
|
||||
Regex::new(concat!(r"^\s*nameserver\s+(", IPRE!(), r")\s*")).unwrap();
|
||||
Regex::new(concatcp!(r"^\s*nameserver\s+(", IPRE_STR, r")\s*")).unwrap();
|
||||
}
|
||||
|
||||
let mut options = String::new();
|
||||
|
Loading…
Reference in New Issue
Block a user