acme: use proxmox-acme-plugins and load schema from there
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
60643023ad
commit
d308dc8af7
1
debian/control
vendored
1
debian/control
vendored
@ -113,6 +113,7 @@ Architecture: any
|
||||
Depends: fonts-font-awesome,
|
||||
libjs-extjs (>= 6.0.1),
|
||||
libjs-qrcodejs (>= 1.20201119),
|
||||
libproxmox-acme-plugins,
|
||||
libsgutils2-2,
|
||||
libzstd1 (>= 1.3.8),
|
||||
lvm2,
|
||||
|
1
debian/control.in
vendored
1
debian/control.in
vendored
@ -3,6 +3,7 @@ Architecture: any
|
||||
Depends: fonts-font-awesome,
|
||||
libjs-extjs (>= 6.0.1),
|
||||
libjs-qrcodejs (>= 1.20201119),
|
||||
libproxmox-acme-plugins,
|
||||
libsgutils2-2,
|
||||
libzstd1 (>= 1.3.8),
|
||||
lvm2,
|
||||
|
@ -1,6 +1,10 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::SystemTime;
|
||||
|
||||
use anyhow::{bail, format_err, Error};
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
|
||||
@ -386,6 +390,43 @@ fn get_directories() -> Result<&'static [KnownAcmeDirectory], Error> {
|
||||
Ok(crate::config::acme::KNOWN_ACME_DIRECTORIES)
|
||||
}
|
||||
|
||||
/// Wrapper for efficient Arc use when returning the ACME challenge-plugin schema for serializing
|
||||
struct ChallengeSchemaWrapper {
|
||||
inner: Arc<Vec<AcmeChallengeSchema>>,
|
||||
}
|
||||
|
||||
impl Serialize for ChallengeSchemaWrapper {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
self.inner.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cached_challenge_schemas() -> Result<ChallengeSchemaWrapper, Error> {
|
||||
lazy_static! {
|
||||
static ref CACHE: Mutex<Option<(Arc<Vec<AcmeChallengeSchema>>, SystemTime)>> =
|
||||
Mutex::new(None);
|
||||
}
|
||||
|
||||
// the actual loading code
|
||||
let mut last = CACHE.lock().unwrap();
|
||||
|
||||
let actual_mtime = fs::metadata(crate::config::acme::ACME_DNS_SCHEMA_FN)?.modified()?;
|
||||
|
||||
let schema = match &*last {
|
||||
Some((schema, cached_mtime)) if *cached_mtime >= actual_mtime => schema.clone(),
|
||||
_ => {
|
||||
let new_schema = Arc::new(crate::config::acme::load_dns_challenge_schema()?);
|
||||
*last = Some((Arc::clone(&new_schema), actual_mtime));
|
||||
new_schema
|
||||
}
|
||||
};
|
||||
|
||||
Ok(ChallengeSchemaWrapper { inner: schema })
|
||||
}
|
||||
|
||||
#[api(
|
||||
access: {
|
||||
permission: &Permission::Anybody,
|
||||
@ -397,18 +438,8 @@ fn get_directories() -> Result<&'static [KnownAcmeDirectory], Error> {
|
||||
},
|
||||
)]
|
||||
/// Get named known ACME directory endpoints.
|
||||
fn get_challenge_schema() -> Result<Vec<AcmeChallengeSchema>, Error> {
|
||||
let mut out = Vec::new();
|
||||
crate::config::acme::foreach_dns_plugin(|id| {
|
||||
out.push(AcmeChallengeSchema {
|
||||
id: id.to_owned(),
|
||||
name: id.to_owned(),
|
||||
ty: "dns",
|
||||
schema: Value::Object(Default::default()),
|
||||
});
|
||||
ControlFlow::Continue(())
|
||||
})?;
|
||||
Ok(out)
|
||||
fn get_challenge_schema() -> Result<ChallengeSchemaWrapper, Error> {
|
||||
get_cached_challenge_schemas()
|
||||
}
|
||||
|
||||
#[api]
|
||||
|
@ -2,12 +2,14 @@ use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::{bail, format_err, Error};
|
||||
use serde_json::Value;
|
||||
|
||||
use proxmox::sys::error::SysError;
|
||||
use proxmox::tools::fs::CreateOptions;
|
||||
use proxmox::tools::fs::{CreateOptions, file_read_string};
|
||||
|
||||
use crate::api2::types::{
|
||||
PROXMOX_SAFE_ID_REGEX,
|
||||
AcmeChallengeSchema,
|
||||
KnownAcmeDirectory,
|
||||
AcmeAccountName,
|
||||
};
|
||||
@ -16,6 +18,8 @@ use crate::tools::ControlFlow;
|
||||
pub(crate) const ACME_DIR: &str = configdir!("/acme");
|
||||
pub(crate) const ACME_ACCOUNT_DIR: &str = configdir!("/acme/accounts");
|
||||
|
||||
pub(crate) const ACME_DNS_SCHEMA_FN: &str = "/usr/share/proxmox-acme/dns-challenge-schema.json";
|
||||
|
||||
pub mod plugin;
|
||||
|
||||
// `const fn`ify this once it is supported in `proxmox`
|
||||
@ -141,6 +145,25 @@ pub fn mark_account_deactivated(name: &str) -> Result<(), Error> {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn load_dns_challenge_schema() -> Result<Vec<AcmeChallengeSchema>, Error> {
|
||||
let raw = file_read_string(&ACME_DNS_SCHEMA_FN)?;
|
||||
let schemas: serde_json::Map<String, Value> = serde_json::from_str(&raw)?;
|
||||
|
||||
Ok(schemas
|
||||
.iter()
|
||||
.map(|(id, schema)| AcmeChallengeSchema {
|
||||
id: id.to_owned(),
|
||||
name: schema
|
||||
.get("name")
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or(id)
|
||||
.to_owned(),
|
||||
ty: "dns",
|
||||
schema: schema.to_owned(),
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn complete_acme_account(_arg: &str, _param: &HashMap<String, String>) -> Vec<String> {
|
||||
let mut out = Vec::new();
|
||||
let _ = foreach_acme_account(|name| {
|
||||
|
Loading…
Reference in New Issue
Block a user