mirror of
https://github.com/rkivalin/certforge.git
synced 2026-10-12 16:00:45 +00:00
Add packaging, CI, and license
- MIT license - Arch Linux PKGBUILD - Debian packaging (debian/) - GitHub Actions: CI (test + clippy) and release workflow builds x86_64 + aarch64 binaries, Arch and Debian packages - Default config is now no-op (certificate blocks commented out) - Fix clippy warnings (collapsible ifs, redundant closures) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
32697369cf
commit
1c517ecbab
@@ -0,0 +1,17 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- run: cargo test --locked
|
||||
- run: cargo clippy --locked -- -D warnings
|
||||
@@ -0,0 +1,190 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
os: ubuntu-latest
|
||||
arch: amd64
|
||||
- target: aarch64-unknown-linux-gnu
|
||||
os: ubuntu-latest
|
||||
arch: arm64
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Install Rust toolchain
|
||||
run: |
|
||||
rustup toolchain install stable --profile minimal
|
||||
rustup target add "${{ matrix.target }}"
|
||||
|
||||
- name: Install cross-compilation tools
|
||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc-aarch64-linux-gnu
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||
run: cargo build --release --locked --target "${{ matrix.target }}"
|
||||
|
||||
- name: Run tests
|
||||
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
||||
run: cargo test --locked
|
||||
|
||||
- name: Package binary
|
||||
run: |
|
||||
cd "target/${{ matrix.target }}/release"
|
||||
tar czf "../../../certforge-${{ matrix.arch }}.tar.gz" certforge
|
||||
cd ../../..
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: certforge-${{ matrix.arch }}
|
||||
path: certforge-${{ matrix.arch }}.tar.gz
|
||||
|
||||
package-archlinux:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
container: archlinux:base-devel
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86_64
|
||||
artifact: amd64
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pacman -Syu --noconfirm rust
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
# makepkg can't run as root, create a build user
|
||||
useradd -m builder
|
||||
chown -R builder:builder .
|
||||
# Adjust PKGBUILD source to use local files
|
||||
cd /tmp
|
||||
VERSION=${GITHUB_REF_NAME#v}
|
||||
mkdir -p "certforge-$VERSION"
|
||||
cp -a "$GITHUB_WORKSPACE"/* "certforge-$VERSION/"
|
||||
tar czf "certforge-$VERSION.tar.gz" "certforge-$VERSION"
|
||||
cp "$GITHUB_WORKSPACE/PKGBUILD" .
|
||||
sed -i "s|pkgver=.*|pkgver=$VERSION|" PKGBUILD
|
||||
sed -i "s|source=.*|source=(\"certforge-$VERSION.tar.gz\")|" PKGBUILD
|
||||
chown -R builder:builder /tmp/certforge-* /tmp/PKGBUILD
|
||||
su builder -c 'makepkg -s --noconfirm --skipinteg'
|
||||
cp /tmp/*.pkg.tar.zst "$GITHUB_WORKSPACE/"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: archlinux-package
|
||||
path: "*.pkg.tar.zst"
|
||||
|
||||
package-debian:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- arch: arm64
|
||||
target: aarch64-unknown-linux-gnu
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Download binary
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: certforge-${{ matrix.arch }}
|
||||
|
||||
- name: Build .deb
|
||||
run: |
|
||||
VERSION=${GITHUB_REF_NAME#v}
|
||||
PKG=certforge_${VERSION}-1_${{ matrix.arch }}
|
||||
mkdir -p "$PKG/DEBIAN"
|
||||
mkdir -p "$PKG/usr/bin"
|
||||
mkdir -p "$PKG/usr/lib/systemd/system"
|
||||
mkdir -p "$PKG/etc/certforge/certs"
|
||||
|
||||
tar xzf "certforge-${{ matrix.arch }}.tar.gz"
|
||||
install -Dm755 certforge "$PKG/usr/bin/certforge"
|
||||
install -Dm644 examples/certforge.service "$PKG/usr/lib/systemd/system/certforge.service"
|
||||
install -Dm644 examples/certforge.timer "$PKG/usr/lib/systemd/system/certforge.timer"
|
||||
install -Dm644 examples/config.toml "$PKG/etc/certforge/config.toml"
|
||||
|
||||
cat >"$PKG/DEBIAN/control" <<CTRL
|
||||
Package: certforge
|
||||
Version: ${VERSION}-1
|
||||
Architecture: ${{ matrix.arch }}
|
||||
Maintainer: Roman Kivalin <roman@shl.dev>
|
||||
Depends: systemd
|
||||
Section: admin
|
||||
Priority: optional
|
||||
Description: ACME certificate manager with DANE and systemd integration
|
||||
Certforge automates ACME certificate issuance and renewal using DNS-01
|
||||
challenges via RFC 2136 dynamic DNS updates with DANE TLSA support.
|
||||
CTRL
|
||||
|
||||
echo "/etc/certforge/config.toml" >"$PKG/DEBIAN/conffiles"
|
||||
|
||||
dpkg-deb --build --root-owner-group "$PKG"
|
||||
mv "${PKG}.deb" "certforge_${VERSION}-1_${{ matrix.arch }}.deb"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: debian-${{ matrix.arch }}
|
||||
path: "*.deb"
|
||||
|
||||
release:
|
||||
needs: [build, package-archlinux, package-debian]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Create release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
VERSION=${GITHUB_REF_NAME#v}
|
||||
# Collect all release files
|
||||
mkdir release
|
||||
cp artifacts/certforge-amd64/certforge-amd64.tar.gz release/
|
||||
cp artifacts/certforge-arm64/certforge-arm64.tar.gz release/
|
||||
cp artifacts/archlinux-package/*.pkg.tar.zst release/ || true
|
||||
cp artifacts/debian-amd64/*.deb release/ || true
|
||||
cp artifacts/debian-arm64/*.deb release/ || true
|
||||
|
||||
# Generate checksums
|
||||
cd release
|
||||
sha256sum * >SHA256SUMS
|
||||
cd ..
|
||||
|
||||
gh release create "${GITHUB_REF_NAME}" \
|
||||
--title "certforge ${VERSION}" \
|
||||
--generate-notes \
|
||||
release/*
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Roman Kivalin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Maintainer: Roman Kivalin <roman@shl.dev>
|
||||
pkgname=certforge
|
||||
pkgver=0.1.0
|
||||
pkgrel=1
|
||||
pkgdesc='ACME certificate manager with DANE and systemd integration'
|
||||
arch=('x86_64' 'aarch64')
|
||||
url='https://github.com/rkivalin/certforge'
|
||||
license=('MIT')
|
||||
depends=('systemd-libs')
|
||||
makedepends=('cargo')
|
||||
backup=('etc/certforge/config.toml')
|
||||
source=("$pkgname-$pkgver.tar.gz")
|
||||
sha256sums=('SKIP')
|
||||
|
||||
prepare() {
|
||||
cd "$pkgname-$pkgver"
|
||||
export RUSTUP_TOOLCHAIN=stable
|
||||
cargo fetch --locked --target "$( rustc -vV | sed -n 's/host: //p' )"
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$pkgname-$pkgver"
|
||||
export RUSTUP_TOOLCHAIN=stable
|
||||
export CARGO_TARGET_DIR=target
|
||||
cargo build --frozen --release
|
||||
}
|
||||
|
||||
check() {
|
||||
cd "$pkgname-$pkgver"
|
||||
export RUSTUP_TOOLCHAIN=stable
|
||||
export CARGO_TARGET_DIR=target
|
||||
cargo test --frozen
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$pkgname-$pkgver"
|
||||
|
||||
install -Dm755 "target/release/$pkgname" "$pkgdir/usr/bin/$pkgname"
|
||||
|
||||
install -Dm644 examples/certforge.service "$pkgdir/usr/lib/systemd/system/certforge.service"
|
||||
install -Dm644 examples/certforge.timer "$pkgdir/usr/lib/systemd/system/certforge.timer"
|
||||
|
||||
install -Dm644 examples/config.toml "$pkgdir/etc/certforge/config.toml"
|
||||
|
||||
install -dm750 "$pkgdir/etc/certforge/certs"
|
||||
install -dm700 "$pkgdir/var/lib/certforge"
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
certforge (0.1.0-1) unstable; urgency=low
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Roman Kivalin <roman@shl.dev> Sat, 12 Apr 2026 18:00:00 +0000
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/etc/certforge/config.toml
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
Source: certforge
|
||||
Section: admin
|
||||
Priority: optional
|
||||
Maintainer: Roman Kivalin <roman@shl.dev>
|
||||
Build-Depends: debhelper-compat (= 13), cargo, rustc
|
||||
Standards-Version: 4.6.2
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: certforge
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, systemd
|
||||
Description: ACME certificate manager with DANE and systemd integration
|
||||
Certforge automates ACME certificate issuance and renewal using DNS-01
|
||||
challenges via RFC 2136 dynamic DNS updates. It publishes DANE TLSA
|
||||
records, integrates with systemd credentials for secret storage, and
|
||||
supports post-renewal hooks to reload/restart services.
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
|
||||
Files: *
|
||||
Copyright: 2026 Roman Kivalin
|
||||
License: MIT
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/make -f
|
||||
export CARGO_HOME = $(CURDIR)/debian/cargo_home
|
||||
export RUSTUP_TOOLCHAIN = stable
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_auto_build:
|
||||
cargo build --release --frozen
|
||||
|
||||
override_dh_auto_test:
|
||||
cargo test --release --frozen
|
||||
|
||||
override_dh_auto_install:
|
||||
install -Dm755 target/release/certforge debian/certforge/usr/bin/certforge
|
||||
install -Dm644 examples/certforge.service debian/certforge/usr/lib/systemd/system/certforge.service
|
||||
install -Dm644 examples/certforge.timer debian/certforge/usr/lib/systemd/system/certforge.timer
|
||||
install -Dm644 examples/config.toml debian/certforge/etc/certforge/config.toml
|
||||
install -dm750 debian/certforge/etc/certforge/certs
|
||||
install -dm700 debian/certforge/var/lib/certforge
|
||||
|
||||
override_dh_auto_clean:
|
||||
cargo clean || true
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
||||
+52
-61
@@ -1,6 +1,8 @@
|
||||
# Example certforge configuration
|
||||
# Certforge configuration
|
||||
#
|
||||
# Full documentation: see the project README
|
||||
# This is a reference configuration. Uncomment and adjust the sections
|
||||
# below to match your environment. No certificates will be managed
|
||||
# until at least one [[certificate]] block is uncommented.
|
||||
|
||||
[acme]
|
||||
directory_url = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
@@ -8,18 +10,18 @@ directory_url = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
# directory_url = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
|
||||
# ACME account key: stored as encrypted systemd credential
|
||||
account_key_credential = "/etc/credstore.encrypted/acme-account-key"
|
||||
# account_key_credential = "/etc/credstore.encrypted/acme-account-key"
|
||||
# Or as a plain file:
|
||||
# account_key_path = "/etc/certforge/account.key"
|
||||
account_key_path = "/etc/certforge/account.key"
|
||||
|
||||
contact = ["mailto:admin@example.com"]
|
||||
|
||||
# Default DNS server for RFC 2136 updates
|
||||
[dns.defaults]
|
||||
server = "ns1.example.com"
|
||||
tsig_key_credential = "/etc/credstore.encrypted/dns-tsig-key"
|
||||
# tsig_key_path = "/etc/certforge/tsig.key"
|
||||
tsig_key_name = "certforge-update."
|
||||
# tsig_key_credential = "/etc/credstore.encrypted/dns-tsig-key"
|
||||
tsig_key_path = "/etc/certforge/tsig.key"
|
||||
tsig_key_name = "certforge."
|
||||
tsig_algorithm = "hmac-sha256"
|
||||
port = 53
|
||||
protocol = "tcp"
|
||||
@@ -29,57 +31,46 @@ protocol = "tcp"
|
||||
# server = "ns2.example.org"
|
||||
# tsig_key_credential = "/etc/credstore.encrypted/dns-tsig-org"
|
||||
|
||||
# Mail server certificate
|
||||
[[certificate]]
|
||||
name = "mail"
|
||||
domains = ["mail.example.com"]
|
||||
key_type = "ecdsa-p256"
|
||||
key_credential = "/etc/credstore.encrypted/mail-tls-key"
|
||||
cert_path = "/etc/certforge/certs/mail.pem"
|
||||
renew_before_days = 30
|
||||
rotate_key = false
|
||||
|
||||
# DANE TLSA for SMTP (port 25)
|
||||
[[certificate.dane]]
|
||||
usage = "ee"
|
||||
selector = "spki"
|
||||
matching = "sha256"
|
||||
names = ["_25._tcp.mail.example.com"]
|
||||
ttl = 300
|
||||
pre_publish = true
|
||||
|
||||
# DANE TLSA for IMAP (port 993)
|
||||
[[certificate.dane]]
|
||||
usage = "ee"
|
||||
selector = "spki"
|
||||
matching = "sha256"
|
||||
names = ["_993._tcp.mail.example.com"]
|
||||
ttl = 300
|
||||
|
||||
[[certificate.hook]]
|
||||
type = "systemd-reload"
|
||||
unit = "postfix.service"
|
||||
|
||||
[[certificate.hook]]
|
||||
type = "systemd-restart"
|
||||
unit = "dovecot.service"
|
||||
|
||||
# Web server certificate
|
||||
[[certificate]]
|
||||
name = "web"
|
||||
domains = ["example.com", "www.example.com"]
|
||||
key_type = "ecdsa-p256"
|
||||
key_credential = "/etc/credstore.encrypted/web-tls-key"
|
||||
cert_path = "/etc/certforge/certs/web.pem"
|
||||
renew_before_days = 30
|
||||
|
||||
[[certificate.dane]]
|
||||
usage = "ee"
|
||||
selector = "spki"
|
||||
matching = "sha256"
|
||||
names = ["_443._tcp.example.com", "_443._tcp.www.example.com"]
|
||||
ttl = 3600
|
||||
|
||||
[[certificate.hook]]
|
||||
type = "systemd-reload"
|
||||
unit = "nginx.service"
|
||||
# Uncomment and configure certificate blocks below.
|
||||
#
|
||||
# [[certificate]]
|
||||
# name = "mail"
|
||||
# domains = ["mail.example.com"]
|
||||
# key_type = "ecdsa-p256"
|
||||
# key_credential = "/etc/credstore.encrypted/mail-tls-key"
|
||||
# # key_path = "/etc/certforge/keys/mail.key"
|
||||
# cert_path = "/etc/certforge/certs/mail.pem"
|
||||
# renew_before_days = 30
|
||||
# rotate_key = false
|
||||
#
|
||||
# # DANE TLSA for SMTP (port 25)
|
||||
# [[certificate.dane]]
|
||||
# usage = "ee"
|
||||
# selector = "spki"
|
||||
# matching = "sha256"
|
||||
# names = ["_25._tcp.mail.example.com"]
|
||||
# ttl = 300
|
||||
# pre_publish = true
|
||||
#
|
||||
# [[certificate.hook]]
|
||||
# type = "systemd-reload"
|
||||
# unit = "postfix.service"
|
||||
#
|
||||
# [[certificate]]
|
||||
# name = "web"
|
||||
# domains = ["example.com", "www.example.com"]
|
||||
# key_type = "ecdsa-p256"
|
||||
# key_credential = "/etc/credstore.encrypted/web-tls-key"
|
||||
# cert_path = "/etc/certforge/certs/web.pem"
|
||||
# renew_before_days = 30
|
||||
#
|
||||
# [[certificate.dane]]
|
||||
# usage = "ee"
|
||||
# selector = "spki"
|
||||
# matching = "sha256"
|
||||
# names = ["_443._tcp.example.com", "_443._tcp.www.example.com"]
|
||||
# ttl = 3600
|
||||
#
|
||||
# [[certificate.hook]]
|
||||
# type = "systemd-reload"
|
||||
# unit = "nginx.service"
|
||||
|
||||
+2
-2
@@ -39,7 +39,7 @@ impl AcmeClient {
|
||||
Error::Config(format!("invalid account credentials: {e}"))
|
||||
})?;
|
||||
let account = Account::builder()
|
||||
.map_err(|e| Error::Acme(e))?
|
||||
.map_err(Error::Acme)?
|
||||
.from_credentials(creds)
|
||||
.await?;
|
||||
tracing::info!(id = %account.id(), "loaded existing ACME account");
|
||||
@@ -48,7 +48,7 @@ impl AcmeClient {
|
||||
Err(_) => {
|
||||
tracing::info!(directory = %config.directory_url, "creating new ACME account");
|
||||
let (account, creds) = Account::builder()
|
||||
.map_err(|e| Error::Acme(e))?
|
||||
.map_err(Error::Acme)?
|
||||
.create(
|
||||
&NewAccount {
|
||||
contact: &config
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ use crate::error::{Error, Result};
|
||||
pub struct Config {
|
||||
pub acme: AcmeConfig,
|
||||
pub dns: DnsConfig,
|
||||
#[serde(rename = "certificate")]
|
||||
#[serde(rename = "certificate", default)]
|
||||
pub certificates: Vec<CertificateConfig>,
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ pub async fn publish_tlsa(
|
||||
let zone = find_zone(&name)?;
|
||||
|
||||
updater
|
||||
.replace_tlsa_records(&zone, &name, &[record.clone()], dane.ttl)
|
||||
.replace_tlsa_records(&zone, &name, std::slice::from_ref(record), dane.ttl)
|
||||
.await?;
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -47,11 +47,10 @@ fn decode_tsig_key(raw: &[u8]) -> Result<Vec<u8>> {
|
||||
let trimmed: Vec<u8> = raw.iter().copied().filter(|b| !b.is_ascii_whitespace()).collect();
|
||||
|
||||
// Try standard base64 first, then URL-safe
|
||||
if let Ok(decoded) = base64::engine::general_purpose::STANDARD.decode(&trimmed) {
|
||||
if !decoded.is_empty() {
|
||||
if let Ok(decoded) = base64::engine::general_purpose::STANDARD.decode(&trimmed)
|
||||
&& !decoded.is_empty() {
|
||||
return Ok(decoded);
|
||||
}
|
||||
}
|
||||
|
||||
// If it doesn't decode as base64, assume it's already raw binary
|
||||
Ok(raw.to_vec())
|
||||
|
||||
+6
-9
@@ -103,11 +103,10 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
fn print_status(config: &config::Config, name_filter: Option<&str>) {
|
||||
for cert_config in &config.certificates {
|
||||
if let Some(filter) = name_filter {
|
||||
if cert_config.name != filter {
|
||||
if let Some(filter) = name_filter
|
||||
&& cert_config.name != filter {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
println!("Certificate: {}", cert_config.name);
|
||||
println!(" Domains: {}", cert_config.domains.join(", "));
|
||||
@@ -149,11 +148,10 @@ async fn dane_publish(
|
||||
dry_run: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
for cert_config in &config.certificates {
|
||||
if let Some(filter) = name_filter {
|
||||
if cert_config.name != filter {
|
||||
if let Some(filter) = name_filter
|
||||
&& cert_config.name != filter {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if cert_config.dane.is_empty() {
|
||||
continue;
|
||||
@@ -196,11 +194,10 @@ async fn dane_check(
|
||||
name_filter: Option<&str>,
|
||||
) -> anyhow::Result<()> {
|
||||
for cert_config in &config.certificates {
|
||||
if let Some(filter) = name_filter {
|
||||
if cert_config.name != filter {
|
||||
if let Some(filter) = name_filter
|
||||
&& cert_config.name != filter {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if cert_config.dane.is_empty() {
|
||||
continue;
|
||||
|
||||
+4
-6
@@ -28,11 +28,10 @@ pub async fn run(
|
||||
let acme = AcmeClient::new(&config.acme).await?;
|
||||
|
||||
for cert_config in &config.certificates {
|
||||
if let Some(filter) = name_filter {
|
||||
if cert_config.name != filter {
|
||||
if let Some(filter) = name_filter
|
||||
&& cert_config.name != filter {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
match renew_certificate(config, &acme, cert_config, &mut state, state_dir, force, dry_run)
|
||||
.await
|
||||
@@ -83,8 +82,8 @@ async fn renew_certificate(
|
||||
}
|
||||
|
||||
// Check if existing certificate needs renewal
|
||||
if !force {
|
||||
if let Ok(cert) = CertInfo::load(&cert_config.cert_path) {
|
||||
if !force
|
||||
&& let Ok(cert) = CertInfo::load(&cert_config.cert_path) {
|
||||
let days = cert.days_until_expiry();
|
||||
if !cert.expires_within_days(cert_config.renew_before_days) {
|
||||
tracing::info!(
|
||||
@@ -101,7 +100,6 @@ async fn renew_certificate(
|
||||
);
|
||||
}
|
||||
// If cert doesn't exist or can't be parsed, proceed with issuance
|
||||
}
|
||||
|
||||
// Determine key pair
|
||||
let key = if let Some(pending) = state.pending_rotations.remove(&cert_config.name) {
|
||||
|
||||
Reference in New Issue
Block a user