bonsaidb_server/server/
acme.rs1use std::sync::Arc;
2use std::time::Duration;
3
4use async_acme::cache::AcmeCache;
5use async_trait::async_trait;
6use bonsaidb_core::arc_bytes::serde::Bytes;
7use bonsaidb_core::connection::AsyncConnection;
8use bonsaidb_core::define_basic_unique_mapped_view;
9use bonsaidb_core::document::{CollectionDocument, Emit, KeyId};
10use bonsaidb_core::schema::{Collection, SerializedCollection};
11use serde::{Deserialize, Serialize};
12
13use crate::{Backend, CustomServer, Error};
14
15#[derive(Clone, Debug, Serialize, Deserialize, Collection)]
16#[collection(name = "acme-accounts", authority = "khonsulabs", views = [AcmeAccountByContacts])]
17#[collection(encryption_key = Some(KeyId::Master), encryption_optional, core = bonsaidb_core)]
18pub struct AcmeAccount {
19 pub contacts: Vec<String>,
20 pub data: Bytes,
21}
22
23define_basic_unique_mapped_view!(
24 AcmeAccountByContacts,
25 AcmeAccount,
26 1,
27 "by-contacts",
28 String,
29 |document: CollectionDocument<AcmeAccount>| {
30 document
31 .header
32 .emit_key(document.contents.contacts.join(";"))
33 }
34);
35
36#[async_trait]
37impl<B: Backend> AcmeCache for CustomServer<B> {
38 type Error = Error;
39
40 async fn read_account(&self, contacts: &[&str]) -> Result<Option<Vec<u8>>, Self::Error> {
41 let db = self.hosted().await;
42 let contact = db
43 .view::<AcmeAccountByContacts>()
44 .with_key(&contacts.join(";"))
45 .query_with_collection_docs()
46 .await?
47 .documents
48 .into_iter()
49 .next();
50
51 if let Some((_, contact)) = contact {
52 Ok(Some(contact.contents.data.into_vec()))
53 } else {
54 Ok(None)
55 }
56 }
57
58 async fn write_account(&self, contacts: &[&str], contents: &[u8]) -> Result<(), Self::Error> {
59 let db = self.hosted().await;
60 let mapped_account = db
61 .view::<AcmeAccountByContacts>()
62 .with_key(&contacts.join(";"))
63 .query_with_collection_docs()
64 .await?
65 .documents
66 .into_iter()
67 .next();
68 if let Some((_, mut account)) = mapped_account {
69 account.contents.data = Bytes::from(contents);
70 account.update_async(&db).await?;
71 } else {
72 AcmeAccount {
73 contacts: contacts.iter().map(|&c| c.to_string()).collect(),
74 data: Bytes::from(contents),
75 }
76 .push_into_async(&db)
77 .await?;
78 }
79
80 Ok(())
81 }
82
83 async fn write_certificate(
84 &self,
85 _domains: &[String],
86 _directory_url: &str,
87 key_pem: &str,
88 certificate_pem: &str,
89 ) -> Result<(), Self::Error> {
90 self.install_pem_certificate(certificate_pem.as_bytes(), key_pem.as_bytes())
91 .await
92 }
93}
94
95impl<B: Backend> CustomServer<B> {
96 pub(crate) async fn update_acme_certificates(&self) -> Result<(), Error> {
97 loop {
98 {
99 let key = self.data.primary_tls_key.lock().clone();
100 while async_acme::rustls_helper::duration_until_renewal_attempt(key.as_deref(), 0)
101 > Duration::from_secs(24 * 60 * 60 * 14)
102 {
103 tokio::time::sleep(Duration::from_secs(60 * 60)).await;
104 }
105 }
106
107 log::info!(
108 "requesting new tls certificate for {}",
109 self.data.primary_domain
110 );
111 let domains = vec![self.data.primary_domain.clone()];
112 async_acme::rustls_helper::order(
113 |domain, key| {
114 let mut auth_keys = self.data.alpn_keys.lock();
115 auth_keys.insert(domain, Arc::new(key));
116 Ok(())
117 },
118 &self.data.acme.directory,
119 &domains,
120 Some(self),
121 &self
122 .data
123 .acme
124 .contact_email
125 .iter()
126 .cloned()
127 .collect::<Vec<_>>(),
128 )
129 .await?;
130 }
131 }
132}