Releases: haruspexsystems/Ducks-in-a-Row
Release list
Ducks in a Row 0.10.0-beta.1
This is a beta. The installer is not code signed yet, so Windows SmartScreen and
Microsoft Defender will warn you when you run it. Verify the download against
the SHA256 checksum on the release page. A signed 1.0 will follow this beta.
Read the Known Issues section at the foot of these notes before installing.
Verified on Windows Server 2019 and Windows Server 2025. Not verified on
Windows Server 2022 in this release, and Server 2022 has a servicing floor
that did not exist before; see the .NET 10 entry under Changed.
Added
-
A persistent way to reach the project, at the foot of every dashboard page
and of the setup wizard (#242). The product collects no telemetry, so every
word we get back is one an operator chose to send, which makes it our own
problem if the way to send it is hard to find. It was: the only in app
feedback link sat on the Settings page, one of four tabs, and GitHub
Discussions was named in the support documentation but linked nowhere in the
interface at all. The footer now carries both. The setup wizard carries it
too, deliberately, because an operator who gives up partway through setup is
the one we can least afford to lose and the one no other channel will ever
hear from. Nothing about this sends anything: the feedback link opens a draft
in the operator's own mail client, with the subject filled in and the body
left alone so nothing the app knows rides along uninvited, and the
Discussions link is an ordinary navigation the operator chooses to make,
carryingrel="noopener noreferrer"so GitHub is not even told where the
click came from. The Privacy section of the README is unchanged and stays
true word for word. -
An Alerts card on the Settings page, so the alerting engine is finally visible
(#161). The product shipped complete expiry monitoring, email and webhook
notifiers, and an alert history table, and the dashboard referenced none of
it, so an operator could not find out whether alerting was on, what thresholds
were in force, who was being told, or whether sending had been failing. The
card shows all of that plus the most recent alerts, with failures and their
error text called out, and it says plainly when monitoring is switched off or
when monitoring is on with nothing configured to send over, which is the state
a default install is in. The card also has a Send a test button, which delivers
over every configured channel and reports per channel success or failure,
because SMTP fails quietly and an alerting system nobody has seen work is one
nobody should trust. The test is unmistakable at both ends: the email subject
leads with[Ducks in a Row TEST]and says on its first line that no
certificate is expiring, and the webhook payload is the distincttest.alert
event carryingtest: trueand no certificate list. It goes through the same
signing path as a real alert, so it proves the real path rather than a
shortcut. It writes nothing to the alert history, deliberately: that table has
no way to mark a row as a test, and a test row would consume a real
certificate's slot in the unique index and permanently suppress its actual
warning. Roughly a minute of cooldown sits between tests, shared across
everyone signed in. -
Alert configuration is now writable from the Settings page (#162). It could
previously only be changed by hand editingappsettings.jsonon the server,
which is why the card above named that file in four places. Expiry monitoring,
the check interval, the warning thresholds, the SMTP relay host, the sender
address and the recipient list are all editable and saved through the settings
overlay. The load bearing part is not the endpoint but how a saved value is
applied: .NET flattens a JSON array into indexed keys and merges one index at
a time, so an overlay saving two thresholds over the four the product ships
would have yielded four, silently, with every value positive, distinct and
correctly ordered. Arrays are therefore replaced wholesale rather than merged. -
The whole SMTP transport is configurable from the same card (PR #252). The send
path always supported the port, transport security and authentication; the
configuration plumbing stopped at three fields, which left an operator who
needed a nonstandard port or a credential editing a file on the server for a
channel the dashboard otherwise owns. Port, an explicit TLS mode (none,
STARTTLS, implicit), username, password and sender display name are now part
of the writable set. TLS became a choice instead of a derivation: with no mode
stored the old rule based on the port still applies, so an install configured
before the mode existed keeps exactly the behaviour it had, and the card always
shows the mode a send would actually use. The password is write only end to
end. It is protected with the Data Protection keyring before it reaches the
store, and no response, list, log line or error body ever carries it in any
form, ciphertext included. A save that does not mention the password carries
the stored one forward, because every save rewrites the whole alert block.
The webhook block stays file only. -
ACME device attestation (
device-attest-01, draft-ietf-acme-device-attest-08)
for issuing to hardware attested devices that present apermanent-identifier
instead of adnsname (#139 to #146). Administration lives in a device
attestation card on the ACME dashboard tab, and the profiles, allowlist, and
trust anchors are stored in the database, so every change hot applies to in
flight orders without a restart. Apple is the only attestation format in this
release; the verifier is a plugin registry keyed on the CBOR format string,
and TPM and hardware module formats are deferred. The feature is off by
default and fails closed: a template with no enabled device attestation
profile does not offerdevice-attest-01at all, so a device order is refused
asunsupportedIdentifierexactly as if the feature were absent. An allowlist
gates which devices may enrol and an empty allowlist issues to nobody. The
gate is re-checked at new order, at challenge validation, and at finalize,
each writing a policy audit row the dashboard labels as blocked by the device
attestation policy. The attested public key must equal the CSR public key, any
dnsSAN on a device order is refused, and the Apple root is embedded and
pinned, with custom trust anchors allowed only as additions that can never
shadow or replace it. Documented in docs/device-attestation.md. -
Automatic renewal of the server's own TLS certificate (#105). The wizard
enrols a TLS certificate for the host from the connected CA, but nothing
renewed it, so at the end of its validity the host fell back to the self
signed certificate and trust broke for every browser and ACME client at once.
A daily background service now re-enrols the certificate inside a renewal
window, using the same template and computer account path as setup. Renewal
never restarts the host on its own: a successful renewal installs the new
certificate and stages it, and the dashboard carries the pending change behind
an Apply button, which is the announced restart. The window is capped at a
third of the certificate's validity so a short lived template does not renew
on every check, and the server's own certificate is kept out of the product's
expiry alerting. -
Provisioning the server TLS certificate from the Settings page (#106). Once
setup completes the wizard's one click enrolment is locked, so an installed
instance previously had no way to provision or re-provision its certificate
and the certificate warning was inert. The Settings page now offers a Provision
certificate action on a host that never enrolled one, sharing the same enrol
and restart flow as renewal, and the external URL certificate warning links
straight to it. -
Dashboard revocation scope modes (#262). Which certificates the dashboard will
revoke is now an administrator choice:ducks-managed(the default),custom
with a selected template list, orall. Every mode sits under the TLS
capability ceiling described below and none of them can widen it. A status file
written before the setting existed reads asducks-managedwith an empty list,
so an upgraded install starts narrow rather than wide. Ducks managed is a
union: a certificate this product issued over ACME, or one whose template is in
the enabled set. The setting is read fresh on each decision, so a change
applies without a restart, and the startup log reports the active mode. ACME
revoke-certis deliberately exempt: a client revoking its own certificate
keeps its RFC 8555 authorization and must never wait on a dashboard setting,
because that path is how a key compromise gets answered. -
Private range egress blocking for challenge validation (#102): one setting,
Certus:Acme:ChallengeValidation:BlockPrivateRanges, adds the RFC 1918
ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to the HTTP-01 and
TLS-ALPN-01 egress block list without hand listing CIDRs. Off by default,
because an internal CA usually validates hosts on exactly these ranges; the
new hardening guide (docs/hardening.md) documents that tradeoff and the
AdditionalBlockedCidrsrecipe for anything else, carrier grade NAT for
example. With the flag on, an order for a private IP literal is refused at
order time and a name resolving to a private address fails validation as a
policy rejection, not a retried transport error. -
Optional AD principal link on EAB credentials (#132): a credential can
record which directory account (user, computer, or group) it was issued
to, picked through a debounced type ahead over Active Directory an...
Ducks in a Row 0.9.0-beta.1
This section becomes the 0.9 beta, the first public release, once testing
wraps up. It ships unsigned: Haruspex Systems B.V. is still being set up, so a
code signing certificate is not available yet. A signed 1.0 follows this beta.
Added
- ACME server (RFC 8555) that proxies certificate enrolment to Active Directory
Certificate Services. - A directory per ADCS template at
/acme/{template}/directory. - HTTP-01, DNS-01, and TLS-ALPN-01 challenge validation.
- React dashboard showing the full certificate inventory read from the ADCS CA
database. - Expiry monitoring with email (SMTP) and webhook alerts.
- Guided, browser based setup wizard that discovers the CAs published in Active
Directory, live tests the connection, applies the configuration, and restarts
the service to load it. - Windows Integrated Authentication on the dashboard, gated to a configured
administrator group. - MSI installer and Windows service for production deployment, with a data
folder prompt (also settable unattended viaDATAFOLDER=). - EF Core schema migrations: existing databases upgrade in place at service
start; databases from before migrations were introduced are adopted when
their schema matches, otherwise startup fails with a documented reset. - Certificate revocation tracking: a dashboard tile and filtered view for
revoked certificates, with the revocation date and reason shown whether the
certificate was revoked through ACME or directly on the CA console. - One click TLS certificate enrollment for the server itself during setup,
issued from your own CA, so the dashboard and ACME clients trust the
connection without a manual certificate. - The setup wizard checks each certificate template for ACME readiness and
explains any issue, restricts the list to templates that will actually
work, and resumes where you left off if interrupted partway through. - Change the external URL from the dashboard Settings page any time after
setup, without hand editing configuration files. - Manual certificate renewal and CA certificate chain download from the
dashboard. - On demand inventory sync: a Refresh button, plus an automatic sync right
after any issuance or revocation, so the dashboard catches up in seconds
rather than waiting for the next scheduled cycle.
Changed
-
Default sync interval lowered from 15 to 5 minutes, so a certificate
revoked directly on the CA console appears on the dashboard within about
five minutes instead of up to sixteen. -
The Fleet Health score reads "No certificates yet" rather than a
misleading 100% healthy before anything has been issued. -
Dashboard mascot and browser tab icon updated to the duck knight artwork.
-
Clean break rename of everything user visible from Certus to Ducks in a
Row: install folderC:\Program Files\Ducks in a Row, data folder
C:\ProgramData\Ducks in a Row, Windows serviceDucksInARow, executable
DucksInARow.Service.exe, databaseducks.db, log filesducks-*.log,
installerDucks-in-a-Row.msi. Existing pre release installs are not
migrated: uninstall the old product, install the new MSI, and delete the old
C:\ProgramData\Certusfolder when you no longer need it. -
An empty CA connection string no longer falls back to the mock CA. The
service starts unconfigured (CA operations answer 503 until the setup wizard
connects a CA); the mock now requires the explicitCertus:UseMockCa=true
and shows a banner in the dashboard. -
Same version rebuilds of the MSI now replace the installed product instead
of installing beside it. Installing the new MSI also removes stacked
duplicate installs from earlier builds and stops the orphaned service they
left behind; uninstall reliably stops and removes the service again.