ACME freshness check improvements
This commit is contained in:
13
.github/workflows/ci.yml
vendored
13
.github/workflows/ci.yml
vendored
@@ -150,9 +150,22 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6.0.2
|
uses: actions/checkout@v6.0.2
|
||||||
|
|
||||||
|
- name: Free disk space (heavy ARM targets)
|
||||||
|
if: contains(matrix.target, 'arm')
|
||||||
|
run: |
|
||||||
|
df -h /mnt /
|
||||||
|
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android /usr/local/.ghcup /usr/local/share/powershell /usr/share/swift /opt/hostedtoolcache/CodeQL
|
||||||
|
sudo docker image prune --all --force || true
|
||||||
|
df -h /mnt /
|
||||||
|
|
||||||
- name: Add swap (heavy ARM targets)
|
- name: Add swap (heavy ARM targets)
|
||||||
if: contains(matrix.target, 'arm')
|
if: contains(matrix.target, 'arm')
|
||||||
run: |
|
run: |
|
||||||
|
mnt_avail=$(df --output=avail -k /mnt | tail -1)
|
||||||
|
if [ "$mnt_avail" -lt 18874368 ]; then
|
||||||
|
echo "Insufficient space on /mnt (${mnt_avail}K available), aborting swap setup"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
sudo fallocate -l 16G /mnt/swapfile
|
sudo fallocate -l 16G /mnt/swapfile
|
||||||
sudo chmod 600 /mnt/swapfile
|
sudo chmod 600 /mnt/swapfile
|
||||||
sudo mkswap /mnt/swapfile
|
sudo mkswap /mnt/swapfile
|
||||||
|
|||||||
8
crates/common/src/cache/principals.rs
vendored
8
crates/common/src/cache/principals.rs
vendored
@@ -238,8 +238,8 @@ impl Server {
|
|||||||
.addresses
|
.addresses
|
||||||
.iter()
|
.iter()
|
||||||
.any(|address| {
|
.any(|address| {
|
||||||
address.local_part.as_ref() == local_part
|
address.domain_id == domain_id
|
||||||
&& address.domain_id == domain_id
|
&& address.local_part.as_ref() == local_part
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
EmailCache::Account(item_id)
|
EmailCache::Account(item_id)
|
||||||
@@ -250,8 +250,8 @@ impl Server {
|
|||||||
ObjectType::MailingList => {
|
ObjectType::MailingList => {
|
||||||
if let Some(list) = self.try_list(item_id).await?
|
if let Some(list) = self.try_list(item_id).await?
|
||||||
&& !list.addresses.iter().any(|address| {
|
&& !list.addresses.iter().any(|address| {
|
||||||
address.local_part.as_ref() == local_part
|
address.domain_id == domain_id
|
||||||
&& address.domain_id == domain_id
|
&& address.local_part.as_ref() == local_part
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
EmailCache::DisabledListAddress(item_id)
|
EmailCache::DisabledListAddress(item_id)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ pub enum AcmeError {
|
|||||||
Json(serde_json::Error),
|
Json(serde_json::Error),
|
||||||
Crypto(String),
|
Crypto(String),
|
||||||
Invalid(String),
|
Invalid(String),
|
||||||
|
NotDue(String),
|
||||||
Dns(String),
|
Dns(String),
|
||||||
AuthInvalid(String),
|
AuthInvalid(String),
|
||||||
OrderInvalid(String),
|
OrderInvalid(String),
|
||||||
@@ -257,6 +258,7 @@ impl Display for AcmeError {
|
|||||||
AcmeError::Dns(err) => write!(f, "DNS error: {}", err),
|
AcmeError::Dns(err) => write!(f, "DNS error: {}", err),
|
||||||
AcmeError::Crypto(err) => write!(f, "Cryptographic error: {}", err),
|
AcmeError::Crypto(err) => write!(f, "Cryptographic error: {}", err),
|
||||||
AcmeError::Invalid(err) => write!(f, "Invalid request: {}", err),
|
AcmeError::Invalid(err) => write!(f, "Invalid request: {}", err),
|
||||||
|
AcmeError::NotDue(err) => write!(f, "{}", err),
|
||||||
AcmeError::AuthInvalid(status) => write!(f, "Authentication failed: {:?}", status),
|
AcmeError::AuthInvalid(status) => write!(f, "Authentication failed: {:?}", status),
|
||||||
AcmeError::OrderTimeout { .. } => write!(f, "Order processing timed out"),
|
AcmeError::OrderTimeout { .. } => write!(f, "Order processing timed out"),
|
||||||
AcmeError::OrderInvalid(reason) => write!(f, "Order is invalid: {}", reason),
|
AcmeError::OrderInvalid(reason) => write!(f, "Order is invalid: {}", reason),
|
||||||
|
|||||||
@@ -65,10 +65,11 @@ impl Server {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if let Some(renew_at) = self.acme_certificate_renewal_due(&domains, renew_before, now()) {
|
if let Some(renew_at) = self.acme_certificate_renewal_due(&domains, renew_before, now()) {
|
||||||
return Ok(vec![Task::AcmeRenewal(TaskDomainManagement {
|
return Err(AcmeError::NotDue(format!(
|
||||||
domain_id,
|
"Certificate for domain {} is still valid; renewal is not due until {}",
|
||||||
status: TaskStatus::at(renew_at as i64),
|
domain.name,
|
||||||
})]);
|
UTCDateTime::from_timestamp(renew_at as i64)
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let dns_parameters = match &domain.dns_management {
|
let dns_parameters = match &domain.dns_management {
|
||||||
@@ -168,29 +169,15 @@ impl Server {
|
|||||||
self.cluster_broadcast(BroadcastEvent::RegistryChange(change))
|
self.cluster_broadcast(BroadcastEvent::RegistryChange(change))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Schedule next renewal
|
|
||||||
let mut tasks = Vec::new();
|
let mut tasks = Vec::new();
|
||||||
let renew_in = match renew_before {
|
let renew_at = Self::acme_renewal_due_at(
|
||||||
AcmeRenewBefore::R12 => {
|
parsed_cert.valid_not_before.timestamp(),
|
||||||
// 1/2 of the remaining time until expiration
|
parsed_cert.valid_not_after.timestamp(),
|
||||||
expires_in / 2
|
renew_before,
|
||||||
}
|
);
|
||||||
AcmeRenewBefore::R23 => {
|
|
||||||
// 2/3 of the remaining time until expiration
|
|
||||||
expires_in * 2 / 3
|
|
||||||
}
|
|
||||||
AcmeRenewBefore::R34 => {
|
|
||||||
// 3/4 of the remaining time until expiration
|
|
||||||
expires_in * 3 / 4
|
|
||||||
}
|
|
||||||
AcmeRenewBefore::R45 => {
|
|
||||||
// 4/5 of the remaining time until expiration
|
|
||||||
expires_in * 4 / 5
|
|
||||||
}
|
|
||||||
};
|
|
||||||
tasks.push(Task::AcmeRenewal(TaskDomainManagement {
|
tasks.push(Task::AcmeRenewal(TaskDomainManagement {
|
||||||
domain_id,
|
domain_id,
|
||||||
status: TaskStatus::at((now + renew_in) as i64),
|
status: TaskStatus::at(renew_at),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Update TLSA records
|
// Update TLSA records
|
||||||
@@ -245,14 +232,8 @@ impl Server {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let not_valid_before = parsed.valid_not_before.timestamp();
|
let not_valid_before = parsed.valid_not_before.timestamp();
|
||||||
let total = not_valid_after.saturating_sub(not_valid_before);
|
let renew_at =
|
||||||
let (numerator, denominator) = match renew_before {
|
Self::acme_renewal_due_at(not_valid_before, not_valid_after, renew_before);
|
||||||
AcmeRenewBefore::R12 => (1, 2),
|
|
||||||
AcmeRenewBefore::R23 => (2, 3),
|
|
||||||
AcmeRenewBefore::R34 => (3, 4),
|
|
||||||
AcmeRenewBefore::R45 => (4, 5),
|
|
||||||
};
|
|
||||||
let renew_at = not_valid_before + total * numerator / denominator;
|
|
||||||
return if now < renew_at {
|
return if now < renew_at {
|
||||||
Some(renew_at as u64)
|
Some(renew_at as u64)
|
||||||
} else {
|
} else {
|
||||||
@@ -262,4 +243,19 @@ impl Server {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn acme_renewal_due_at(
|
||||||
|
not_valid_before: i64,
|
||||||
|
not_valid_after: i64,
|
||||||
|
renew_before: AcmeRenewBefore,
|
||||||
|
) -> i64 {
|
||||||
|
let total = not_valid_after.saturating_sub(not_valid_before);
|
||||||
|
let (numerator, denominator) = match renew_before {
|
||||||
|
AcmeRenewBefore::R12 => (1, 2),
|
||||||
|
AcmeRenewBefore::R23 => (2, 3),
|
||||||
|
AcmeRenewBefore::R34 => (3, 4),
|
||||||
|
AcmeRenewBefore::R45 => (4, 5),
|
||||||
|
};
|
||||||
|
not_valid_before + total * numerator / denominator
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ async fn acme_management(server: &Server, task: &TaskDomainManagement) -> trc::R
|
|||||||
Err(err) => match err {
|
Err(err) => match err {
|
||||||
AcmeError::Crypto(_)
|
AcmeError::Crypto(_)
|
||||||
| AcmeError::Invalid(_)
|
| AcmeError::Invalid(_)
|
||||||
|
| AcmeError::NotDue(_)
|
||||||
| AcmeError::ChallengeNotSupported { .. }
|
| AcmeError::ChallengeNotSupported { .. }
|
||||||
| AcmeError::OrderInvalid(_)
|
| AcmeError::OrderInvalid(_)
|
||||||
| AcmeError::Json(_)
|
| AcmeError::Json(_)
|
||||||
|
|||||||
Reference in New Issue
Block a user