move basic ACME types into src/api2/types/acme.rs
And rename AccountName into AcmeAccountName.
This commit is contained in:
@ -1,16 +1,15 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::{bail, format_err, Error};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use proxmox::api::{api, schema::{Schema, StringSchema, ApiStringFormat}};
|
||||
use proxmox::sys::error::SysError;
|
||||
use proxmox::tools::fs::CreateOptions;
|
||||
|
||||
use crate::api2::types::{
|
||||
DNS_ALIAS_FORMAT, DNS_NAME_FORMAT, PROXMOX_SAFE_ID_FORMAT, PROXMOX_SAFE_ID_REGEX,
|
||||
PROXMOX_SAFE_ID_REGEX,
|
||||
KnownAcmeDirectory,
|
||||
AcmeAccountName,
|
||||
};
|
||||
use crate::tools::ControlFlow;
|
||||
|
||||
@ -44,61 +43,6 @@ pub(crate) fn make_acme_account_dir() -> nix::Result<()> {
|
||||
create_acme_subdir(ACME_ACCOUNT_DIR)
|
||||
}
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
"domain": { format: &DNS_NAME_FORMAT },
|
||||
"alias": {
|
||||
optional: true,
|
||||
format: &DNS_ALIAS_FORMAT,
|
||||
},
|
||||
"plugin": {
|
||||
optional: true,
|
||||
format: &PROXMOX_SAFE_ID_FORMAT,
|
||||
},
|
||||
},
|
||||
default_key: "domain",
|
||||
)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
/// A domain entry for an ACME certificate.
|
||||
pub struct AcmeDomain {
|
||||
/// The domain to certify for.
|
||||
pub domain: String,
|
||||
|
||||
/// The domain to use for challenges instead of the default acme challenge domain.
|
||||
///
|
||||
/// This is useful if you use CNAME entries to redirect `_acme-challenge.*` domains to a
|
||||
/// different DNS server.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub alias: Option<String>,
|
||||
|
||||
/// The plugin to use to validate this domain.
|
||||
///
|
||||
/// Empty means standalone HTTP validation is used.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub plugin: Option<String>,
|
||||
}
|
||||
|
||||
pub const ACME_DOMAIN_PROPERTY_SCHEMA: Schema = StringSchema::new(
|
||||
"ACME domain configuration string")
|
||||
.format(&ApiStringFormat::PropertyString(&AcmeDomain::API_SCHEMA))
|
||||
.schema();
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
name: { type: String },
|
||||
url: { type: String },
|
||||
},
|
||||
)]
|
||||
/// An ACME directory endpoint with a name and URL.
|
||||
#[derive(Serialize)]
|
||||
pub struct KnownAcmeDirectory {
|
||||
/// The ACME directory's name.
|
||||
pub name: &'static str,
|
||||
|
||||
/// The ACME directory's endpoint URL.
|
||||
pub url: &'static str,
|
||||
}
|
||||
|
||||
pub const KNOWN_ACME_DIRECTORIES: &[KnownAcmeDirectory] = &[
|
||||
KnownAcmeDirectory {
|
||||
name: "Let's Encrypt V2",
|
||||
@ -116,70 +60,10 @@ pub fn account_path(name: &str) -> String {
|
||||
format!("{}/{}", ACME_ACCOUNT_DIR, name)
|
||||
}
|
||||
|
||||
#[api(format: &PROXMOX_SAFE_ID_FORMAT)]
|
||||
/// ACME account name.
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct AccountName(String);
|
||||
|
||||
impl AccountName {
|
||||
pub fn into_string(self) -> String {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn from_string(name: String) -> Result<Self, Error> {
|
||||
match &Self::API_SCHEMA {
|
||||
Schema::String(s) => s.check_constraints(&name)?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(Self(name))
|
||||
}
|
||||
|
||||
pub unsafe fn from_string_unchecked(name: String) -> Self {
|
||||
Self(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for AccountName {
|
||||
type Target = str;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for AccountName {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut str {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for AccountName {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &str {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for AccountName {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for AccountName {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn foreach_acme_account<F>(mut func: F) -> Result<(), Error>
|
||||
where
|
||||
F: FnMut(AccountName) -> ControlFlow<Result<(), Error>>,
|
||||
F: FnMut(AcmeAccountName) -> ControlFlow<Result<(), Error>>,
|
||||
{
|
||||
match crate::tools::fs::scan_subdir(-1, ACME_ACCOUNT_DIR, &PROXMOX_SAFE_ID_REGEX) {
|
||||
Ok(files) => {
|
||||
@ -191,7 +75,10 @@ where
|
||||
continue;
|
||||
}
|
||||
|
||||
let account_name = AccountName(file_name.to_owned());
|
||||
let account_name = match AcmeAccountName::from_string(file_name.to_owned()) {
|
||||
Ok(account_name) => account_name,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
if let ControlFlow::Break(result) = func(account_name) {
|
||||
return result;
|
||||
|
@ -15,6 +15,8 @@ use crate::api2::types::PROXMOX_SAFE_ID_FORMAT;
|
||||
|
||||
pub const PLUGIN_ID_SCHEMA: Schema = StringSchema::new("ACME Challenge Plugin ID.")
|
||||
.format(&PROXMOX_SAFE_ID_FORMAT)
|
||||
.min_length(1)
|
||||
.max_length(32)
|
||||
.schema();
|
||||
|
||||
lazy_static! {
|
||||
|
@ -10,8 +10,8 @@ use proxmox::api::api;
|
||||
use proxmox::api::schema::{ApiStringFormat, Updater};
|
||||
use proxmox::tools::fs::{replace_file, CreateOptions};
|
||||
|
||||
use crate::api2::types::{AcmeDomain, AcmeAccountName, ACME_DOMAIN_PROPERTY_SCHEMA};
|
||||
use crate::acme::AcmeClient;
|
||||
use crate::config::acme::{AccountName, AcmeDomain, ACME_DOMAIN_PROPERTY_SCHEMA};
|
||||
|
||||
const CONF_FILE: &str = configdir!("/node.cfg");
|
||||
const LOCK_FILE: &str = configdir!("/.node.lck");
|
||||
@ -49,7 +49,7 @@ pub fn save_config(config: &NodeConfig) -> Result<(), Error> {
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
account: { type: AccountName },
|
||||
account: { type: AcmeAccountName },
|
||||
}
|
||||
)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
@ -58,7 +58,7 @@ pub fn save_config(config: &NodeConfig) -> Result<(), Error> {
|
||||
/// Currently only contains the name of the account use.
|
||||
pub struct AcmeConfig {
|
||||
/// Account to use to acquire ACME certificates.
|
||||
account: AccountName,
|
||||
account: AcmeAccountName,
|
||||
}
|
||||
|
||||
#[api(
|
||||
|
Reference in New Issue
Block a user