move basic ACME types into src/api2/types/acme.rs
And rename AccountName into AcmeAccountName.
This commit is contained in:
@ -14,12 +14,11 @@ use proxmox_acme_rs::account::AccountData as AcmeAccountData;
|
||||
use proxmox_acme_rs::Account;
|
||||
|
||||
use crate::acme::AcmeClient;
|
||||
use crate::api2::types::Authid;
|
||||
use crate::config::acl::PRIV_SYS_MODIFY;
|
||||
use crate::config::acme::plugin::{
|
||||
DnsPlugin, DnsPluginCore, DnsPluginCoreUpdater, PLUGIN_ID_SCHEMA,
|
||||
};
|
||||
use crate::config::acme::{AccountName, KnownAcmeDirectory};
|
||||
use crate::api2::types::{Authid, KnownAcmeDirectory, AcmeAccountName};
|
||||
use crate::server::WorkerTask;
|
||||
use crate::tools::ControlFlow;
|
||||
|
||||
@ -65,7 +64,7 @@ const PLUGIN_ITEM_ROUTER: Router = Router::new()
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
name: { type: AccountName },
|
||||
name: { type: AcmeAccountName },
|
||||
},
|
||||
)]
|
||||
/// An ACME Account entry.
|
||||
@ -73,7 +72,7 @@ const PLUGIN_ITEM_ROUTER: Router = Router::new()
|
||||
/// Currently only contains a 'name' property.
|
||||
#[derive(Serialize)]
|
||||
pub struct AccountEntry {
|
||||
name: AccountName,
|
||||
name: AcmeAccountName,
|
||||
}
|
||||
|
||||
#[api(
|
||||
@ -128,7 +127,7 @@ pub struct AccountInfo {
|
||||
#[api(
|
||||
input: {
|
||||
properties: {
|
||||
name: { type: AccountName },
|
||||
name: { type: AcmeAccountName },
|
||||
},
|
||||
},
|
||||
access: {
|
||||
@ -138,7 +137,7 @@ pub struct AccountInfo {
|
||||
protected: true,
|
||||
)]
|
||||
/// Return existing ACME account information.
|
||||
pub async fn get_account(name: AccountName) -> Result<AccountInfo, Error> {
|
||||
pub async fn get_account(name: AcmeAccountName) -> Result<AccountInfo, Error> {
|
||||
let client = AcmeClient::load(&name).await?;
|
||||
let account = client.account()?;
|
||||
Ok(AccountInfo {
|
||||
@ -162,7 +161,7 @@ fn account_contact_from_string(s: &str) -> Vec<String> {
|
||||
input: {
|
||||
properties: {
|
||||
name: {
|
||||
type: AccountName,
|
||||
type: AcmeAccountName,
|
||||
optional: true,
|
||||
},
|
||||
contact: {
|
||||
@ -186,7 +185,7 @@ fn account_contact_from_string(s: &str) -> Vec<String> {
|
||||
)]
|
||||
/// Register an ACME account.
|
||||
fn register_account(
|
||||
name: Option<AccountName>,
|
||||
name: Option<AcmeAccountName>,
|
||||
// Todo: email & email-list schema
|
||||
contact: String,
|
||||
tos_url: Option<String>,
|
||||
@ -196,7 +195,7 @@ fn register_account(
|
||||
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
|
||||
|
||||
let name = name
|
||||
.unwrap_or_else(|| unsafe { AccountName::from_string_unchecked("default".to_string()) });
|
||||
.unwrap_or_else(|| unsafe { AcmeAccountName::from_string_unchecked("default".to_string()) });
|
||||
|
||||
if Path::new(&crate::config::acme::account_path(&name)).exists() {
|
||||
http_bail!(BAD_REQUEST, "account {:?} already exists", name);
|
||||
@ -233,7 +232,7 @@ fn register_account(
|
||||
|
||||
pub async fn do_register_account<'a>(
|
||||
client: &'a mut AcmeClient,
|
||||
name: &AccountName,
|
||||
name: &AcmeAccountName,
|
||||
agree_to_tos: bool,
|
||||
contact: String,
|
||||
rsa_bits: Option<u32>,
|
||||
@ -247,7 +246,7 @@ pub async fn do_register_account<'a>(
|
||||
#[api(
|
||||
input: {
|
||||
properties: {
|
||||
name: { type: AccountName },
|
||||
name: { type: AcmeAccountName },
|
||||
contact: {
|
||||
description: "List of email addresses.",
|
||||
optional: true,
|
||||
@ -261,7 +260,7 @@ pub async fn do_register_account<'a>(
|
||||
)]
|
||||
/// Update an ACME account.
|
||||
pub fn update_account(
|
||||
name: AccountName,
|
||||
name: AcmeAccountName,
|
||||
// Todo: email & email-list schema
|
||||
contact: Option<String>,
|
||||
rpcenv: &mut dyn RpcEnvironment,
|
||||
@ -291,7 +290,7 @@ pub fn update_account(
|
||||
#[api(
|
||||
input: {
|
||||
properties: {
|
||||
name: { type: AccountName },
|
||||
name: { type: AcmeAccountName },
|
||||
force: {
|
||||
description:
|
||||
"Delete account data even if the server refuses to deactivate the account.",
|
||||
@ -307,7 +306,7 @@ pub fn update_account(
|
||||
)]
|
||||
/// Deactivate an ACME account.
|
||||
pub fn deactivate_account(
|
||||
name: AccountName,
|
||||
name: AcmeAccountName,
|
||||
force: bool,
|
||||
rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<String, Error> {
|
||||
|
@ -14,8 +14,8 @@ use proxmox::list_subdirs_api_method;
|
||||
use crate::acme::AcmeClient;
|
||||
use crate::api2::types::Authid;
|
||||
use crate::api2::types::NODE_SCHEMA;
|
||||
use crate::api2::types::AcmeDomain;
|
||||
use crate::config::acl::PRIV_SYS_MODIFY;
|
||||
use crate::config::acme::AcmeDomain;
|
||||
use crate::config::node::NodeConfig;
|
||||
use crate::server::WorkerTask;
|
||||
use crate::tools::cert;
|
||||
|
126
src/api2/types/acme.rs
Normal file
126
src/api2/types/acme.rs
Normal file
@ -0,0 +1,126 @@
|
||||
use std::fmt;
|
||||
|
||||
use anyhow::Error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use proxmox::api::{api, schema::{Schema, StringSchema, ApiStringFormat}};
|
||||
|
||||
use crate::api2::types::{
|
||||
DNS_ALIAS_FORMAT, DNS_NAME_FORMAT, PROXMOX_SAFE_ID_FORMAT,
|
||||
};
|
||||
|
||||
#[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,
|
||||
}
|
||||
|
||||
#[api(format: &PROXMOX_SAFE_ID_FORMAT)]
|
||||
/// ACME account name.
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct AcmeAccountName(String);
|
||||
|
||||
impl AcmeAccountName {
|
||||
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 AcmeAccountName {
|
||||
type Target = str;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for AcmeAccountName {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut str {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for AcmeAccountName {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &str {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for AcmeAccountName {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for AcmeAccountName {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
@ -37,6 +37,9 @@ pub use tape::*;
|
||||
mod file_restore;
|
||||
pub use file_restore::*;
|
||||
|
||||
mod acme;
|
||||
pub use acme::*;
|
||||
|
||||
// File names: may not contain slashes, may not start with "."
|
||||
pub const FILENAME_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|name| {
|
||||
if name.starts_with('.') {
|
||||
|
Reference in New Issue
Block a user